首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

MFC OnSize 與 MoveWindow 關係解析:無需 MoveWindow 直接 OnDraw 繪圖

     編輯:程式設計疑難解答

核心結論

在繪圖類視圖中,根本不需要調用 MoveWindow。只需在 OnSize 中記錄新尺寸,然後在 OnDraw 中根據當前客戶區大小按比例重新繪圖即可。

為什麼不需要 MoveWindow?

  • 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?

場景是否需 MoveWindow說明
對話框/表單視圖調整子控件佈局是在 OnSize 中調用子控件 MoveWindow 實現自適應佈局
分割視圖調整分割條位置是CSplitterWnd::SetRowInfo/SetColumnInfo 內部調用 MoveWindow
純繪圖視圖(CView 衍生)否僅在 OnDraw 中按比例繪圖,無子控件需移動

常見誤區

  1. 誤以為 OnSize 必須調用 MoveWindow → 導致遞歸調用或錯誤佈局。
  2. 在 OnDraw 中調用 MoveWindow → 觸發重繪循環,程序卡死。
  3. 混淆「視圖縮放」(繪圖內容縮放)與「控件佈局」(子窗口位置調整)。

記住:繪圖靠 OnDraw + 映射模式/手動縮放,佈局靠 OnSize + MoveWindow。兩者職責分離,按場景選用。

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