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

时间:2015-12-23 20:45:45

标签: c++ c++builder c++builder-6

我在删除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"出现

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

1 个答案:

答案 0 :(得分:1)

您的代码中有两个错误。

  1. 调用Form1构造函数时尚未分配全局TForm1变量,因此您的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;
    }
    

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