実行時にフォームからTFrameを削除する

私はC ++ Builderを使ってVCLフォームアプリケーションを作成しています。今私はコンポーネントの束を含んでいるTFrameを持っていて、これはこのように見えます...

enter image description here

私はまた、ボタンを呼び出す "追加"があります。基本的にフォームのAddボタンを押すたびに、新しい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などに変更することも考えていました。そして、プログラムを削除すると、TFrameとTFrameXが一致し、削除するTFrameを特定します。たとえば、ボタン4を押すと、TFrame4と一致し、TFrame4が削除されます。

私はこのアイデアをどのように実装するのか分かりません。または、これを行う簡単な方法がありますか?

2

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

TFrame インスタンスの位置を変更するなど、閉じている TFrame を親の TForm に通知する必要がある場合は、 TFrame クラスのカスタム 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。。。
}
4
追加された
本当にありがとう!私は数日間このことに固執していて、それは私のプログラムの主要な部分です]
追加された 著者 livelaughlove,
これをもう一度読むと、これらのフレームの位置付けとその背後にあるロジックについての質問をお願いしたいと思います。真ん中のフレームを削除する必要がある場合は、すべてのフレームをシフトする必要があるという、本当に良い点がありました。しかし、私はこれらのフレームを配置する方法と名前を付けた方法のために、フレームを上にシフトすると、フレームの名前を変更し、位置を再計算する必要があります。私は私の質問は、位置を行うためのより良い方法があると思いますか?私は本当に助けてくれてありがとう、私はちょうど協同組合の学生で、私はこのようなプログラムに取り組んだことはありません
追加された 著者 livelaughlove,
タイタイ!私はそれを試してみると、このセットアップでロジック側でプログラミングする方がずっと簡単でした
追加された 著者 livelaughlove,
TList std :: vector std :: list などのポインタに TFrame 快適です。特定の TFrame インスタンスが閉じられている場合、そのポインタをリスト内で見つけて削除し、残りのポインタをループして Top のプロパティを >高さ TFrame をクリックします。実際に私の TFrame オブジェクトには Name の値を与えないので、 Name の値に頼る必要はありません。 code> Name を空の文字列に置き換えます。それはうまく動作します。
追加された 著者 Remy Lebeau,