在按钮 OnClick 方法中作为发件人传递什么?

What to pass as a Sender in a button OnClick method?

我有一个动态创建按钮的函数

void createBtn(News obj,TForm *Form1){
    TButton *spam = new TButton(Form1);
    spam->Parent = newsCard;
    spam->Position->X = 280;
    spam->Position->Y = 256;
    spam->Text = "Spam";
}

我需要给它分配一个 OnClick 事件,所以我在上面的函数中添加了以下行:

spam->OnClick = spamClick;

spamClick 的代码是:

void __fastcall TForm1::spamClick(TObject *Sender, News obj)
 {
    allUsers[userIndex].spamNews(obj);
    ShowMessage("Done!");
 }

问题是,我需要在行中传递 obj,但该函数需要 2 个参数,即 Senderobj

spam->OnClick = spamClick(obj); // error here

但是不知道要传什么。我试过 Form1spamnewsCard。但是没有任何效果。

我作为 Sender 传递什么?或者,有没有办法将 OnClick 事件分配给 createBtn() 内的按钮?

编辑: class 新闻具有以下定义

class News
{
public:
    News(string, string, string, Dates);
    string title;
    string description;
    Dates date;
    int rate;
    string category;
    vector<Comment> comments;
    int spamCount;
    static int newsCount;
    int newsID;
    int numOfRatedUsers;
};

spamNews 是用户 class 中的一个函数,它将 obj.newsID 推入用户中的向量,然后增加 spamCount。

void user::spamNews(News& obj) {
//check that the news in not already spammed 
    if(!findNews(spammedNews,obj)){  
        spammedNews.push_back(obj.newsID);
        obj.spamCount++;
    }
}

您的第二种方法不起作用,因为您试图先 调用 spamClick(),然后将其 return 值分配给 OnClick 事件.

您的第一种方法是正确的方法,但是您不能向 OnClick 事件处理程序添加参数。

TButton 具有 Tag... 用于保存 user-defined 数据的属性。但是,由于 News 对象不是通过指针传递的,因此 Tag... 属性在这种情况下不是很有用(除非 News 对象保存在 array/list然后可以将其索引存储在 Tag).

否则,我会建议从 TButton 派生一个新的 class 来保存 News 对象,例如:

class TMyButton : public TButton
{
public:
    News NewsObj;

    __fastcall TMyButton(TComponent *Owner, const News &obj)
        : TButton(Owner), NewsObj(obj) {}
};

void TForm1::createBtn(const News &obj)
{
    TMyButton *spam = new TMyButton(this, obj);
    spam->Parent = newsCard;
    spam->Position->X = 280;
    spam->Position->Y = 256;
    spam->Text = _D("Spam");
    spam->OnClick = &spamClick;
}

void __fastcall TForm1::spamClick(TObject *Sender)
{
    MyButton *btn = static_cast<TMyButton*>(Sender);
    allUsers[userIndex].spamNews(btn->NewsObj);
    ShowMessage(_D("Done!"));
}

UPDATE:由于您的 News 对象存储在您正在循环的 vector 中,因此一个更简单的解决方案是通过News 通过 reference 指向 createBtn() 的对象,然后将 pointer 存储到 TButton::Tag 属性,例如:

void TForm1::createBtn(News &obj)
{
    TButton *spam = new TButton(this);
    spam->Parent = newsCard;
    spam->Position->X = 280;
    spam->Position->Y = 256;
    spam->Text = _D("Spam");
    spam->Tag = reinterpret_cast<NativeInt>(&obj);
    spam->OnClick = &spamClick;
}

void __fastcall TForm1::spamClick(TObject *Sender)
{
    TButton *btn = static_cast<TButton*>(Sender);
    News *obj = reinterpret_cast<News*>(btn->Tag);
    allUsers[userIndex].spamNews(*obj);
    ShowMessage(_D("Done!"));
}

或者,使用 TMyButton 后代:

class TMyButton : public TButton
{
public:
    News *NewsObj;

    __fastcall TMyButton(TComponent *Owner)
        : TButton(Owner) {}
};

void TForm1::createBtn(News &obj)
{
    TMyButton *spam = new TMyButton(this);
    spam->Parent = newsCard;
    spam->Position->X = 280;
    spam->Position->Y = 256;
    spam->Text = _D("Spam");
    spam->NewsObj = &obj;
    spam->OnClick = &spamClick;
}

void __fastcall TForm1::spamClick(TObject *Sender)
{
    MyButton *btn = static_cast<TMyButton*>(Sender);
    allUsers[userIndex].spamNews(*(btn->NewsObj));
    ShowMessage(_D("Done!"));
}