将事件分配给在运行时动态创建的VCL控件

时间:2018-03-01 00:22:53

标签: c++ c++builder c++builder-6

我尝试在运行时创建动态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);
}

1 个答案:

答案 0 :(得分:0)

VCL事件处理程序预期是一个类的非静态成员。您的OnTimer处理程序不是类成员,而是一个自由浮动函数(命名空间并不重要)。

正确解决此问题的方法是为OnTimer事件处理程序创建一个类,然后将该类与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);
}

话虽如此,实际上还有一种替代方法,可以使用System::TMethod结构将自由浮动函数用作您想要的VCL事件处理程序:

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);
}