MDI 應用程式的客戶區完全被 MDICLIENT 視窗覆蓋,導致 CMDIFrameWnd 的 OnPaint、背景色、游標設定均失效。微軟不支援對 MDICLIENT 進行子類化,故無法直接在其 WM_PAINT 繪圖。
在主框架 CMainFrame 中:
PreTranslateMessage 攔截 MDICLIENT 的 WM_PAINT。WM_PAINT 給主框架自身。OnPaint 中繪製背景位圖至 MDICLIENT DC。IDB_BITMAP1。
BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
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); // 主框架客戶區即 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。BitBlt 至螢幕,消除閃爍。GetDC(m_hWndMDIClient) 取得的是 MDICLIENT 的裝置內容,繪製內容直接顯示於 MDI 客戶區。CMDIFrameWnd::OnPaint() 以維持子視窗標題列等標準繪製。stdafx.h 包含 afxctl.h 並啟用 AFX_MANAGE_STATE。