2011-06-23 24 views
5

私はパネルが(それに他の多くのコントロールを含む)パネルとそれが空であるフォームBを含むフォームAを持っているとしましょう。
プログラムでパネルをフォームAから切り離し、フォームBで移動することはできますか?パネルを切り離して別のウィンドウに表示するにはどうすればいいですか?

私はパネルの所有者を変更することができますが、それは異なるフォームの間で動作するのですか?

更新:
Google検索の後、私はParentWindowプロパティがあることがわかります。

+0

'ParentWindow'は機能しません。ドキュメントの[this](http://docwiki.embarcadero.com/VCL/en/Controls.TWinControl.ParentWindow)を参照してください。 "ParentWindowを設定すると、Parentがnil(Delphi)またはNULL(C++)でない場合は効果がありません。 'Parent'はnilではありません(formAです)。 –

答えて

2

@

Nは本当にあなたがパネルを使用しているだろう何のためにTFormのを使用することによって、それがパネルだったかのように、また、フォームとして表示されます。次に、その目的のために空白のパネルが残っている場所に実行時にフォームをドッキングし、同じ方法で実行時にドッキング解除します。

TPanelをドッキング解除してトップレベルフォームウィンドウとして表示することはできませんが、トップレベルフォームウィンドウを使用してコードにドッキングすることができます。必要な外観と機能を得るには、正しいツール(この場合はTForm)を使用する必要があります。

ちなみに、Toolbar 2000のようなコンポーネントライブラリは、ツールバーパネルに基づいてフローティングツールバーウィンドウを可能にするので、designtim要素をdesigtimeで1つのフォームに残すことを本当に強く求めているのであれば、ツールバー2000ツールバーを「ドッキング解除/フローティング」モードで表示したり、ツールバードックへのマウス駆動ドッキングやドッキング解除を処理するためのコードがたくさんあります。

2

パネルと子コンポーネントが実行時に作成されている場合は、あなただけのFormBにパネルのParentを設定することができます。

Panel1.Parent := FormB; 

FormBは、あなたがこれを行うことができます前に、既に作成されている必要があること。

詳細については、Delphi Wikiページhereを参照してください。

+0

これは、パネルがフォームAでデザイン作成されていない場合にのみ適用されます。それ以外の場合、フォームAはパネルの所有権を保持します。 – NGLN

+0

合意。それを反映するように編集されました。 –

+0

残念ながら、パネル上のコントロールの設定は非常に複雑です。実行時にそれらを構築するにはかなりの作業が必要です。 – Ampere

4

あなたは所有権を考慮する必要があります。そうしないと、フォームAの破壊はフォームBのパネルの消滅(つまり破壊)につながります。

type 
    TForm2 = class(TForm) 
    public 
    InsertedPanel: TControl; // or TPanel 

procedure RemoveComponents(AForm: TComponent; AControl: TWinControl); 
var 
    I: Integer; 
begin 
    for I := 0 to AControl.ControlCount - 1 do 
    begin 
    if AControl.Controls[I] is TWinControl then 
     RemoveComponents(AForm, TWinControl(AControl.Controls[I])); 
    if AControl.Controls[I].Owner = AForm then 
     AForm.RemoveComponent(AControl.Controls[I]); 
    end; 
    AForm.RemoveComponent(AControl); 
end; 

procedure TForm1.Button3Click(Sender: TObject); 
begin 
    Form2.InsertedPanel := Panel1; 
    Panel1.Parent := nil; 
    RemoveComponents(Self, Panel1); 
    Form2.InsertComponent(Form2.InsertedPanel); // < this is not necessary 
    Form2.InsertedPanel.Parent := Form2;  // as long as Parent is set 
    Panel1 := nil;        // or if you free the panel 
end;           // manually 

余分な参照は、ビット愚かに見えるかもしれません:同じオブジェクトにForm2.InsertedPanelPanel1点が、それは一種の意味的に好適です。たぶん中央制御変数が良いでしょう。

アップデート:私は誤ってRemoveComponentは、パネル上の子コントロールにカスケード接続することを想定し

。もちろん、フォームAからパネルを削除するだけでは、パネルのすべての子コントロールがフォームAによって所有されたままになります。そのため、RemoveComponentsルーチンを追加してパネルのすべての子コントロールから所有権を削除しました。

この時点で、パネルの子コントロールには所有者がいないことに注意してください。しかし、彼らはパネルの親コントロールであるため、パネルを破壊するとそれらのコントロールが解放されます。したがって、パネルに親があるか、パネルを明示的に解放してください。

上記のすべては、デザイン時に作成されたパネルにのみ適用され、フォーム上にデザインタイムが配置されていましたが、それは私の前提でした。この変更された親の動作は明らかに必要とされているか、必要であるため、実行時に完全に実装することを検討することをお勧めします。パネルデザインを設計する能力を維持するために、そのパネルをデザインし、フォームの周りにフレームをジャンプできるフレームを作成することをお勧めします。

+0

実際、あなたは正しくはありません。親を変更すると、誰がそれを破壊するのかが変更されます(親は行います - 答えに投稿したドキュメントのリンクを参照してください)。したがって、Form1からコンポーネントを削除してForm2に追加する処理は、Parentハンドルを変更します。 (それは特に私がリンクしているwikiエントリーに記載されています - **注**を参照してください) –

+0

@Ken親は所有者で、それはD7以来導入されていますか? – NGLN

+0

@NGLN:実際、私はよくわかりません。私はもうD7をインストールしておらず、確認できません。それはXEにあり、私はちょうどD2010をチェックし、それは同じです。私は後日までD2007をチェックすることができません。 –

8

他の人が指摘したように、所有権を変更することなく、コントロールの親ウィンドウを変更すると、それはそれの上に座って、複数のコントロールを持っている場合はコントロールの所有者が困難なことが変化するにはいくつかの問題がある...

ワン代わりにフレームを使用することです。フレームはすべてのサブコントロールを所有していますので、フレームの所有者と親を変更するだけで済みます。それ以外はすべて一緒に表示されます。このアプローチでは、すべてのイベントハンドラとグルーコードを単一の場所に保持することもできます。あなたは簡単に何かを持つことができます

+0

+1 _why_を説明するためにフレームが最適な解決策です。どうやら私は何とか私の提案でそれをどうにかして管理していませんでした。 ;-) – NGLN

関連する問題