问题
I am using C++ Builder to create a VCL form application. Right now I have a TFrame containing a bunch of components and it looks like this...
I also have a button call "Add". Basically every time I press that Add button on the form, a new TFrame is added to it and below the previous one making something that looks like a table. And in order to add duplicates I have to rename the TFrame each time before it is created.
int __fastcall TForm1::AddMapCells(void)
{
Num++;
TFrame1 * MyFrame = new TFrame1(Form1);
MyFrame->Parent=Form1;
MyFrame->Name = "TFrame" + IntToStr(Num);
MyFrame->Top = 23*Num;
return Num;
}
So then the naming of TFrame would be TFrame1, TFrame2, TFrame3, etc.
The problem now is I want to make it so then each time I press the 'X' button of a TFrame, it deletes that TFrame and I'm not quite sure how to do it. I was thinking maybe each time I create a TFrame I can also rename the 'X' button so then it's like Button1, Button2, Button3, etc. And then to delete the program would just match ButtonX with TFrameX to identify which TFrame to delete. For example, if I press Button 4, it should match up with TFrame4 and delete TFrame4.
I don't know how to implement this idea. Or would there be an easier way of doing this?
回答1:
A simple solution would be to let the TFrame
instances free themselves for you. Assign an OnClick
event handler to the X button and have it post a queued message to its parent TFrame
window via PostMessage()
, then give the TFrame
class a message handler that frees the TFrame
instance when that message is processed (this is how the TForm::Release()
method works), eg:
void __fastcall TFrame1::CloseButtonClick(TObject *Sender)
{
// CM_RELEASE is defined in Controls.hpp
PostMessage(Handle, CM_RELEASE, 0, 0);
}
void __fastcall TFrame1::WndProc(TMessage &Message)
{
if (Message.Msg == CM_RELEASE)
{
delete this;
return;
}
TFrame::WndProc(Message);
}
If you need your parent TForm
to be notified of the TFrame
being closed (for instance, to reposition lower TFrame
instances), you can expose a custom TNotifyEvent
event in the TFrame
class and have your TForm
assign an event handler to it, eg:
class TFrame1 : public TFrame
{
private:
TNotifyEvent FOnClose;
...
public:
...
__property TNotifyEvent OnClose = {read=FOnClose, write=FOnClose};
};
void __fastcall TFrame1::CloseButtonClick(TObject *Sender)
{
if (FOnClose != NULL) FOnClose(this);
PostMessage(Handle, CM_RELEASE, 0, 0);
}
void __fastcall TFrame1::WndProc(TMessage &Message)
{
if (Message.Msg == CM_RELEASE)
{
delete this;
return;
}
TFrame::WndProc(Message);
}
.
int __fastcall TForm1::AddMapCells(void)
{
Num++;
TFrame1 * MyFrame = new TFrame1(this);
MyFrame->Parent = this;
MyFrame->Name = "TFrame" + IntToStr(Num);
MyFrame->Top = 23*Num;
MyFrame->OnClose = &FrameClosed;
return Num;
}
void __fastcall TForm1::FrameClosed(TObject *Sender)
{
// Sender is the TFrame1 instance whose X button was clicked.
// It will auto-free itself after this method exits...
}
来源:https://stackoverflow.com/questions/9163664/deleting-tframe-from-form-at-run-time