• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

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

  • Автор темы iceheart
  • Дата начала
Статус
Закрыто для дальнейших ответов.
I

iceheart

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

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

Создал я в солюшене отдельный проект, в него добавил класс-наследник Windows::Forms::Control'а. Переопределил в нём функцию OnPaint, пока чтобы просто прямоугольник рисовала по границам контрола. Теперь хотелось бы положить контрол на форму в главном проекте, а не получается. :( :(
Ссылку в свойствах главного проекта на проект с контролом добавил, билд ордер настроил как нужно. Но контрол на панели инструментов не появляется, хотя по link removed должен был там показаться автоматически. Пробовал добавить вручную, вписав в класс соответствующий объект и прописав свойства в 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
};
}
 
P

Pasha

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

iceheart

Pasha:
Очень благодарю за скорый ответ. Теоретически, срок сдачи проекта - завтра :(
А еще лучше создать проект с типом Windows Froms Control Library, получишь готовый шаблон. И добавлять новые контролы через Add New/User Control.
Я так и сделал, только шаблон не использовал, а просто пока оставил валяться (как образец), добавил новый айтем Component Class. Сейчас заменил его на User Control. Не помогает.. Добавлено: кстати, тот контрол, что был в проекте по дефолту, ts_controlsControl, тоже не видно в тулбоксе.
Надо наследоваться от System::Windows::Forms::UserControl, тогда твой контрол будет виден в тулбоксе.
Не уверен, что это что-то меняет. В MSDN написано, что оба этих класса нужны, чтобы делать пользовательские элементы управления, а разница между ними в том, что на UserControl можно лепить готовые контролы и компоненты, а на Control нельзя, он должен сам обрабатывать все события. Сейчас попробовал поставить UserControl, тоже не помогло...
 
P

Pasha

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

Вложения

  • SampleControlsLibrary.rar
    145,1 КБ · Просмотры: 154
I

iceheart

Получилось! Получилось! Получилось! :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 )
{
.	.	.
}
Осталось неясным только почему не работало через переопределение? В умной книжке написано, что так тоже можно делать...
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!