if (Key != 0) FModified = true; TEdit::KeyPress (Key);
}
Эта функция сначала заменяет недопустимые символы нулевыми. Если символ допустимый, то задается значение true полю свойства FModified. В
конце вызывается метод KeyPress родительского класса.
Можете скомпилировать и протестировать полученный компонент.
Удобно воспользоваться для параллельной разработки компонента и его теста Менеджером Проектов, включив в группу проекта пакет My.bpi и
приложение Test. Форма содержит компонент EditLetNum, кнопку Button с
надписью Clear (при ее нажатии выполняется метод Clear), метку Labe1, в
которой отображается значейие свойства Modified компонента
EditLetNum1, и три индикатора типа TCheckBox. Два из них (назовите их
CBNum и CBLet) указывают допустимость ввода цифр и букв. О третьем речь пойдет в следующем разделе.
Обработчик события OnCreate формы может иметь вид: void __fastcall TForml::FormCreate(TObject *Sender)
{
if (EditLetNuml->Modified) Label1->Caption = "Modified = true";
else Label1->Caption = "Modified = false";
}
Этот обработчик заносит в метку Label1 сообщение о текущем значении свойства Modified.
В обработчике события OnKeyUp компонента EditLetNum напишите оператор:
FormCreate(Sender);
Этот оператор вызывает тот же приведенный выше обработчик события
OnCreate формы для отображения текущего значения Modified.
Обработчик события OnClick индикатора CBNum может иметь вид:
EditLetNum1->EnableNum = CBNum->Checked;
CBLet->Checked = EditLetNum1->EnableLet;
EditLetNum1->SetFocus();
Первый оператор этого обработчика устанавливает значение параметра
EnableNum в зависимости от состояния индикатора CBNum. Второй оператор устанавливает состояние индикатора CBLet равным значению параметра EnableLet. Это надо, поскольку если, например, сбрасывается в false значение параметра EnableNum, а значение параметра EnableLet в
этот момент тоже было равно false, то компонент EditLetNum1 установит значение EnableLet равным true. И надо, чтобы это новое значение отобразилось в индикаторе CBLet.
Аналогично может выглядеть обработчик события OnClick индикатора
CBLet:
EditLetNum1->EnableLet = CBLet->Checked;
CBNum->Checked = EditLetNum1->EnableNum;
EditLetNum1->SetFocus();
В обработчике события OnClick кнопки Clear напишите: EditLetNum1->Clear();
FormCreate(Sender);
Эти операторы проверят работу введенного вами метода Clear и
отобразят на экране изменение значения свойства Modified.
Оттранслируйте компонент. В вашем тестовом приложении установите свойства EnableNum и EnableLet в соответствии с тем, какие исходные установки индикаторов CBNum и CBLet вы задали.
Активизируйте в окне Менеджера Проектов вершину вашего тестового приложения, запустите его на выполнение m проверьте в работе при различных значениях свойств EnableNum и EnableLet.
Если в написанных файлах вашего нового компонента что-то не в порядке, вам может захотеться ввести в файл реализации компонента какие-то точки прерывания. В Windows 2000/ХР и NT проблем не
возникнет. При запуске теста на выполнение точки прерывания, введен-
ные в файл компонента, окажутся недоступными. А если вы активизируете в окне Менеджера Проектов вершину пакета и попробуете выполнить его, то получите сообщение: «Cannot debug project unless a host application is defined. Use Run | Parameters… dialog box». Это означает, что вы сначала с помощью команды Run | Parameters должны определить хост
— тестирующее приложение. Выполните эту команду, предварительно активизировав в окне Менеджера Проектов вершину пакета. Перед вами откроется диалог. В верхнем окошке вы должны указать файл тестирующего приложения. Для этого можете воспользоваться кнопкой:
поиска Browse. Кнопка Load позволяет вам загрузить тестирующее приложение и начать его выполнение по шагам. Затем можете запускать выполнение обычной командой Run | Run (F9). Впрочем, после того, как вы один раз задали хост для пакета в окне, вы можете в дальнейшем запускать пакет на выполнение обычным образом.
В нашем примере требуется ввести событие OnClear, происходящее в момент очистки окна методом Clear. В C++Builder событие — это просто специально свойство, являющееся указателем функции. Тип обобщенного указателя на функцию, которой передается один параметр типа
TComponent (обычно this), - TNotifyEvent. Подобный тип используется в
C++Builder для событий типа OnClick и многих других, которые передают в обработчик только один параметр — TObject *Sender. Подойдет этот тип и нам для события OnClear.
В этом случае объявления нашего события могут иметь вид: private:
…
iTNotifyEvent FOnClear;
…
__published:
…
__property TNotifyEvent OnClear = (read=FOnClear, write=FOnClear} ;
Эти объявления создают поле FOnClear типа TNotifyEvent,
соответствующее событию. А само событие объявляется точно так же, как любое свойство. Только в read и write записываются не функции чтения и записи, а само поле.
Остается только вызвать в нужный момент обработчик события пользователя, если пользователь его предусмотрел. Проверка, имеется ли обработчик пользователя, осуществляется проверкой соответствующего события как булевой величины, возвращающей true, если пользователь предусмотрел свой обработчик. В нашем случае эта проверка и вызов обработчика пользователя осуществляется добавлением в начало написанной ранее процедуры метода Clear оператора:
if (OnClear) OnClear(this);
который вызывает обработчик пользователя OnClear.
Внесите указанные изменения в файлы компонента, откомпилируйте их, выделите на форме тестового приложения компонент EditLetNum1 и
посмотрите страницу событий в Инспекторе Объектов. Вы увидите, что в списке его событий появилось событие OnClear. Дважды щелкните на его правом окне и вы увидите в тексте модуля заготовку для обработчика этого события:
void __fastcall TForm1::EditLetNum1Clear(TObject *Sender)
{
}
Внесите в этот обработчик какой-нибудь оператор, который бы отображал на экране факт свершения этого события, например:
ShowMessage("Событие OnClear");
Проверьте ваше тестовое приложение в работе.
Мы рассмотрели простейший вариант задания события типа
TNotifyEvent. Попробуем несколько усложнить это событие. Пусть мы будем передавать в это событие параметр CanClear, который по
умолчанию равен true, что будет означать разрешение очистить текст окна редактирования. Но предоставим пользователю возможность в своем обработчике события задать этому параметру значение false, что будет означать отказ от очистки.
Чтобы решить эту задачу, вам надо объявить новый тип события. Это объявление делается с помощью ключевого слова __closure. Пусть,
например, вы хотите дать вводимому новому типу событий имя TClear.
Тогда объявление указателя на этот тип может иметь вид: typedef void __fastcall (__closure *TClear)
(System::TObject *Sender, bool& CanClear);
Приведенный код объявляет указатель на функцию, принимающую два параметра: традиционный для всех обработчиков параметр Sender и булев параметр CanClear, который пользователь сможет изменять.
Приведенное выше объявление типа должно помещаться перед описанием класса. Тогда в объявлениях свойства и его поля надо ссылаться на этот тип, следующим образом изменив соответствующие операторы:
private:
…
TClear FOnClear;
…
__property TClear OnClear = {read=FOnClear, write=FOnClear};
Осталось изменить метод Clear так, чтобы в нем учитывался новый параметр CanClear:
void fastcall TEditLetNum::Clear()
{