| 參數 | 說明 | 範例值 |
nMapMode | 映射模式 | MM_TEXT (像素)、MM_HIMETRIC (0.01mm) |
sizeTotal | 邏輯文檔總大小 (決定捲動範圍) | CSize(3840, 2160) (3x 1080p) |
sizePage | 頁面捲動量 (Page Up/Down、滾輪) | CSize(1280, 720) (1x 螢幕) |
sizeLine | 行捲動量 (方向鍵、滾輪微調) | CSize(25, 15) |
鍵盤導航支援:OnKeyDown 處理方向鍵、Home/End、Page Up/Down
void CMyView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch (nChar)
{
case VK_HOME: // 捲動到最左上
OnScroll(SB_VERT, SB_TOP, 0);
OnScroll(SB_HORZ, SB_TOP, 0);
break;
case VK_END: // 捲動到最右下
OnScroll(SB_VERT, SB_BOTTOM, 0);
OnScroll(SB_HORZ, SB_BOTTOM, 0);
break;
case VK_UP: // 向上一行
OnScroll(SB_VERT, SB_LINEUP, 0);
break;
case VK_DOWN: // 向下一行
OnScroll(SB_VERT, SB_LINEDOWN, 0);
break;
case VK_PRIOR: // Page Up (向上一頁)
OnScroll(SB_VERT, SB_PAGEUP, 0);
break;
case VK_NEXT: // Page Down (向下一頁)
OnScroll(SB_VERT, SB_PAGEDOWN, 0);
break;
case VK_LEFT: // 向左一頁 (水平捲動通常較大步長)
OnScroll(SB_HORZ, SB_PAGEUP, 0);
break;
case VK_RIGHT: // 向右一頁
OnScroll(SB_HORZ, SB_PAGEDOWN, 0);
break;
default:
CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}
}
繪製邏輯:OnDraw 使用邏輯座標
void CMyView::OnDraw(CDC* pDC)
{
// pDC 已自動設定 viewport origin 對應捲動位置
// 直接使用邏輯座標繪製
// 範例:在文檔中心繪製一個大矩形
int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);
int cyScreen = ::GetSystemMetrics(SM_CYSCREEN);
// 文檔中心點 (邏輯座標)
int xCenter = cxScreen * 3 / 2; // 1.5 螢幕寬
int yCenter = cyScreen * 3 / 2; // 1.5 螢幕高
// 矩形大小:600x600 邏輯單位
CRect rect(xCenter - 300, yCenter - 300, xCenter + 300, yCenter + 300);
pDC->SelectStockObject(GRAY_BRUSH);
pDC->Rectangle(rect);
// 可在此繪製更多文檔內容...
}
座標系統關鍵概念
| 座標系 | 來源 | 用途 |
| 裝置座標 | 螢幕像素 | 視窗操作、滑鼠訊息 |
| 用戶區座標 | 視窗左上角為原點 | 視窗內部佈局 |
| 邏輯座標 (文檔座標) | SetScrollSizes 定義的總尺寸空間 | OnDraw 繪製、捲動計算、列印 |
CScrollView 自動處理:OnPrepareDC 設定 SetViewportOrg 將邏輯座標映射到用戶區座標。開發者在 OnDraw 中直接使用邏輯座標即可。
進階技巧
1. 動態調整捲動範圍 (文檔大小變更時)
void CMyView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
{
// 文檔資料變更,重新計算總尺寸
CSize newTotal = CalculateDocumentSize(); // 自訂函式
SetScrollSizes(MM_TEXT, newTotal); // sizePage/sizeLine 保持不變
}
2. 滑鼠滾輪支援 (WM_MOUSEWHEEL)
BOOL CMyView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
// zDelta > 0 向上,< 0 向下,標準值 120 (WHEEL_DELTA)
int nLines = zDelta / 120; // 正負號表示方向
for (int i = 0; i < abs(nLines); ++i)
{
OnScroll(SB_VERT, nLines > 0 ? SB_LINEUP : SB_LINEDOWN, 0);
}
return TRUE;
}
3. 列印支援:OnPrepareDC 設定映射模式
void CMyView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CScrollView::OnPrepareDC(pDC, pInfo);
if (pInfo) // 列印時
{
// 可調整映射模式適應紙張
// pDC->SetMapMode(MM_HIMETRIC);
}
}
常見問題排查
| 現象 | 原因 | 解決 |
| 捲動條不出現 | sizeTotal 小於等於視窗客戶區 | 確保 sizeTotal > 視窗尺寸,或強制 EnableScrollBarCtrl(SB_BOTH, TRUE) |
| 捲動後繪製位置錯誤 | OnDraw 使用裝置/用戶區座標而非邏輯座標 | OnDraw 僅使用邏輯座標,CScrollView 自動處理映射 |
| 鍵盤導航無效 | 焦點不在視圖、未處理 WM_KEYDOWN | 視圖 SetFocus()、確認訊息映射 ON_WM_KEYDOWN() |
| 列印內容截斷 | 邏輯尺寸過大、映射模式不匹配 | OnPrepareDC 設定適當映射模式、OnPrint 分頁處理 |
結語
CScrollView 透過 SetScrollSizes 一行核心代碼即可建立完整捲動機制,配合 OnKeyDown 實現鍵盤導航,OnDraw 使用邏輯座標繪製。掌握「總尺寸、頁面尺寸、行尺寸」三參數含義,即可靈活應對各種大文檔瀏覽需求。現代高 DPI 環境下,建議搭配 GetSystemMetrics(SM_CXSCREEN) 動態計算尺寸,或使用 MM_HIMETRIC 等實體單位映射模式確保列印輸出尺寸正確。
- 上一篇文章: MFC MDI 應用程式實現動畫背景旗幟:CWnd 派生客戶區類 + 定時器幀動畫 + 滑鼠互動
- 下一篇文章: Windows 動畫特技實作:淡入淡出效果完整指南
Copyright ©
程式碼之家 All Rights Reserved