1. Акция на весь декабрь! Получай оплату х2 за уникальные статьи, объемом от 200 слов, если в заголовке темы и теле статьи присутствует слово Python
    Скрыть объявление

Создание пользовательских контролов

Тема в разделе ".NET", создана пользователем iceheart, 18 дек 2007.

Статус темы:
Закрыта.
  1. iceheart

    iceheart Гость

    Здравствуйте.

    Я только-только начинаю переходить на .NET, раньше писал под VCL или чистым API. С непривычки к новой технологии постоянно спотыкаюсь на всяких пустяках... Пишу проект под С++, в нём нужно использовать собственный элемент управления. Так уж получается, что написать этот элемент с нуля будет гораздо проще, чем лепить из готовых кнопочек...

    Создал я в солюшене отдельный проект, в него добавил класс-наследник Windows::Forms::Control'а. Переопределил в нём функцию OnPaint, пока чтобы просто прямоугольник рисовала по границам контрола. Теперь хотелось бы положить контрол на форму в главном проекте, а не получается. :( :(
    Ссылку в свойствах главного проекта на проект с контролом добавил, билд ордер настроил как нужно. Но контрол на панели инструментов не появляется, хотя по доке должен был там показаться автоматически. Пробовал добавить вручную, вписав в класс соответствующий объект и прописав свойства в InitializeComponent. Проект компилируется, но на форме контрол не видать, как в дизайнере, так и во время выполнения (то есть метод OnPaint не вызывается или же не работает).

    Подскажите, что надо сделать, чтобы контрол появился в тулбоксе?
    Нужно ли что-то делать с контролом, чтобы правильно выполнялась отрисовка?
    И наконец, как правильно настроить отображение контрола в режиме дизайна?
    Если у кото-нибудь найдётся пример готового контрола под С++, буду очень благодарен.

    А вот теперешний сорец того самого контрола:
    Код (Text):
    #pragma once

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Diagnostics;
    using namespace System::Windows::Forms;

    namespace ts_controls {

    /// <summary>
    /// Summary for tcTape
    /// </summary>
    public ref class tcTape : public System::Windows::Forms::Control
    {
    public:
    tcTape(void)
    {
    InitializeComponent();
    SetStyle( ControlStyles::UserPaint, true );
    }
    tcTape(System::ComponentModel::IContainer ^container)
    {
    /// <summary>
    /// Required for Windows.Forms Class Composition Designer support
    /// </summary>

    container->Add(this);
    InitializeComponent();
    }

    protected:
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    ~tcTape()
    {
    if (components)
    {
    delete components;
    }
    }

    virtual void OnPaint( PaintEventArgs ^e )override
    {
    System::Drawing::Pen^ pen = gcnew System::Drawing::Pen( System::Drawing::Color::Black );
    e->Graphics->DrawRectangle( pen, 0, 0, Width, Height );
    }

    private:
    /// <summary>
    /// Required designer variable.
    /// </summary>
    System::ComponentModel::Container ^components;

    #pragma region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    void InitializeComponent(void)
    {
    components = gcnew System::ComponentModel::Container();
    }
    #pragma endregion
    };
    }
     
  2. Pasha

    Pasha Гость

    Для: iceheart
    Надо наследоваться от System::Windows::Forms::UserControl, тогда твой контрол будет виден в тулбоксе. Все остальное у тебя правильно.
    А еще лучше создать проект с типом Windows Froms Control Library, получишь готовый шаблон. И добавлять новые контролы через Add New/User Control.
     
  3. iceheart

    iceheart Гость

    Pasha:
    Очень благодарю за скорый ответ. Теоретически, срок сдачи проекта - завтра :(
    Я так и сделал, только шаблон не использовал, а просто пока оставил валяться (как образец), добавил новый айтем Component Class. Сейчас заменил его на User Control. Не помогает.. Добавлено: кстати, тот контрол, что был в проекте по дефолту, ts_controlsControl, тоже не видно в тулбоксе.
    Не уверен, что это что-то меняет. В MSDN написано, что оба этих класса нужны, чтобы делать пользовательские элементы управления, а разница между ними в том, что на UserControl можно лепить готовые контролы и компоненты, а на Control нельзя, он должен сам обрабатывать все события. Сейчас попробовал поставить UserControl, тоже не помогло...
     
  4. Pasha

    Pasha Гость

    Для: iceheart
    Может у тебя со студией глюки? Вот, смотри в аттаче что моя нагенерила.
     

    Вложения:

  5. iceheart

    iceheart Гость

    Получилось! Получилось! Получилось! :blink:
    Мне удалось добавить контрол в форму, вручную отредактировав класс формы и метод InitializeComponent. После этого контрол стал виден в дизайнере и при запуске проги, хотя в тулбоксе так и не появился:
    Код (Text):
        public ref class Form1 : public System::Windows::Forms::Form
    {
    .   .   .
    private: ts_controls::tcTape^ tape;
    .   .   .
    void InitializeComponent(void)
    {
    .   .   .
    this->tape = (gcnew ts_controls::tcTape(this->components));
    .   .   .
    //
    // tape
    //
    this->tape->Location = System::Drawing::Point(58, 75);
    this->tape->Name = L"tape";
    this->tape->Size = System::Drawing::Size(370, 60);
    .   .   .
    //
    // Form1
    //
    this->Controls->Add(this->tape);
    .   .   .
    }
    .   .   .
    }
    После этого контрол даже начал обрабатывать некоторые события (например Resize), но вот событие Paint он не обрабатывал, так внешне контрол напоминал "дыру" в форме. Пробовал устанавливать стиль контрола UserPaint, не помогло:
    Код (Text):
    SetStyle( ControlStyles::UserPaint, true );
    Потом попробовал изменить способ обработки события Paint. Раньше я это делал через переопределение метода OnPaint:
    Код (Text):
    virtual void OnPaint( PaintEventArgs ^e )override
    {
    .   .   .
    }
    Теперь вмето этого метода использую делегаты, и всё работает:
    Код (Text):
    void Init()
    {
    .   .   .
    Paint += gcnew PaintEventHandler( this, &tcTape::OnPaint );
    .   .   .
    }

    void OnPaint( Object ^o, PaintEventArgs ^e )
    {
    .   .   .
    }
    Осталось неясным только почему не работало через переопределение? В умной книжке написано, что так тоже можно делать...
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей