背景
在畢業快一年的工作時間中,對windows編程的某些特性並不夠熟悉,例如滾動條的使用。在一次需求中需要用到滾動條,在開發過程中走了不少彎路,因此需要做一些筆記總結一下學習到的內容。
先推薦幾個寫的特別好的博客:
Windows編程之滾動條—滾動條消息
C語言Windows程序設計-> 第八天-> 滾動條
三、Windows編程之滾動條—滾動條信息函數
基本滾動條的使用是非常簡單的,無法就那么幾個步驟
- 判斷是否需要滾動條,並初始化滾動條,比如頁面大小等變量。
如: EnableScrollBarCtrl
和SetScrollInfo
等API, SetScrollInfo
用於設置滾動條的相關參數, 包括滾動范圍的最大值和最小值, 頁面大小, 滑塊的位置。
typedef struct tagSCROLLINFO
{
UINT cbSize ; //設置為sizeof (SCROLLINFO), 表示該結構的大小
UINT fMask ; //要設置或獲取的值
int nMin ; //滾動條范圍的最小值
int nMax ; //滾動條范圍的最大值
UINT nPage ; //頁面大小
int nPos ; //當前位置
int nTrackPos ; //當前追蹤位置
}SCROLLINFO;
fMask中我們常用的是 SIF_ALL(是SIF_RANGE、SIF_POS、SIF_PAGE和SIF_TRACKPOS的組合),
在win32中,滾動條的長度和窗口的長度是成一定比例的。如下公式所控制:
- 對滾動條的消息處理,例如幾個典型的消息:
SB_LINEDOWN
、SB_LINEUP
、SB_THUMBPOSITION
、SB_THUMBTRACK
; 以及SB_PAGEDOWN
等之類的消息。主要邏輯就是在滾動條移動時,要更新子窗口相對於父窗口的位置(如,調用MoveWindow
函數等)。
鼠標滑輪的消息,在MFC的CWnd窗口中,捕獲滑輪消息,轉發滾動條消息:
BOOL CxxxxWnd::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if (m_bEnableVScroll)
{
if (zDelta > 0)
{
PostMessage(WM_VSCROLL, SB_LINEUP, 0);
}
else
{
PostMessage(WM_VSCROLL, SB_LINEDOWN, 0);
}
}
return __super::OnMouseWheel(nFlags, zDelta, pt);
}
常用的滾動條消息如下:
開發過程中遇到的問題
-
帶滾動條的窗口的窗口結構
之前不太曉得帶滾動條的窗口的窗口結構,帶滾動條的窗口一定是有子窗口的。滑動的時候,改變子窗口的相對位置。參考一張圖:
-
如何使滾動條可以拖拽?
主要是對SB_THUMBPOSITION
和SB_THUMBTRACK
消息的處理。當把鼠標的光標放在卷動方塊上並按住鼠標鍵時,您就可以移動卷動方塊。這樣就產生了帶有SB_THUMBTRACK
和SB_THUMBPOSITION
通知碼的滾動條消息。在wParam
的低字組是SB_THUMBTRACK
時,wParam
的高字組是使用者在拖動卷動方塊時的目前位置。該位置位於卷動列范圍的最小值和最大值之間。在wParam
的低字組是SB_THUMBPOSITION
時,wParam
的高字組是使用者釋放鼠標鍵后卷動方塊的最終位置。
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
bSuccess = GetScrollInfo(SB_VERT, &si);
si.fMask = SIF_POS;
si.nPos = si.nTrackPos;
bSuccess = SetScrollInfo(SB_VERT, &si);
//按照成員變量nPos的消息移動子窗口位置即可....
Invalidate();
}
break;