在 MFC 對話框中啟用滾動條(屬性頁勾選 Horizontal/Vertical Scroll)後,滾動條無控件 ID,無法通過 DDX 綁定變量。直接在 OnHScroll/OnVScroll 中使用 pScrollBar->GetScrollPos() 會失效,因為對話框的 m_hWnd 未正確關聯。
OnInitDialog 中調用 SetScrollRange(SB_HORZ/VERT, 0, 100) 設置範圍;::GetScrollPos(m_hWnd, SB_HORZ) / ::SetScrollPos(m_hWnd, SB_HORZ, pos) 讀寫位置;ScrollWindow(dx, dy) 滾動客戶區內容;pScrollBar,僅根據 nSBCode 計算新位置。BOOL CTestDlgDlg::OnInitDialog() {
CDialog::OnInitDialog();
SetScrollRange(SB_HORZ, 0, 100);
SetScrollRange(SB_VERT, 0, 100);
return TRUE;
}
void CTestDlgDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) {
int nPrevPos = GetScrollPos(SB_HORZ);
int nCurPos = nPrevPos;
CRect rect; GetClientRect(&rect);
switch (nSBCode) {
case SB_LEFT: nCurPos = 0; break;
case SB_RIGHT: nCurPos = 100; break;
case SB_PAGELEFT: nCurPos = max(0, nPrevPos - 10); break;
case SB_PAGERIGHT: nCurPos = min(100, nPrevPos + 10); break;
case SB_THUMBPOSITION: nCurPos = nPos; break;
case SB_LINELEFT: nCurPos = max(0, nPrevPos - 2); break;
case SB_LINERIGHT: nCurPos = min(100, nPrevPos + 2); break;
case SB_THUMBTRACK: /* 拖動時不更新,待 SB_ENDSCROLL 處理 */ break;
case SB_ENDSCROLL: break;
}
SetScrollPos(SB_HORZ, nCurPos);
ScrollWindow(rect.Width() * (nPrevPos - nCurPos) / 100, 0);
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
// OnVScroll 邏輯同理,僅將 SB_HORZ 改 SB_VERT,Width 改 Height,x 位移改 y 位移
ScrollWindow 參數為像素位移,需根據客戶區寬高與滾動範圍 (0-100) 線性映射;SB_THUMBTRACK 可選擇實時滾動或延遲至 SB_ENDSCROLL,視繪製開銷決定;SetScrollRange 最大值,而非寫死 100。若內容極其複雜,可在對話框中嵌入 CFormView,利用其自帶滾動條與視圖架構,減少手動座標計算。但會增加框架複雜度,視項目權衡。