問題:CView 中繪製的網格線、圖形、坐標軸,滾動條滾動後消失。原因:OnDraw 未根據滾動位置計算繪製區域。
OnDraw(CDC* pDC) 接收的 pDC 已經根據滾動位置設置了 視口原點 (SetViewportOrg)。MoveTo(100,100)) 會自動映射到正確的屏幕像素。OnDraw 中用邏輯座標完整繪製整個文檔內容,系統自動裁剪可見區域。MM_LOENGLISH 或 MM_TEXT) 並設定文檔大小 SetScrollSizes。OnDraw 並傳遞已偏移的 DC。// MyView.h
class CMyView : public CView {
DECLARE_DYNCREATE(CMyView)
protected:
CSize m_docSize; // 文檔邏輯大小
public:
virtual void OnDraw(CDC* pDC);
virtual void OnInitialUpdate();
};
// MyView.cpp
void CMyView::OnInitialUpdate() {
CView::OnInitialUpdate();
m_docSize = CSize(2000, 2000); // 邏輯單位 (0.01mm)
SetScrollSizes(MM_LOENGLISH, m_docSize);
}
void CMyView::OnDraw(CDC* pDC) {
// 1. 繪製網格 (每 100 邏輯單位一條線)
CPen penGrid(PS_DOT, 1, RGB(200,200,200));
CPen* pOldPen = pDC->SelectObject(&penGrid);
for (int x = 0; x <= m_docSize.cx; x += 100) {
pDC->MoveTo(x, 0);
pDC->LineTo(x, m_docSize.cy);
}
for (int y = 0; y <= m_docSize.cy; y += 100) {
pDC->MoveTo(0, y);
pDC->LineTo(m_docSize.cx, y);
}
// 2. 繪製坐標軸 (紅色粗線)
CPen penAxis(PS_SOLID, 2, RGB(255,0,0));
pDC->SelectObject(&penAxis);
pDC->MoveTo(0, m_docSize.cy/2);
pDC->LineTo(m_docSize.cx, m_docSize.cy/2); // X軸
pDC->MoveTo(m_docSize.cx/2, 0);
pDC->LineTo(m_docSize.cx/2, m_docSize.cy); // Y軸
pDC->SelectObject(pOldPen);
}
SetScrollSizes(MM_LOENGLISH, totalSize) 建立文檔大小與滾動範圍映射。OnDraw 使用邏輯座標 (如 1000 代表 1 英吋),而非設備像素。pDC->GetClipBox() 裁剪不可見部分,無需手動判斷。OnDraw 開頭獲取 CRect clipRect; pDC->GetClipBox(&clipRect); 僅繪製相交對象。OnHScroll/OnVScroll 中手動 Invalidate() 並試圖計算偏移繪製 → 複雜且易錯。MM_TEXT (像素模式) 但未自行處理偏移 → 滾動後圖形位置錯亂。遵循「文檔座標系 + OnDraw 全繪 + MFC 自動裁剪」模式,滾動重繪即可正常工作。