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

Delphi MDI 子視窗標題列按鈕自繪:最小化、最大化、關閉功能完整實現

     編輯:Delphi

問題背景

MDI 主視窗放置 MainMenu 時,標題列右上角會自動顯示子視窗的最小化/最大化/關閉三鍵。但若選單改放 ToolBar 或自訂繪製,系統不再自動建立,需自行實作。

架構設計

  1. 自訂按鈕類別:繼承 TBitBtn,覆寫 WndProc 屏蔽 WM_SETFOCUS 防止取得焦點影響視覺狀態。
  2. Action 封裝功能:TWindowClose(內建)、自訂 TWindowMinimize、TWindowRestore 繼承 TWindowAction,利用 Action 機制自動管理啟用/可見狀態。
  3. 位置同步:FormResize 重新計算三鍵座標固定於客戶區右上角。
  4. 可見性判斷:ApplicationEvents.OnIdle 檢查 ActiveMDIChild.WindowState = wsMaximized 決定顯示/隱藏。

核心程式碼節錄

type
  TMDIButton = class(TBitBtn)
    procedure WndProc(var Message: TMessage); override;
  end;

  TWindowMinimize = class(TWindowAction)
    procedure ExecuteTarget(Target: TObject); override;
  end;

  TWindowRestore = class(TWindowAction)
    procedure ExecuteTarget(Target: TObject); override;
  end;

procedure TMDIButton.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_SETFOCUS then Exit; // 拒絕焦點
  inherited;
end;

procedure TWindowMinimize.ExecuteTarget(Target: TObject);
begin
  inherited;
  with GetForm(Target) do
    if Assigned(ActiveMDIChild) then
      ActiveMDIChild.WindowState := wsMinimized;
end;

procedure TWindowRestore.ExecuteTarget(Target: TObject);
begin
  inherited;
  with GetForm(Target) do
    if Assigned(ActiveMDIChild) then
      ActiveMDIChild.WindowState := wsNormal;
end;

建立與佈局

procedure TForm1.FormCreate(Sender: TObject);
begin
  // 關閉鈕
  BtnClose := TMDIButton.Create(Self);
  BtnClose.Parent := Self; BtnClose.Width := 16; BtnClose.Height := 15;
  WindowClose := TWindowClose.Create(nil);
  WindowClose.ActionList := ActionList1; WindowClose.ImageIndex := 2;
  BtnClose.Action := WindowClose;

  // 最小化鈕
  BtnMin := TMDIButton.Create(Self); ...
  WindowMinimize := TWindowMinimize.Create(nil);
  WindowMinimize.ActionList := ActionList1; WindowMinimize.ImageIndex := 0;
  BtnMin.Action := WindowMinimize;

  // 還原鈕
  BtnRestore := TMDIButton.Create(Self); ...
  WindowRestore := TWindowRestore.Create(nil);
  WindowRestore.ActionList := ActionList1; WindowRestore.ImageIndex := 1;
  BtnRestore.Action := WindowRestore;

  SetMDIFormActionPos; // 初始定位
end;

procedure TForm1.SetMDIFormActionPos;
begin
  if Assigned(BtnClose)   then begin BtnClose.Left   := Width - 26; BtnClose.Top   := 6; end;
  if Assigned(BtnRestore) then begin BtnRestore.Left := Width - 44; BtnRestore.Top := 6; end;
  if Assigned(BtnMin)     then begin BtnMin.Left     := Width - 60; BtnMin.Top     := 6; end;
end;

閒置時檢查可見性

procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
var ShowBtn: Boolean;
begin
  ShowBtn := Assigned(ActiveMDIChild) and (ActiveMDIChild.WindowState = wsMaximized);
  BtnClose.Visible   := ShowBtn;
  BtnMin.Visible     := ShowBtn;
  BtnRestore.Visible := ShowBtn;
end;

資源釋放

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(BtnClose);   FreeAndNil(WindowClose);
  FreeAndNil(BtnMin);     FreeAndNil(WindowMinimize);
  FreeAndNil(BtnRestore); FreeAndNil(WindowRestore);
end;

優勢

  • 完全由 VCL Action 機制管理狀態,程式碼結構清晰。
  • 按鈕不搶焦點,不干擾子視窗內部控件 Tab 順序。
  • 支援自訂圖示、ToolTip、快捷鍵等擴充。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved