在繪圖類視圖中,根本不需要調用 MoveWindow。只需在 OnSize 中記錄新尺寸,然後在 OnDraw 中根據當前客戶區大小按比例重新繪圖即可。
MoveWindow 用於改變子窗口/控件的位置和大小(即佈局管理)。OnDraw 是繪製客戶區內容的虛擬函數,由框架在需要重繪時自動調用(如 Invalidate 後)。CView、CScrollView)的客戶區大小由框架自動管理,OnSize 只是通知「大小已變」,不需要你手動移動視圖自身。// 1. OnSize 中記錄尺寸,觸發重繪
void CMyView::OnSize(UINT nType, int cx, int cy) {
CView::OnSize(nType, cx, cy);
m_cx = cx; m_cy = cy; // 保存當前客戶區寬高
Invalidate(TRUE); // 標記客戶區無效,觸發 WM_PAINT → OnDraw
}
// 2. OnDraw 中按比例繪圖(方法一:映射模式)
void CMyView::OnDraw(CDC* pDC) {
CRect rect;
GetClientRect(&rect);
// 設置各向異性映射模式:邏輯座標 → 設備座標自動縮放
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(m_baseWidth, m_baseHeight); // 邏輯座標系基準大小
pDC->SetViewportExt(rect.Width(), rect.Height()); // 設備座標系實際大小
// 繪製代碼使用邏輯座標(基準大小),自動映射縮放
DrawMyGraphics(pDC);
}
// 3. OnDraw 中按比例繪圖(方法二:手動縮放座標)
void CMyView::OnDraw(CDC* pDC) {
CRect rect;
GetClientRect(&rect);
double scaleX = (double)rect.Width() / m_baseWidth;
double scaleY = (double)rect.Height() / m_baseHeight;
// 手動縮放每個繪圖座標
pDC->Rectangle((int)(10*scaleX), (int)(10*scaleY), (int)(100*scaleX), (int)(100*scaleY));
// ...
}
| 場景 | 是否需 MoveWindow | 說明 |
|---|---|---|
| 對話框/表單視圖調整子控件佈局 | 是 | 在 OnSize 中調用子控件 MoveWindow 實現自適應佈局 |
| 分割視圖調整分割條位置 | 是 | CSplitterWnd::SetRowInfo/SetColumnInfo 內部調用 MoveWindow |
| 純繪圖視圖(CView 衍生) | 否 | 僅在 OnDraw 中按比例繪圖,無子控件需移動 |
OnSize 必須調用 MoveWindow → 導致遞歸調用或錯誤佈局。OnDraw 中調用 MoveWindow → 觸發重繪循環,程序卡死。記住:繪圖靠 OnDraw + 映射模式/手動縮放,佈局靠 OnSize + MoveWindow。兩者職責分離,按場景選用。