Обработчик событий для динамически создаваемого CheckBox

Я написал программу на C++ с использованием Borland C++ Builder 5. Программа динамически создает массив TCheckBox объекты. Я пытался написать OnClick обработчик событий, который определит, какой флажок нажимается, и выполнит некоторые инструкции, основанные на этом. Мой обработчик событий основан на аналогичных публикациях на этом сайте, но я не могу заставить его работать.

Вот (сокращенный) код

// Header declaration
void __fastcall CBoxClick(TObject *Sender); 
// End Header

// CBoxClick function (the event handler)

void __fastcall CBoxClick(TObject *Sender){
    if (dynamic_cast<TCheckBox*>(Sender)!=NULL){
        //Do stuff
    }
    else{
        Form1 -> Debug -> Text = "Object is not a TCheckBox";         
    }
}

void ChkBoxInit(void){
    int i;                                            //Loop counter index
    TCheckBox* ChkBx[NCARDS];                         //Define array of type checkboxes
    for(i = 0; i < NCARDS; i++){                      //Initalize each checkbox
        ChkBx[i] = new TCheckBox(Form1);              //Create a new checkbox
        ChkBx[i] -> Parent = Form1;                   //Define parent of checkbox
        ChkBx[i] -> Tag = i;                          //Set value of Tag to index
        //  Other CheckBox parameters here such as Height, Width, Top, Left, Name are here
        //  Next, call event handler. I've tried the following 2 statements with the comment results
        ChkBx[i] -> OnClick = CBoxClick(ChkBx[i]);    //  Results in E2109: Not an allowed type
        ChkBx[i] -> OnClick = CBoxClick;              /* Alternate try - Results in E2034: Cannot convert
                                                        'void (_fastcall *)(TObject *)' to 
                                                        'void (_fastcall * (_closure )(TObject *))(TObject *)'  */
    }                                                 //End of for loop
}                                                     //End of function

2 ответа

CBoxClick() не является членом вашего класса Form.

В вашем файле cpp компилятор видит его как отдельную функцию. Вот на что жалуется сообщение об ошибке при назначении OnClick событие не выполняется (нестатические методы класса имеют __closure атрибут, нечленов нет).

Удостовериться CBoxClick() объявлен внутри вашего класса Form в заголовочном файле:

class TForm1 : public TForm
{
    ...
public:
    ...
    void __fastcall CBoxClick(TObject *Sender); // <-- add this
    ...
};

А затем измените эту строку в вашем файле cpp:

void __fastcall CBoxClick(TObject *Sender){

На это вместо этого:

void __fastcall TForm1::CBoxClick(TObject *Sender){

А затем измените свое назначение OnClick событие из этого:

ChkBx[i]->OnClick = CBoxClick;

На это вместо (так как ChkBoxInit() само по себе, похоже, не является членом класса Form):

ChkBx[i]->OnClick = Form1->CBoxClick;

Первый синтаксис, который вы пробовали (OnClick = CBoxClick(ChkBx[i]);) просто неправильно, как вы на самом деле звоните CBoxClick() а затем пытается назначить его void вернуть значение OnClickчто, очевидно, не сработает. Вам необходимо назначить адрес CBoxClick() в OnClickи это будет работать только для нестатических методов класса, но не для автономных функций (ну, это МОЖЕТ быть сделано, но для этого требуется другой код, включающий взлом с приведением типа с использованием TMethod структура).

Кроме того, вы не должны использовать dynamic_cast, Так как вы знаете Sender всегда будет TCheckBoxиспользовать static_cast вместо:

void __fastcall TForm1::CBoxClick(TObject *Sender){
    TCheckBox *cb = static_cast<TCheckBox*>(Sender);
    //Do stuff with cb...
}

ОБНОВЛЕНИЕ: Теперь, с учетом сказанного, лучший вариант - избавиться от ChkBoxInit() в целом и вместо этого выполните инициализацию массива внутри собственного конструктора формы:

class TForm1 : public TForm
{
    ...
private:
    ...
    void __fastcall CBoxClick(TObject *Sender); // <-- moved here
    ...
public:
    __fastcall TForm1(TComponent *Owner); // <-- constructor
    ...
};

__fastcall TForm1::TForm1(TComponent *Owner)
    : TForm(Owner)
{
    TCheckBox* ChkBx[NCARDS];                         //Define array of type checkboxes
    for(int i = 0; i < NCARDS; i++){                  //Initalize each checkbox
        ChkBx[i] = new TCheckBox(this);               //Create a new checkbox
        ChkBx[i] -> Parent = this;                    //Define parent of checkbox
        ChkBx[i] -> Tag = i;                          //Set value of Tag to index
        //  Other CheckBox parameters here such as Height, Width, Top, Left, Name are here
        //  Next, setup event handler
        ChkBx[i]->OnClick = CBoxClick;
    }                                                 //End of for loop
}        

void __fastcall TForm1::CBoxClick(TObject *Sender)
{
    TCheckBox *cb = static_cast<TCheckBox*>(Sender);
    // Do stuff with cb...
}

Реми - У меня все еще проблемы с использованием редактора. Вот рабочий код, основанный на вашем первом ответе с одним небольшим изменением. Спасибо за помощь.

`//.h Файл ----------------

class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TButton *Deal;
        TButton *Reset;
        TButton *Help;
        TButton *Quit;
        TEdit *Debug;
        void __fastcall QuitClick(TObject *Sender);
        void __fastcall ResetClick(TObject *Sender);
private:    // User declarations
public:     // User declarations
  __fastcall TForm1(TComponent* Owner);
  void __fastcall CBoxClick(TObject *Sender);  //CheckBox Event Handler prototype
};

//.cpp файл ----------------

  void ChkBoxInit(void){
    int i;                                         //Loop counter index
    TCheckBox* ChkBx[NCARDS];                      //Define array of type checkbox
    for(i = 0; i < NCARDS; i++){                   //Initalize each checkbox
      ChkBx[i] = new TCheckBox(Form1);             //Create a new checkbox
      ChkBx[i] -> Parent = Form1;                  //Define parent of checkbox

// ..... Various parameters of ChkBx[i] go here (height, Width, Top, Left, etc.)

      ChkBx[i] -> Tag = i;                         //Use index value as tag
`     ChkBx[i] -> OnClick = Form1 -> CBoxClick;    //Assign OnClick event to CBoxClick
    }                                              //End of for loop
  }                                                //End of function


//  Event Handler ------------------

 void __fastcall TForm1::CBoxClick(TObject *Sender){
   if (static_cast<TCheckBox*>(Sender)!=NULL){
     Form1 -> Debug -> Text =  (static_cast<TCheckBox*>(Sender) -> Name);
   }
   else{
     Form1 -> Debug -> Text = "Object is not a TCheckBox";
   }
 }
Другие вопросы по тегам