假設我的表單A包含一個面板(其中包含許多其他控件)和一個表單B,它是空的。
我可以以編程方式從窗體A分離面板並將它移動到窗體B中(也可以回到窗體A)?如何分離面板並將其顯示在單獨的窗口中?
我知道我可以更改面板的所有者,但它可以在不同的窗體之間工作嗎?
更新:
一些谷歌搜索後,我看到有一個ParentWindow屬性。
假設我的表單A包含一個面板(其中包含許多其他控件)和一個表單B,它是空的。
我可以以編程方式從窗體A分離面板並將它移動到窗體B中(也可以回到窗體A)?如何分離面板並將其顯示在單獨的窗口中?
我知道我可以更改面板的所有者,但它可以在不同的窗體之間工作嗎?
更新:
一些谷歌搜索後,我看到有一個ParentWindow屬性。
您可以輕鬆擁有的東西看起來好像它是一個面板,也可作爲一種形式,通過真正使用TForm的什麼你會使用的面板。然後在運行時將表單停靠在爲此目的而留有空白麪板的位置,並以相同的方式在運行時取消它。
您無法取消鎖定TPanel並將其作爲頂級窗體顯示,但您可以採用頂級窗體並將其停靠在代碼中。要獲得所需的外觀和功能,必須使用正確的工具(本例中爲TForm)。
順便說一下,像Toolbar 2000這樣的組件庫允許基於工具欄面板的浮動工具欄窗口,所以如果你真的堅持讓所有的designtim元素保持一種形式,在設計時,你應該看看它在Toolbar 2000它有很多代碼可以使工具欄處於「未鎖定/浮動」模式,並且可以處理鼠標驅動的工具欄停靠和取消鎖定到工具欄停靠欄。
您必須考慮所有權,否則銷燬表格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.InsertedPanel
和Panel1
指向同一個對象,但它是一種語義首選。也許中央控制變量更好。
更新:
我錯認爲RemoveComponent級聯到面板上的子控件。當然,並不是這樣,只有從窗體A移除面板纔會留下面板仍然由窗體A擁有的所有子控件。因此,我添加了RemoveComponents例程以從面板的所有子控件中移除所有權。
請注意,面板的子控件目前沒有所有者。但由於它們是面板的父控制,所以面板的銷燬將釋放這些控制。所以要確保面板有父母,或者明確地釋放面板。
以上所有僅適用於設計時創建的面板,將設計時間放在窗體上,這是我的假設。由於這種變化的父母行爲顯然是需要或需要的,所以您可能需要考慮在運行時完全實現它。爲了保持設計面板設計時間的能力,我建議創建一個框架,您可以在該框架上設計該面板,並在窗體周圍跳轉框架。
其實,你不太對。更改父母更改誰將其銷燬(父母的職責 - 請參閱我在答案中發佈的文檔鏈接)。因此,更改父處理從Form1中刪除該組件並將其添加到Form2。 (這是特別描述在我鏈接的wiki條目 - 請參閱** Note **。) –
@Ken Parent是Owner,是從D7開始的某個地方介紹的嗎? – NGLN
@NGLN:其實我不確定。我沒有再安裝D7,無法檢查。這是在XE,我只是檢查了D2010,它是一樣的。我將無法在稍後檢查D2007。 –
正如其他人所指出的,有幾個問題,改變控制的父窗口不改變所有權,並改變一個老闆控制是很困難的,如果它有多個控件坐在上面......
一解決方法是使用一個框架。一個框架擁有它所有的子控件,所以你需要做的就是改變框架的所有者和父母,其他的東西都會隨之而來。這種方法還允許您將所有事件處理程序和代碼粘貼到一個地方。
N - [
+1爲了解釋_why_幀是最好的解決方案。顯然,我不知道如何用我的建議來管理。 ;-) – NGLN
'ParentWindow'不起作用。請參閱文檔中的[this](http://docwiki.embarcadero.com/VCL/en/Controls.TWinControl.ParentWindow):「如果Parent不是零(Delphi)或NULL(C++),則設置ParentWindow不起作用。」 '父'不是零(它是formA)。 –