1. Наш канал codeby в telegram. Пишем об информационной безопасности, методах защиты информации, о программировании. Не пропускай новости с кодебай, будь в тренде ! Подробнее ...

    Скрыть объявление

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

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

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

    iceheart Гость

    Репутация:
    0
    Здравствуйте.

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

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

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

    А вот теперешний сорец того самого контрола:
    Код:
    #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 Гость

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

    iceheart Гость

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

    Pasha Гость

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

    Вложения:

  5. iceheart

    iceheart Гость

    Репутация:
    0
    Получилось! Получилось! Получилось! :blink:
    Мне удалось добавить контрол в форму, вручную отредактировав класс формы и метод InitializeComponent. После этого контрол стал виден в дизайнере и при запуске проги, хотя в тулбоксе так и не появился:
    Код:
    	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, не помогло:
    Код:
    SetStyle( ControlStyles::UserPaint, true );
    Потом попробовал изменить способ обработки события Paint. Раньше я это делал через переопределение метода OnPaint:
    Код:
    virtual void OnPaint( PaintEventArgs ^e )override
    {
    .	.	.
    }
    Теперь вмето этого метода использую делегаты, и всё работает:
    Код:
    void Init()
    {
    .	.	.
    Paint += gcnew PaintEventHandler( this, &tcTape::OnPaint );
    .	.	.
    }
    
    void OnPaint( Object ^o, PaintEventArgs ^e )
    {
    .	.	.
    }
    Осталось неясным только почему не работало через переопределение? В умной книжке написано, что так тоже можно делать...
     
Загрузка...
Статус темы:
Закрыта.

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