MDI 主視窗放置 MainMenu 時,標題列右上角會自動顯示子視窗的最小化/最大化/關閉三鍵。但若選單改放 ToolBar 或自訂繪製,系統不再自動建立,需自行實作。
TBitBtn,覆寫 WndProc 屏蔽 WM_SETFOCUS 防止取得焦點影響視覺狀態。TWindowClose(內建)、自訂 TWindowMinimize、TWindowRestore 繼承 TWindowAction,利用 Action 機制自動管理啟用/可見狀態。FormResize 重新計算三鍵座標固定於客戶區右上角。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;