首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 視窗容器化:將表單嵌入 Panel 實現非 MDI 多視窗佈局

     編輯:Delphi

應用場景

需在主視窗 Form1 的 Panel1 內嵌入 Form2、Form3 等子視窗,但不想使用 MDI 架構。關鍵在於攔截視窗建立參數,指定父視窗控制代碼與 WS_CHILD 風格。

核心技術:重寫 CreateParams 與 Loaded

type
  TForm2 = class(TForm)
  public
    procedure CreateParams(var Params: TCreateParams); override;
    procedure Loaded; override;
  end;

procedure TForm2.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  // 指定父視窗為擁有者 (Form1) 的控制代碼
  Params.WndParent := (Owner as TForm).Handle;
  // 設為子視窗風格,支援同層剪裁
  Params.Style := WS_CHILD or WS_CLIPSIBLINGS;
  Params.X := 0;
  Params.Y := 0;
end;

procedure TForm2.Loaded;
begin
  inherited Loaded;
  Visible := False;           // 建立期間先隱藏
  Position := poDefault;      // 避免預設定位干擾
  BorderIcons := [];          // 移除標題列圖示
  BorderStyle := bsNone;      // 無邊框
  HandleNeeded;               // 強制建立視窗控制代碼
  SetBounds(0, 0, Width, Height); // 維持原始尺寸
  Visible := True;            // 顯示於容器內
end;

主視窗建立子視窗範例

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form2 := TForm2.Create(Self);  // Self 為 Owner,對應 CreateParams 中的 Owner
  Form2.Parent := Panel1;        // VCL 親子關係(可選,僅影響座標系統)
  Form2.Show;
  
  Form3 := TForm3.Create(Self);
  Form3.Parent := Panel1;
  Form3.Show;
end;

關鍵差異:CreateParams vs Loaded

方法呼叫時機用途
CreateParams視窗控制代碼建立前設定 WndParent、Style、ExStyle 等底層參數
LoadedDFM 載入完成、控制代碼已建立後調整視窗屬性、呼叫 HandleNeeded、設定邊界

進階技巧

  • 座標系統:子視窗座標相對於父視窗客戶區原點 (0,0)
  • 訊息傳遞:父視窗可透過 SendMessage 與子視窗通訊
  • 焦點管理:WS_TABSTOP 風格讓子視窗參與 Tab 順序
  • 多層嵌套:同樣原理可實現多層容器巢狀結構

常見陷阱

  1. 忘記設定 BorderStyle := bsNone 導致雙重邊框
  2. Owner 與 Parent 混淆:Owner 負責釋放記憶體,Parent 負責視覺包含
  3. 未呼叫 HandleNeeded 導致 Handle 為 0 而後續操作失敗

總結

透過覆寫 CreateParams 指定 WndParent 與 WS_CHILD 風格,配合 Loaded 微調視窗屬性,即可輕鬆實現「表單即控制項」的靈活佈局,完全替代傳統 MDI 架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved