MDI 應用程式的主框架視窗包含一個特殊的 MDICLIENT 子視窗,完全覆蓋客戶區。導致:
CMDIFrameWnd 的背景色與游標設定失效MDICLIENT 子類別化WM_PAINT在主框架類別中覆寫 PreTranslateMessage 攔截 MDICLIENT 的重繪訊息,轉發 WM_PAINT 給主框架,再於 OnPaint 繪製背景圖。
IDB_BITMAP1CMainFrame 加入 PreTranslateMessage 與 OnPaint 處理函式BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) {
// 攔截 MDICLIENT 的 WM_PAINT
if (pMsg->hwnd == m_hWndMDIClient && pMsg->message == WM_PAINT) {
PostMessage(WM_PAINT); // 轉發給主框架
}
return CMDIFrameWnd::PreTranslateMessage(pMsg);
}
void CMainFrame::OnPaint() {
CDC dc, memdc;
dc.m_hDC = ::GetDC(m_hWndMDIClient); // 取得 MDICLIENT DC
CRect rect;
GetClientRect(&rect); // 取得客戶區大小
CBitmap bitmap;
BITMAP szbitmap;
bitmap.LoadBitmap(IDB_BITMAP1); // 載入位圖資源
bitmap.GetObject(sizeof(BITMAP), &szbitmap);
CSize size(szbitmap.bmWidth, szbitmap.bmHeight);
memdc.CreateCompatibleDC(&dc); // 建立相容 DC
CBitmap* oldbitmap = memdc.SelectObject(&bitmap);
// 伸縮繪製填滿整個客戶區
StretchBlt(dc.m_hDC, 0, 0, rect.Width(), rect.Height(),
memdc.m_hDC, 0, 0, size.cx, size.cy, SRCCOPY);
memdc.SelectObject(oldbitmap);
memdc.DeleteDC();
dc.DeleteDC();
CMDIFrameWnd::OnPaint(); // 呼叫基底類別
}
| 技術點 | 說明 |
|---|---|
| m_hWndMDIClient | 主框架成員變數,指向 MDICLIENT 視窗控制代碼 |
| PreTranslateMessage | 訊息派送前攔截點,可過濾/轉發訊息 |
| PostMessage(WM_PAINT) | 非同步張貼重繪訊息,避免遞迴 |
| StretchBlt | 將位圖伸縮繪製至目標 DC,自適應視窗大小 |
| GetDC(m_hWndMDIClient) | 直接取得 MDICLIENT 的裝置內容,而非主框架 |
LoadImage 載入外部 BMP/PNG/JPGBitBlt 迴圈實現磚狀重複StretchBlt 參數Visual C++ 6.0 / MFC 4.2 以上,Windows 98/NT 4.0/2000/XP 均可正常執行。