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

MFC 框架程式實現真全螢幕模式:CFullScreenHandler 可復用類別封裝

     編輯:關於VC++

設計目標

將「全螢幕切換」邏輯封裝為獨立 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();
}

整合步驟 (以 SDI 為例)

  1. 將 CFullScreenHandler.h/.cpp 加入專案
  2. MainFrm.h 引入標頭並宣告成員:CFullScreenHandler m_FullScreenHandler;
  3. 選單 ID_VIEW_FULLSCREEN 對應命令處理:
    
    void CMainFrame::OnViewFullScreen() {
        if (m_FullScreenHandler.InFullScreenMode())
            m_FullScreenHandler.Restore(this);
        else
            m_FullScreenHandler.Maximize(this);
    }
        
  4. 選單更新處理:
    
    void CMainFrame::OnUpdateViewFullScreen(CCmdUI* pCmdUI) {
        pCmdUI->SetCheck(m_FullScreenHandler.InFullScreenMode());
    }
        
  5. 關鍵:攔截 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);
    }
        
  6. View 繪製提示 (選用):
    
    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);
        }
        // ... 正常繪製
    }
        

執行效果

全螢幕提示文字 全螢幕矩形計算示意

為什麼需要 OnGetMinMaxInfo?

Windows 預設不允許視窗客戶區大於螢幕工作區。若不攔截 WM_GETMINMAXINFO,SetWindowPlacement 會被系統限制大小,導致底部殘留狀態列(「發育不全的全螢幕」)。手動設定 ptMaxSize/ptMaxTrackSize 為略大於螢幕的值即可繞過限制。

適用範圍與擴充

  • SDI / MDI / 對話框主視窗 (透過 CWnd* 重載)
  • 可擴充:多螢幕支援 (MonitorFromWindow)、動畫切換 (AnimateWindow)、快速鍵 (Accelerator)
  • 執行緒安全:單一 UI 執行緒模型下無競爭

完整原始碼請參考本文配套下載。此方案源自「使用 GDI+ 進行圖像處理」範例改造,已在 VC6.0+Win2000 驗證。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved