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

MDI 主框架視窗背景圖片繪製技巧:攔截 WM_PAINT 實現全客戶區貼圖

     編輯:VC 教學

問題分析

MDI 應用程式的客戶區完全被 MDICLIENT 視窗覆蓋,導致 CMDIFrameWnd 的 OnPaint、背景色、游標設定均失效。微軟不支援對 MDICLIENT 進行子類化,故無法直接在其 WM_PAINT 繪圖。

解決方案:訊息轉發法

在主框架 CMainFrame 中:

  1. 覆寫 PreTranslateMessage 攔截 MDICLIENT 的 WM_PAINT。
  2. 轉發 WM_PAINT 給主框架自身。
  3. 在主框架 OnPaint 中繪製背景位圖至 MDICLIENT DC。

關鍵程式碼

1. 成員變數與資源

  • 匯入 256 色位圖資源 IDB_BITMAP1。

2. PreTranslateMessage 攔截


BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->hwnd == m_hWndMDIClient && pMsg->message == WM_PAINT)
        PostMessage(WM_PAINT); // 轉發給主框架
    return CMDIFrameWnd::PreTranslateMessage(pMsg);
}

3. OnPaint 繪製背景


void CMainFrame::OnPaint()
{
    CDC dc, memDC;
    dc.m_hDC = ::GetDC(m_hWndMDIClient); // 直接取得 MDICLIENT DC

    CRect rect;
    GetClientRect(&rect); // 主框架客戶區即 MDICLIENT 區域

    CBitmap bmp;
    bmp.LoadBitmap(IDB_BITMAP1);
    BITMAP bmInfo;
    bmp.GetObject(sizeof(BITMAP), &bmInfo);
    CSize size(bmInfo.bmWidth, bmInfo.bmHeight);

    memDC.CreateCompatibleDC(&dc);
    CBitmap* pOldBmp = memDC.SelectObject(&bmp);

    // 拉伸貼圖填滿整個客戶區
    StretchBlt(dc.m_hDC, 0, 0, rect.Width(), rect.Height(),
               memDC.m_hDC, 0, 0, size.cx, size.cy, SRCCOPY);

    memDC.SelectObject(pOldBmp);
    memDC.DeleteDC();
    dc.DeleteDC();

    CMDIFrameWnd::OnPaint(); // 呼叫基底類別處理其他繪製
}

進階擴充

  • 真彩色位圖:使用 LoadImage 載入 24/32-bit BMP,配合 CreateDIBSection 繪製。
  • 平鋪模式:改用 BitBlt 迴圈而非 StretchBlt。
  • 雙緩衝:在記憶體 DC 先合成再一次 BitBlt 至螢幕,消除閃爍。

注意事項

  • GetDC(m_hWndMDIClient) 取得的是 MDICLIENT 的裝置內容,繪製內容直接顯示於 MDI 客戶區。
  • 必須呼叫 CMDIFrameWnd::OnPaint() 以維持子視窗標題列等標準繪製。
  • 若專案啟用視覺樣式 (XP Themes),需在 stdafx.h 包含 afxctl.h 並啟用 AFX_MANAGE_STATE。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved