将事件分配给在运行时动态创建的 VCL 控件
Assigning events to a VCL control created dynamically at runtime
我正在尝试在运行时创建动态 VCL 控件并为其分配事件处理程序。
我想我已经尝试了所有方法来让它工作,但不能(我尝试的所有方法都会产生不同的错误)。
如果您能帮忙填写下面代码中的问号,那就太好了!
哦,如果您想知道为什么它在 namespace
而不是 class
中,那是因为这实际上是一个我不断添加的大型库。当我将它更改为 class
时,您会认为它会很好,但不,它会产生大量奇怪的错误。
test.h
namespace TestSpace {
TTimer *time;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
?Declaration for OnTimer event?
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TestSpace::time->OnTimer = ?;
TestSpace::time->Enabled = true;
}
TestSpace::?(TObject* Sender) {
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
VCL 事件处理程序预期 是class 的non-static 成员。您的 OnTimer
处理程序不是 class 成员,而是 free-floating 函数(命名空间并不重要)。
解决此问题的正确方法是为您的OnTimer
事件处理程序创建一个class,然后实例化该class在 TTimer
旁边,例如:
test.h
namespace TestSpace {
class TimerEvents {
public:
void __fastcall TimerElapsed(TObject *Sender);
};
TTimer *time;
TimerEvents time_events;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TestSpace::time->OnTimer = &(time_events.TimerElapsed);
TestSpace::time->Enabled = true;
}
void __fastcall TestSpace::TimerEvents::TimerElapsed(TObject* Sender) {
// 'this' is the TimerEvents object
// 'Sender' is the TTimer object
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
也就是说,实际上有一种 替代方法 可以像您想要的那样使用 free-floating 函数作为 VCL 事件处理程序,方法是使用 System::TMethod
结构:
test.h
namespace TestSpace {
TTimer *time;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
// NOTE: must add an explicit void* parameter to receive
// what is supposed to be a class 'this' pointer...
void __fastcall TimerElapsed(void *This, TObject *Sender);
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TMethod m;
m.Data = ...; // whatever you want to pass to the 'This' parameter, even null...
m.Code = &TestSpace::TimerElapsed;
TestSpace::time->OnTimer = reinterpret_cast<TNotifyEvent&>(m);
TestSpace::time->Enabled = true;
}
void __fastcall TestSpace::TimerElapsed(void *This, TObject* Sender) {
// 'This' is whatever you assigned to TMethod::Data
// 'Sender' is the TTimer object
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
我正在尝试在运行时创建动态 VCL 控件并为其分配事件处理程序。
我想我已经尝试了所有方法来让它工作,但不能(我尝试的所有方法都会产生不同的错误)。
如果您能帮忙填写下面代码中的问号,那就太好了!
哦,如果您想知道为什么它在 namespace
而不是 class
中,那是因为这实际上是一个我不断添加的大型库。当我将它更改为 class
时,您会认为它会很好,但不,它会产生大量奇怪的错误。
test.h
namespace TestSpace {
TTimer *time;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
?Declaration for OnTimer event?
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TestSpace::time->OnTimer = ?;
TestSpace::time->Enabled = true;
}
TestSpace::?(TObject* Sender) {
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
VCL 事件处理程序预期 是class 的non-static 成员。您的 OnTimer
处理程序不是 class 成员,而是 free-floating 函数(命名空间并不重要)。
解决此问题的正确方法是为您的OnTimer
事件处理程序创建一个class,然后实例化该class在 TTimer
旁边,例如:
test.h
namespace TestSpace {
class TimerEvents {
public:
void __fastcall TimerElapsed(TObject *Sender);
};
TTimer *time;
TimerEvents time_events;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TestSpace::time->OnTimer = &(time_events.TimerElapsed);
TestSpace::time->Enabled = true;
}
void __fastcall TestSpace::TimerEvents::TimerElapsed(TObject* Sender) {
// 'this' is the TimerEvents object
// 'Sender' is the TTimer object
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
也就是说,实际上有一种 替代方法 可以像您想要的那样使用 free-floating 函数作为 VCL 事件处理程序,方法是使用 System::TMethod
结构:
test.h
namespace TestSpace {
TTimer *time;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
// NOTE: must add an explicit void* parameter to receive
// what is supposed to be a class 'this' pointer...
void __fastcall TimerElapsed(void *This, TObject *Sender);
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TMethod m;
m.Data = ...; // whatever you want to pass to the 'This' parameter, even null...
m.Code = &TestSpace::TimerElapsed;
TestSpace::time->OnTimer = reinterpret_cast<TNotifyEvent&>(m);
TestSpace::time->Enabled = true;
}
void __fastcall TestSpace::TimerElapsed(void *This, TObject* Sender) {
// 'This' is whatever you assigned to TMethod::Data
// 'Sender' is the TTimer object
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}