將「全螢幕切換」邏輯封裝為獨立 CFullScreenHandler 類別,零侵入式整合至現有 SDI/MDI 專案。提供 Maximize()、Restore()、InFullScreenMode() 三大介面,自動處理視窗狀態備份/還原、WM_GETMINMAXINFO 攔截、選單同步、使用者提示。
class CFullScreenHandler {
public:
CFullScreenHandler();
~CFullScreenHandler();
void Maximize(CFrameWnd* pFrame); // 進入全螢幕
void Restore(CFrameWnd* pFrame); // 還原視窗
BOOL InFullScreenMode() const; // 查詢狀態
CSize GetMaxSize() const; // 供 OnGetMinMaxInfo 使用
private:
CRect m_rcRestore; // 原視窗矩形
BOOL m_bFullScreen = FALSE;
};
Maximize()
void CFullScreenHandler::Maximize(CFrameWnd* pFrame) {
if (m_bFullScreen) return;
// 1. 備份目前視窗佈局
WINDOWPLACEMENT wp;
pFrame->GetWindowPlacement(&wp);
m_rcRestore = wp.rcNormalPosition;
// 2. 隱藏 UI 元素
CControlBar* pBar;
// 隱藏工具列、狀態列... (透過框架視窗列舉控制列)
// 3. 計算全螢幕目標矩形 (含非客戶區調整)
CRect rcScreen(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
::AdjustWindowRectEx(&rcScreen, pFrame->GetStyle(), TRUE, pFrame->GetExStyle());
// 4. 套用新佈局
WINDOWPLACEMENT wpNew = wp;
wpNew.showCmd = SW_SHOWNORMAL;
wpNew.rcNormalPosition = rcScreen;
pFrame->SetWindowPlacement(&wpNew);
m_bFullScreen = TRUE;
}
Restore()
void CFullScreenHandler::Restore(CFrameWnd* pFrame) {
if (!m_bFullScreen) return;
// 顯示先前隱藏的控制列...
WINDOWPLACEMENT wp;
pFrame->GetWindowPlacement(&wp);
wp.rcNormalPosition = m_rcRestore;
pFrame->SetWindowPlacement(&wp);
m_rcRestore.SetRectEmpty();
m_bFullScreen = FALSE;
}
GetMaxSize()
CSize CFullScreenHandler::GetMaxSize() const {
CRect rc(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
rc.InflateRect(10, 50); // 稍大於螢幕,確保覆蓋工作區
return rc.Size();
}
CFullScreenHandler.h/.cpp 加入專案MainFrm.h 引入標頭並宣告成員:CFullScreenHandler m_FullScreenHandler;ID_VIEW_FULLSCREEN 對應命令處理:
void CMainFrame::OnViewFullScreen() {
if (m_FullScreenHandler.InFullScreenMode())
m_FullScreenHandler.Restore(this);
else
m_FullScreenHandler.Maximize(this);
}
void CMainFrame::OnUpdateViewFullScreen(CCmdUI* pCmdUI) {
pCmdUI->SetCheck(m_FullScreenHandler.InFullScreenMode());
}
WM_GETMINMAXINFO:
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO* lpMMI) {
if (m_FullScreenHandler.InFullScreenMode()) {
CSize sz = m_FullScreenHandler.GetMaxSize();
lpMMI->ptMaxSize = CPoint(sz.cx, sz.cy);
lpMMI->ptMaxTrackSize = CPoint(sz.cx, sz.cy);
}
CFrameWnd::OnGetMinMaxInfo(lpMMI);
}
void CMyView::OnDraw(CDC* pDC) {
if (GetParentFrame()->m_FullScreenHandler.InFullScreenMode()) {
CRect rc; GetClientRect(&rc);
pDC->DrawText(_T("按 Ctrl+U 或雙擊滑鼠左鍵退出全螢幕"), &rc,
DT_CENTER|DT_VCENTER|DT_SINGLELINE);
}
// ... 正常繪製
}

Windows 預設不允許視窗客戶區大於螢幕工作區。若不攔截 WM_GETMINMAXINFO,SetWindowPlacement 會被系統限制大小,導致底部殘留狀態列(「發育不全的全螢幕」)。手動設定 ptMaxSize/ptMaxTrackSize 為略大於螢幕的值即可繞過限制。
CWnd* 重載)MonitorFromWindow)、動畫切換 (AnimateWindow)、快速鍵 (Accelerator)完整原始碼請參考本文配套下載。此方案源自「使用 GDI+ 進行圖像處理」範例改造,已在 VC6.0+Win2000 驗證。