【问题标题】:Deleting TFrame from form at run time在运行时从窗体中删除 TFrame
【发布时间】:2012-02-28 03:18:14
【问题描述】:

我正在使用 C++ Builder 创建一个 VCL 表单应用程序。现在我有一个包含一堆组件的 TFrame,它看起来像这样......

我还有一个名为“添加”的按钮。基本上每次我按下表单上的 Add 按钮时,都会在其中添加一个新的 TFrame,并在前一个 TFrame 的下方创建一个看起来像表格的东西。为了添加重复项,我必须在每次创建 TFrame 之前重命名它。

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

那么TFrame的命名就是TFrame1、TFrame2、TFrame3等

现在的问题是我想这样做,所以每次我按下 TFrame 的“X”按钮时,它都会删除该 TFrame,我不太确定该怎么做。我在想,也许每次我创建一个 TFrame 时,我也可以重命名“X”按钮,所以它就像 Button1、Button2、Button3 等。然后删除程序只需将 ButtonX 与 TFrameX 匹配以确定要删除的 TFrame。例如,如果我按下按钮 4,它应该与 TFrame4 匹配并删除 TFrame4。

我不知道如何实现这个想法。或者有更简单的方法吗?

【问题讨论】:

    标签: c++ runtime c++builder tframe


    【解决方案1】:

    一个简单的解决方案是让TFrame 实例为您释放自己。将OnClick 事件处理程序分配给X 按钮,并让它通过PostMessage() 将排队的消息发布到其父TFrame 窗口,然后给TFrame 类提供一个消息处理程序,当该消息时释放TFrame 实例被处理(这就是TForm::Release() 方法的工作原理),例如:

    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);
    }
    

    如果您需要通知您的父级 TForm TFrame 正在关闭(例如,重新定位较低的 TFrame 实例),您可以在 TNotifyEvent 类中公开自定义 TNotifyEvent 事件并让您的 TForm 为其分配一个事件处理程序,例如:

    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...
    }
    

    【讨论】:

    • 非常感谢!我已经坚持了好几天了,这是我计划的主要部分=]
    • 如果您再次阅读此内容,我想就这些框架的定位及其背后的逻辑征求您的建议。你提出了一个非常好的观点,如果要删除中间的帧,我将不得不将所有帧向上移动。然而,由于我定位这些框架的方式以及我命名它们的方式,将它们向上移动还需要重命名框架并重新计算位置。我想我的问题是,有没有更好的方法来定位?我真的很感谢你的帮助,我只是一个合作学生,我从来没有处理过这样的项目
    • 将您的TFrame 指针存储在TListstd::vectorstd::list 等中,无论您喜欢什么。当给定的TFrame 实例正在关闭时,您可以在列表中找到该指针,将其删除,然后循环遍历剩余的指针,将它们的Top 属性按正在关闭的TFrameHeight 递减.你不必依赖他们的Name 值,事实上我总是给我的TFrame 对象没有Name 值,只需将Name 设置为一个空白字符串。它工作正常。
    • 你好!我会尝试一下,使用此设置在逻辑方面进行编程要容易得多
    猜你喜欢
    • 2011-05-22
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    相关资源
    最近更新 更多