将事件分配给在运行时动态创建的VCL控件 [英] Assigning events to a VCL control created dynamically at runtime

查看:75
本文介绍了将事件分配给在运行时动态创建的VCL控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在运行时创建动态VCL控件,并为其分配事件处理程序。



我想我已经尽了一切努力使其正常工作。 ,但不能(我尝试的所有东西都会产生不同的错误)。



如果您可以在下面的代码中填写问号,那将会很有帮助! p>

哦,如果您想知道为什么它是在命名空间而不是 class ,这是因为这实际上是我一直添加到的大型库。当我将其更改为时,您会认为这很好,但是,不会,它会产生大量的怪异错误。



test.h

 命名空间TestSpace {
TTimer *时间;
AnsiString文件;
void __fastcall MyFunc(AnsiString f);
?OnTimer事件的声明?
}

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事件处理程序是预期成为课程的非静态成员。您的 OnTimer 处理程序不是类成员,而是一个自由浮动的函数(名称空间并不重要)。



解决此问题的正确方法是为您的 OnTimer 事件处理程序创建一个类,然后将该实例与<$一起实例化。 c $ c> TTimer ,例如:



test.h

 命名空间TestSpace {
class TimerEvents {
public:
void __fastcall TimerElapsed(TObject * Sender);
};
TTimer *时间;
TimerEvents time_events;
AnsiString文件;
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){
//'这是TimerEvents对象
//'Sender'是TTimer对象
TestSpace :: time-> Enabled = false;
DeleteFile(TestSpace :: file);
}

话虽这么说,实际上还有一个替代通过使用 System :: TMethod 结构:



test.h

 命名空间TestSpace {
TTimer * time;
AnsiString文件;
void __fastcall MyFunc(AnsiString f);
//注意:必须添加一个显式的void *参数才能接收
// //应该是一个类'this'指针...
void __fastcall TimerElapsed(void * This,TObject *发件人);
}

test.cpp

  void __fastcall TestSpace :: MyFunc(AnsiString f){
TestSpace :: file = f;
TMethod m;
m.Data = ...; //无论您想传递给 This参数的任何内容,甚至为null ...
m.Code =& TestSpace :: TimerElapsed;
TestSpace :: time-> OnTimer = reinterpret_cast< TNotifyEvent&>(m);
TestSpace :: time-> Enabled = true;
}

void __fastcall TestSpace :: TimerElapsed(void * This,TObject * Sender){
//'这是您分配给TMethod :: Data $ b $的任何内容b //'发件人'是TTimer对象
TestSpace :: time-> Enabled = false;
DeleteFile(TestSpace :: file);
}


I'm trying to create a dynamic VCL control at runtime and assign an event handler to it.

I think I've tried everything to get this to work, but cannot (everything I try generates different errors).

If you could help fill in the question marks in the code below, it would be of great help!

Oh, in case you're wondering why it's in a namespace instead of a class, it's because this is actually a large library that I just kept adding to. When I change it to a class, you'd think it would be fine, but no, it generates a gazillion weird errors.

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

解决方案

A VCL event handler is expected to be a non-static member of a class. Your OnTimer handler is not a class member, it is a free-floating function instead (the namespace is not important).

The correct way to solve this issue is to create a class for your OnTimer event handler, and then instantiate that class alongside the TTimer, eg:

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

That being said, there is actually an alternative way to use a free-floating function as a VCL event handler like you want, by using the System::TMethod struct:

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控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆