參考 RealPlayer 的「正常」、「精簡」、「迷你」三種顯示模式,本文實現對話框基礎應用程式的三模式切換:正常模式(完整介面)、精簡模式(隱藏狀態列)、迷你模式(僅保留標題列與工具列)。核心在於精確計算各模式下的視窗尺寸。
| 模式 | 顯示元素 | 尺寸計算邏輯 |
|---|---|---|
| 正常 (0) | 選單、工具列、狀態列、客戶區 | 原始視窗尺寸 |
| 精簡 (1) | 選單、工具列、客戶區(隱藏狀態列) | 高度 = 視窗高 - 客戶區高 + 工具列高 - 邊框高 |
| 迷你 (2) | 僅標題列、工具列(隱藏選單、狀態列、客戶區) | 高度 = 標題列高 + 工具列高 + 邊框高×2 |
void CMainFrame::ViewMode(int nViewType) {
CRect ClientRect, WindowRect, ToolbarRect, StatusbarRect;
// 取得各區域尺寸
WindowRect = m_WindowRect; // 需在 OnCreate 時儲存初始視窗矩形
ClientRect = m_ClientRect; // 需在 OnCreate 時儲存初始客戶區矩形
m_wndToolBar.GetWindowRect(&ToolbarRect);
int borderHeight = GetSystemMetrics(SM_CYBORDER);
int captionHeight = GetSystemMetrics(SM_CYCAPTION);
CStatusBar* pStatus = (CStatusBar*)AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR);
pStatus->GetWindowRect(&StatusbarRect);
DockControlBar(&m_wndToolBar); // 確保工具列停靠狀態
int CompactCx = WindowRect.Width(); // 寬度不變
int CompactCy;
switch (nViewType) {
case 0: // 正常模式
if (hMenu != NULL) ::SetMenu(m_hWnd, hMenu); // 還原選單
pStatus->ShowWindow(SW_SHOW);
CompactCy = WindowRect.Height();
break;
case 1: // 精簡模式
if (hMenu != NULL) ::SetMenu(m_hWnd, hMenu);
pStatus->ShowWindow(SW_HIDE);
CompactCy = WindowRect.Height() - ClientRect.Height() + ToolbarRect.Height() - borderHeight;
break;
case 2: // 迷你模式
hMenu = ::GetMenu(m_hWnd); // 儲存選單控制碼
::SetMenu(m_hWnd, NULL); // 隱藏選單
pStatus->ShowWindow(SW_HIDE);
CompactCy = captionHeight + ToolbarRect.Height() + borderHeight * 2;
break;
}
SetWindowPos(&wndTop, WindowRect.left, WindowRect.top, CompactCx, CompactCy, SWP_SHOWWINDOW);
}
GetSystemMetrics(SM_CYCAPTION)、SM_CYBORDER 取得標題列與邊框高度hMenu,恢復時重新設定DockControlBar 確保尺寸計算準確ShowWindow(SW_HIDE/SHOW) 控制OnCreate 中儲存 m_WindowRect、m_ClientRect以精確的系統度量計算取代試誤調整,實現穩定的三模式視窗切換。邏輯清晰、無硬編碼尺寸、適應不同 DPI 與主題設定。原始碼可直接整合至 SDI/MDI 主框架類別中使用。