0

我在删除 Borland C++Builder 6 中动态创建的按钮时遇到问题。

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner) {
  TButton *but = new TButton(this);
  but->Left = 100;
  but->Top = 100;
  but->OnClick = click;
  Form1->InsertControl(but);
}

void __fastcall TForm1::click(TObject *Sender) {
    delete Sender;
}

当我单击创建的按钮时,出现错误“模块'rtl60.bpl'中地址40005905的访问冲突,读取地址00000018”

我知道为删除它的按钮分配一个方法是错误的,但我真的需要通过按下它来删除按钮

4

1 回答 1

1

您的代码中有两个错误。

  1. 调用构造函数Form1时尚未分配全局变量,因此您的语句无效并可能崩溃。使用而不是. 但是,您不应该直接调用,而是设置按钮的属性:TForm1Form1->InsertControl(but)this->Form1->InsertControl()Parent

    but->Parent = this;
    
  2. 当事件处理程序正在运行时,事件的发生是不安全delete的。Sender处理程序退出后,RTL 仍需要访问对象(如您的 AccessViolation 错误所示)。您将不得不延迟delete,例如使用短计时器:

    void __fastcall TForm1::DeleteButtonTimerElapsed(TObject *Sender)
    {
        TObject *obj = reinterpret_cast<TObject*>(DeleteButtonTimer->Tag);
        DeleteButtonTimer->Tag = 0;
        DeleteButtonTimer->Enabled = false;
        delete obj;
    }
    
    void __fastcall TForm1::click(TObject *Sender)
    {
        DeleteButtonTimer->Tag = reinterpret_cast<int>(Sender);
        DeleteButtonTimer->Enabled = true;
    }
    

    PostMessage()或者使用(我更喜欢这种方法)向自己发布自定义消息:

    #define WM_DELETE_OBJECT (WM_USER + 1)
    
    void __fastcall TForm1::WndProc(TMessage &Message)
    {
        if (Message.Msg == WM_DELETE_OBJECT)
            delete reinterpret_cast<TObject*>(Message.LParam);
        else
            TForm::WndProc(Message);
    }
    
    void __fastcall TForm1::click(TObject *Sender)
    {
        TButton *btn = static_cast<TButton*>(Sender);
        btn->OnClick = NULL;
        PostMessage(Handle, WM_DELETE_OBJECT, 0, reinterpret_cast<LPARAM>(Sender));
    }
    
于 2015-12-23T23:03:16.783 回答