删除动态创建的控件 borland 6 c++ builder

Deleting dynamically created control borland 6 c++ builder

我在 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;
}

当我点击创建的按钮时,出现错误 "Access violation at address 40005905 in module 'rtl60.bpl', read of address 00000018"

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

您的代码中有两个错误。

  1. 调用TForm1构造函数时,全局Form1变量还没有赋值,所以你的Form1->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;
    }
    

    或 post 使用 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));
    }