首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

MFC 建立捲動視圖:CScrollView 完整應用指南 (鍵盤導航、尺寸設定、OnDraw 繪製)

     編輯:VC 教學

何時需要 CScrollView?

當邏輯畫面尺寸超過螢幕可視區域 (如大型圖表、長文檔、地圖、CAD 圖面) 時,需提供捲動條讓使用者瀏覽完整內容。CScrollView 封裝了捲動條建立、訊息處理、座標轉換等繁瑣邏輯,是實現捲動視圖的標準選擇。

專案建立步驟

  1. AppWizard 建立 SDI/MDI 專案,選項勾選 Initial Toolbar、Generate Source Comments。
  2. 將預設產生的 CView 派生類改為 CScrollView 派生:
    • 檢視類別宣告:class CMyView : public CScrollView
    • 實作檔:IMPLEMENT_DYNCREATE(CMyView, CScrollView)
    • 訊息映射:基類改為 CScrollView。
  3. ClassWizard 加入 WM_CREATE、WM_KEYDOWN 訊息處理。

核心初始化:OnCreate 設定捲動尺寸


int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CScrollView::OnCreate(lpCreateStruct) == -1) return -1;

    // 1. 取得螢幕尺寸
    int cxScreen = ::GetSystemMetrics(SM_CXSCREEN);
    int cyScreen = ::GetSystemMetrics(SM_CYSCREEN);

    // 2. 設定邏輯總尺寸:螢幕的 3 倍 (可根據實際內容調整)
    CSize sizeTotal(cxScreen * 3, cyScreen * 3);

    // 3. 設定頁面捲動尺寸 (Page Up/Down、滾輪一頁)
    CSize sizePage(cxScreen, cyScreen); // 一頁 = 一個螢幕

    // 4. 設定行捲動尺寸 (方向鍵、滾輪一行)
    CSize sizeLine(cxScreen / 50, cyScreen / 50); // 1/50 螢幕

    // 5. 關鍵呼叫:設定捲動參數
    // 映射模式 MM_TEXT = 1 像素 = 1 邏輯單位
    SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);

    return 0;
}

SetScrollSizes 參數詳解

鍵盤導航支援: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);

    // 可在此繪製更多文檔內容...
}

座標系統關鍵概念

參數說明範例值
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)

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);
    }
}

常見問題排查

座標系來源用途
裝置座標螢幕像素視窗操作、滑鼠訊息
用戶區座標視窗左上角為原點視窗內部佈局
邏輯座標 (文檔座標)SetScrollSizes 定義的總尺寸空間OnDraw 繪製、捲動計算、列印
現象原因解決
捲動條不出現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 等實體單位映射模式確保列印輸出尺寸正確。

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