class TMyClass; //Предварительное объявление класса
typedef void __fastcall (__closure *TMyEvent) (TMyClass* Sender);
class TMyClass // Реализация класса
{
private:
TMyEvent fMyEvent; // Событие
protected:
virtual void DoMyEvent (void) // Генератор
{if (fMyEvent) fMyEvent (this);}
};
События в простом классе (не в компоненте)
То есть, если я пишу компонент, то ясное дело, могу создавать в нем события. А вот если у меня просто класс, который мной написан и совершенно не нужно лепить его на форму в виде контрольчика. Можно ли для класса, который просто объявлен в модуле, описать событие, или что-то подобное событию, чтобы класс генерировал его в самые разные моменты времени, а основная программа могла обработать это событие?
Создаётся тип, аналогичный событию TNotifyEvent (обязательно со словом __closure). Только нужно изменить тип указателя Sender класс создаваемых объектов (или базовый)
Код:
Цитата: el scorpio
Да.
Создаётся тип, аналогичный событию TNotifyEvent (обязательно со словом __closure). Только нужно изменить тип указателя Sender класс создаваемых объектов (или базовый)
Создаётся тип, аналогичный событию TNotifyEvent (обязательно со словом __closure). Только нужно изменить тип указателя Sender класс создаваемых объектов (или базовый)
Код:
class TMyClass; //Предварительное объявление класса
typedef void __fastcall (__closure *TMyEvent) (TMyClass* Sender);
typedef void __fastcall (__closure *TMyEvent) (TMyClass* Sender);
Если можно поподробнее, что значит "аналогичный TNotifyEvent". Как именно надо реализовать класс событий TMyEvent?
Цитата: Andreika
Можно ли создавать события в обычном классе, который объявлен в модуле, а не в компоненте VCL?
Такое в VCL сплошь и рядом. Посмотри, например, как сделано в TStringList.
typedef void __fastcall (__closure *TNotifyEvent)(TObject* Sender); где
__closure - слово, означающее, что объект этого типа - структура с двумя полями (адрес объекта, адрес метода)
Sender - параметр метода - указатель на объект, сгенерировавший событие. Здесь он имеет тип TObject - базовый класс для всех VCL объектов.
В зависимости от параметров события, назначается его обработчик - метод другого объекта. Если генератором события будут объекты, не производные от TObject, значит нужно объявить другой тип события (по образу и подобию TNotifyEvent), используя в качестве Sender указатель на объект своего класса.
Вот простенький пример другого типа (можно с Sender-ом, можно без-здесь без)
Header класса
Код:
typedef void __fastcall (__closure *TEventInfoMessage)(AnsiString Info,int Count);
class MyClass
{
private:
TEventInfoMessage FOnEventInfoMessage;
protected:
virtual void __fastcall EventInfoMessage(AnsiString Info,int Count);
public:
...
void __fastcall ReadAll();
__property TEventInfoMessage
onEventInfoMessage={read=FOnEventInfoMessage,write=FOnEventInfoMessage};
};
class MyClass
{
private:
TEventInfoMessage FOnEventInfoMessage;
protected:
virtual void __fastcall EventInfoMessage(AnsiString Info,int Count);
public:
...
void __fastcall ReadAll();
__property TEventInfoMessage
onEventInfoMessage={read=FOnEventInfoMessage,write=FOnEventInfoMessage};
};
Cpp класса
Код:
void __fastcall MyClass::EventInfoMessage(AnsiString Info,int Count)
{
if(FOnEventInfoMessage) FOnEventInfoMessage(Info,Count);
}
void __fastcall MyClass::ReadAll()
{
...
while(...)
{
...
EventInfoMessage(Info,Count);
...
}
}
{
if(FOnEventInfoMessage) FOnEventInfoMessage(Info,Count);
}
void __fastcall MyClass::ReadAll()
{
...
while(...)
{
...
EventInfoMessage(Info,Count);
...
}
}
Cpp главной формы
Код:
void __fastcall TMainForm::FormActivate(TObject *Sender)
{
MyClass *myobject=new MyClass();
myobject->onEventInfoMessage=EventInfoMessage;
myobject->ReadAll();
}
void __fastcall TMainForm::EventInfoMessage(AnsiString Info,int Count)
{
if(Info != "") Edit1->Text=Info;
Edit2->Text=AnsiString(Count);
MainForm->Update();
Application->ProcessMessages();
}
{
MyClass *myobject=new MyClass();
myobject->onEventInfoMessage=EventInfoMessage;
myobject->ReadAll();
}
void __fastcall TMainForm::EventInfoMessage(AnsiString Info,int Count)
{
if(Info != "") Edit1->Text=Info;
Edit2->Text=AnsiString(Count);
MainForm->Update();
Application->ProcessMessages();
}
Sender как указатель на объект-"генератор" - параметр необязательный, но такое бывает редко.
Разработка событий предполагает, что обработчик будет использовать адрес "генератора". Например, метод обрабатывает события нескольких компонентов, обращаясь к Sender.