播放器類應用常需「全螢幕」模式:隱藏標題列、選單、工作列,佔滿整個螢幕工作區。本文提供基於 `WINDOWPLACEMENT` 保存/恢復狀態、配合 `OnGetMinMaxInfo` 限制最大化尺寸的完整 MFC 實作,僅需少量程式碼即可整合至現有 `CDialog`/`CDialogEx` 專案。
class CFullScreenDlg : public CDialog {
// ...
protected:
WINDOWPLACEMENT m_wpPrev; // 保存進入全螢幕前的視窗狀態
CRect m_rcFullScreenRect; // 全螢幕目標矩形 (經 AdjustWindowRectEx 修正)
bool m_bFullScreen = false; // 目前狀態旗標
};
void CFullScreenDlg::FullScreenView() {
if (!m_bFullScreen) {
// 1. 保存當前視窗完整狀態 (位置、尺寸、最大化/最小化狀態)
GetWindowPlacement(&m_wpPrev);
// 2. 取得桌面工作區矩形 (排除工作列)
CRect rcDesk;
::GetWindowRect(::GetDesktopWindow(), &rcDesk);
// 3. 依視窗風格修正為客戶區對應的視窗矩形
::AdjustWindowRectEx(&rcDesk, GetStyle(), FALSE, GetExStyle());
m_rcFullScreenRect = rcDesk;
// 4. 準備新視窗配置
WINDOWPLACEMENT wpNew = m_wpPrev;
wpNew.showCmd = SW_SHOWNORMAL; // 正常顯示 (非最大化/最小化)
wpNew.rcNormalPosition = m_rcFullScreenRect;
m_bFullScreen = true;
// 5. 套用
SetWindowPlacement(&wpNew);
} else {
// 退出全螢幕:直接恢復原狀態
m_bFullScreen = false;
SetWindowPlacement(&m_wpPrev);
}
}
void CFullScreenDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI) {
if (m_bFullScreen) {
// 強制最大/最小追蹤尺寸皆等於全螢幕矩形
lpMMI->ptMaxSize = m_rcFullScreenRect.Size();
lpMMI->ptMaxTrackSize = lpMMI->ptMaxSize;
lpMMI->ptMinTrackSize = lpMMI->ptMaxSize; // 可選:也禁止縮小
}
CDialog::OnGetMinMaxInfo(lpMMI);
}
// 在 OnLButtonDblClk 或 PreTranslateMessage 中
void CFullScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point) {
// 僅在標題列區域雙擊觸發
if (SendMessage(WM_NCHITTEST, 0, MAKELPARAM(point.x, point.y)) == HTCAPTION)
FullScreenView();
CDialog::OnLButtonDblClk(nFlags, point);
}
// 或覆寫 PreTranslateMessage 攔截 Alt+Enter
BOOL CFullScreenDlg::PreTranslateMessage(MSG* pMsg) {
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN && GetKeyState(VK_MENU) & 0x8000) {
FullScreenView();
return TRUE;
}
return CDialog::PreTranslateMessage(pMsg);
}
GetWindowPlacement/SetWindowPlacement 完整保存/恢復 **最大化/最小化/正常狀態、位置、尺寸**,比單純 `GetWindowRect`/`MoveWindow` 魯棒。AdjustWindowRectEx 依視窗風格 (標題列、邊框、選單) 將「客戶區期望尺寸」反推為「視窗外部矩形」,確保全螢幕時客戶區精確貼合螢幕邊緣。OnGetMinMaxInfo 在使用者拖曳邊框、雙擊標題列最大化時被系統呼叫,設定 `ptMaxTrackSize` 可強制限制拖曳上限。