SDK的復(fù)雜性了,所謂復(fù)雜性,即在一個程序中,大大小小的事情都得程序編寫者親力親為,Windows幫的忙很少,我在想,要是使用文本框之類的組件也得一句一句的寫滾動條控制代碼,那不累死!
一、滾動條細(xì)節(jié)問題
滾動條這玩意兒眾所周知了,一個滾動條由三個部分組成:向上(左)移動按鈕、卷動方塊和向下(右)移動按鈕,剛看到書上說這個「卷動方塊」時還差點(diǎn)兒沒明白過來。
滾動條上常用的有五種操作:
1.點(diǎn)擊向上(左)移動按鈕,向上(左)移動一行
2.點(diǎn)擊向下(右)移動按鈕,向下(右)移動一行
3.點(diǎn)擊卷動方塊上方空白處,向上翻一頁
4.點(diǎn)擊卷動方塊下方空白處,向下翻一頁
5.拖動卷動方塊
滾動條分水平滾動條和垂直滾動條,在Windows中就對應(yīng)WM_HSCROLL和WM_VSCROLL兩種消息,其中WM_HSCROLL是供左右移動的消息,WM_VSCROLL是供上下移動的消息。也就是說,響應(yīng)滾動條的五種操作都是在這兩個消息下執(zhí)行的,比如當(dāng)用戶對垂直滾動條進(jìn)行操作時,就會給Windows發(fā)出一個WM_VSCROLL消息,至于對這個垂直滾動條具體執(zhí)行的是什么操作,是向上移動一行還是向下移動一行,這就要引出一個「通知碼」的概念。
這個「通知碼」是怎么來的呢?當(dāng)發(fā)送WM_VSCROLL或WM_HSCROLL消息時,會附帶有wParam和lParam參數(shù)。其中l(wèi)Param的作用沒太弄明白,至于wParam參數(shù),其分為一個低位字和高位字,我對這兩個概念的認(rèn)識也比較模糊。其中低字組是一個數(shù)值,而這個數(shù)值就是「通知碼」。
「通知碼」是以SB(scroll bar)開頭的標(biāo)識符定義(全是大寫名稱),這些標(biāo)識符比較好理解,比如SB_UP向上移動一行,SB_DOWN是向下移動一行。考試大提示:那現(xiàn)在如果要寫響應(yīng)將滾動條向下移動一行的代碼,該如何寫呢?看看下面的代碼:
case WM_VSCROLL: //響應(yīng)垂直滾動條操作的消息
switch(LOWORD(wParam))
{
case SB_DOWN: //向下移動通知碼標(biāo)識符
//程序執(zhí)行代碼
break;
}
頭痛呀,本來有著很清晰的思路,但現(xiàn)在無緣無故多了個LOWORD,書中的前面幾章也沒講這東西,只說了這是一個宏,在用GetSystemMetrics獲取窗體顯示區(qū)域大小時,到是用過LOWORD宏,除此之外還有一個HIWORD宏。
case WM_SIZE:
x = LOWORD(lParam);
y = HIWORD(lParam);
上面這段代碼就是用來獲取窗體顯示區(qū)域的寬度和高度,不過使用的參數(shù)是lParam??磥硪朊髅靼装椎睦^續(xù)滾動條其它的知識點(diǎn),還得先弄清楚這兩個宏,另外還有l(wèi)Param和wParam這兩個參數(shù),也是很常見的參數(shù),得弄清楚。
先了解一下lParam和wParam兩個參數(shù),lParam是一個UINT數(shù)據(jù)類型(unsigned int),wParam是一個LONG數(shù)據(jù)類型。在這兩個參數(shù)中分別包含一個16位低位字和一個16位高位字。通過sizeof計(jì)算出,一個UINT類型占用4個字節(jié),一個LONG也是占用4個字節(jié),因?yàn)?個字節(jié)等于8比特,那4個字節(jié)的數(shù)據(jù)類型就是32比特,由此可知UINT和LONG是32位數(shù)據(jù)類型。我的基礎(chǔ)知識不牢,又不得不惡補(bǔ)了一下。知道了lParam和wParam是32位數(shù)據(jù)類型,再來說說16位低位字和16位高位字。
其中LOWORD是獲取一個16位低位字,HIWORD是獲取一個16位高位字,我估摸著就是將一個32位的數(shù)據(jù)類型分解成兩個16位數(shù)據(jù)類型。
通過wParam的低位字和高位字就能獲取滾動條的「通知碼」和卷動方塊位置。
wParam低位值 wParam高位值
SB_THUMBTRACK 卷動方塊時的目前位置
SB_THUMBPOSITION 使用者釋放鼠標(biāo)鍵后卷動方塊的最終位置
其它的卷動列操作 忽略
這樣一來就明白了上面switch語句的作用。
二、控制滾動條操作方法
SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ; //設(shè)置滾動條卷動方塊滾動范圍
SetScrollPos (hwnd, iBar, iPos, bRedraw) ; //設(shè)置卷動方塊的位置
BOOL GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos); //獲取滾動條卷動廣場滾動范圍
int GetScrollPos(HWND hWnd, int nBar); //獲取卷動方塊的位置
下面給個簡單的示例代碼:
int iVscrollPos; //滾動條卷動方塊位置
SetScrollRange (hwnd, SB_VERT, 0, 20, FALSE) ; //滾動條范圍為20
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ; //初始化滾動條位置
case WM_VSCROLL: //垂直滾動條操作消息
switch (LOWORD (wParam)) //wParam 16位低位值,即「通知碼」
{
case SB_LINEDOWN: //滾動條向下移動一行
iVscrollPos += 1;
break;
case SB_LINEUP: //滾動條向上移動一行
iVscrollPos -= 1;
break;
case SB_PAGEDOWN: //滾動條向下翻一頁
break;
case SB_PAGEUP: //滾動條向上翻一頁
break;
case SB_: //將卷動方塊移置頂部
iVscrollPos = 0;
break;
case SB_BOTTOM: //將卷動方塊移置底部
break;
case SB_THUMBPOSITION: //拖動卷動方塊釋放鼠標(biāo)后
break;
case SB_THUMBTRACK: //托運(yùn)卷動方塊
break;
case SB_ENDSROLL: //完成滾動操作?
break;
}
上面的代碼只是修改了iVscrollPos的值,要想讓滾動條發(fā)生視覺改變,還得使用SetScrollPos來重新定位卷動方塊的位置。
//用min和max宏來調(diào)控iVscrollPos,確保iVscrollPos的值在SetScrollRange設(shè)置的范圍之內(nèi)
iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ;
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT)) //如果卷動方塊有變動
{
//SB_VERT表示設(shè)置垂直滾動條的卷動方塊位置,用SB_HORZ標(biāo)識符是設(shè)置水平滾動條的卷動方塊位置
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
//滾動條的卷動方塊已經(jīng)作了改變,現(xiàn)在得設(shè)置重繪顯示區(qū)域大小了
//在這里是使用InvalidateRect來設(shè)置整個顯示區(qū)域?yàn)闊o效,即重繪整個顯示區(qū)域
InvalidateRect (hwnd, NULL, TRUE) ;
}
好了,這第一種控制滾動條的方法就這么著了,其實(shí)就用到了SetScrollPos和SetScrollRange兩個函數(shù),相對比較簡單。書中說這是一種很古老的方法了,在WIN32 API中新提供了兩個操作滾動條的函數(shù):SetScrollInfo和GetScrollInfo函數(shù)。這兩個函數(shù)可以完成上面幾個函數(shù)的功能,而且還多了兩個特性:
第一個特性
可以修改卷動方塊大小,主要是修改卷動方塊的高度。
第二個特性
可以接受32位參數(shù)。在前面的方法中,是在一個32位數(shù)據(jù)類型中提取一個16位低位字和一個16位高位字來獲取滾動條的各種信息,比如卷動方塊位置,通知碼等,而使用WIN32 API中這兩個新的函數(shù)可以直接接受32位的參數(shù)。
一、滾動條細(xì)節(jié)問題
滾動條這玩意兒眾所周知了,一個滾動條由三個部分組成:向上(左)移動按鈕、卷動方塊和向下(右)移動按鈕,剛看到書上說這個「卷動方塊」時還差點(diǎn)兒沒明白過來。
滾動條上常用的有五種操作:
1.點(diǎn)擊向上(左)移動按鈕,向上(左)移動一行
2.點(diǎn)擊向下(右)移動按鈕,向下(右)移動一行
3.點(diǎn)擊卷動方塊上方空白處,向上翻一頁
4.點(diǎn)擊卷動方塊下方空白處,向下翻一頁
5.拖動卷動方塊
滾動條分水平滾動條和垂直滾動條,在Windows中就對應(yīng)WM_HSCROLL和WM_VSCROLL兩種消息,其中WM_HSCROLL是供左右移動的消息,WM_VSCROLL是供上下移動的消息。也就是說,響應(yīng)滾動條的五種操作都是在這兩個消息下執(zhí)行的,比如當(dāng)用戶對垂直滾動條進(jìn)行操作時,就會給Windows發(fā)出一個WM_VSCROLL消息,至于對這個垂直滾動條具體執(zhí)行的是什么操作,是向上移動一行還是向下移動一行,這就要引出一個「通知碼」的概念。
這個「通知碼」是怎么來的呢?當(dāng)發(fā)送WM_VSCROLL或WM_HSCROLL消息時,會附帶有wParam和lParam參數(shù)。其中l(wèi)Param的作用沒太弄明白,至于wParam參數(shù),其分為一個低位字和高位字,我對這兩個概念的認(rèn)識也比較模糊。其中低字組是一個數(shù)值,而這個數(shù)值就是「通知碼」。
「通知碼」是以SB(scroll bar)開頭的標(biāo)識符定義(全是大寫名稱),這些標(biāo)識符比較好理解,比如SB_UP向上移動一行,SB_DOWN是向下移動一行。考試大提示:那現(xiàn)在如果要寫響應(yīng)將滾動條向下移動一行的代碼,該如何寫呢?看看下面的代碼:
case WM_VSCROLL: //響應(yīng)垂直滾動條操作的消息
switch(LOWORD(wParam))
{
case SB_DOWN: //向下移動通知碼標(biāo)識符
//程序執(zhí)行代碼
break;
}
頭痛呀,本來有著很清晰的思路,但現(xiàn)在無緣無故多了個LOWORD,書中的前面幾章也沒講這東西,只說了這是一個宏,在用GetSystemMetrics獲取窗體顯示區(qū)域大小時,到是用過LOWORD宏,除此之外還有一個HIWORD宏。
case WM_SIZE:
x = LOWORD(lParam);
y = HIWORD(lParam);
上面這段代碼就是用來獲取窗體顯示區(qū)域的寬度和高度,不過使用的參數(shù)是lParam??磥硪朊髅靼装椎睦^續(xù)滾動條其它的知識點(diǎn),還得先弄清楚這兩個宏,另外還有l(wèi)Param和wParam這兩個參數(shù),也是很常見的參數(shù),得弄清楚。
先了解一下lParam和wParam兩個參數(shù),lParam是一個UINT數(shù)據(jù)類型(unsigned int),wParam是一個LONG數(shù)據(jù)類型。在這兩個參數(shù)中分別包含一個16位低位字和一個16位高位字。通過sizeof計(jì)算出,一個UINT類型占用4個字節(jié),一個LONG也是占用4個字節(jié),因?yàn)?個字節(jié)等于8比特,那4個字節(jié)的數(shù)據(jù)類型就是32比特,由此可知UINT和LONG是32位數(shù)據(jù)類型。我的基礎(chǔ)知識不牢,又不得不惡補(bǔ)了一下。知道了lParam和wParam是32位數(shù)據(jù)類型,再來說說16位低位字和16位高位字。
其中LOWORD是獲取一個16位低位字,HIWORD是獲取一個16位高位字,我估摸著就是將一個32位的數(shù)據(jù)類型分解成兩個16位數(shù)據(jù)類型。
通過wParam的低位字和高位字就能獲取滾動條的「通知碼」和卷動方塊位置。
wParam低位值 wParam高位值
SB_THUMBTRACK 卷動方塊時的目前位置
SB_THUMBPOSITION 使用者釋放鼠標(biāo)鍵后卷動方塊的最終位置
其它的卷動列操作 忽略
這樣一來就明白了上面switch語句的作用。
二、控制滾動條操作方法
SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ; //設(shè)置滾動條卷動方塊滾動范圍
SetScrollPos (hwnd, iBar, iPos, bRedraw) ; //設(shè)置卷動方塊的位置
BOOL GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos); //獲取滾動條卷動廣場滾動范圍
int GetScrollPos(HWND hWnd, int nBar); //獲取卷動方塊的位置
下面給個簡單的示例代碼:
int iVscrollPos; //滾動條卷動方塊位置
SetScrollRange (hwnd, SB_VERT, 0, 20, FALSE) ; //滾動條范圍為20
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ; //初始化滾動條位置
case WM_VSCROLL: //垂直滾動條操作消息
switch (LOWORD (wParam)) //wParam 16位低位值,即「通知碼」
{
case SB_LINEDOWN: //滾動條向下移動一行
iVscrollPos += 1;
break;
case SB_LINEUP: //滾動條向上移動一行
iVscrollPos -= 1;
break;
case SB_PAGEDOWN: //滾動條向下翻一頁
break;
case SB_PAGEUP: //滾動條向上翻一頁
break;
case SB_: //將卷動方塊移置頂部
iVscrollPos = 0;
break;
case SB_BOTTOM: //將卷動方塊移置底部
break;
case SB_THUMBPOSITION: //拖動卷動方塊釋放鼠標(biāo)后
break;
case SB_THUMBTRACK: //托運(yùn)卷動方塊
break;
case SB_ENDSROLL: //完成滾動操作?
break;
}
上面的代碼只是修改了iVscrollPos的值,要想讓滾動條發(fā)生視覺改變,還得使用SetScrollPos來重新定位卷動方塊的位置。
//用min和max宏來調(diào)控iVscrollPos,確保iVscrollPos的值在SetScrollRange設(shè)置的范圍之內(nèi)
iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ;
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT)) //如果卷動方塊有變動
{
//SB_VERT表示設(shè)置垂直滾動條的卷動方塊位置,用SB_HORZ標(biāo)識符是設(shè)置水平滾動條的卷動方塊位置
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
//滾動條的卷動方塊已經(jīng)作了改變,現(xiàn)在得設(shè)置重繪顯示區(qū)域大小了
//在這里是使用InvalidateRect來設(shè)置整個顯示區(qū)域?yàn)闊o效,即重繪整個顯示區(qū)域
InvalidateRect (hwnd, NULL, TRUE) ;
}
好了,這第一種控制滾動條的方法就這么著了,其實(shí)就用到了SetScrollPos和SetScrollRange兩個函數(shù),相對比較簡單。書中說這是一種很古老的方法了,在WIN32 API中新提供了兩個操作滾動條的函數(shù):SetScrollInfo和GetScrollInfo函數(shù)。這兩個函數(shù)可以完成上面幾個函數(shù)的功能,而且還多了兩個特性:
第一個特性
可以修改卷動方塊大小,主要是修改卷動方塊的高度。
第二個特性
可以接受32位參數(shù)。在前面的方法中,是在一個32位數(shù)據(jù)類型中提取一個16位低位字和一個16位高位字來獲取滾動條的各種信息,比如卷動方塊位置,通知碼等,而使用WIN32 API中這兩個新的函數(shù)可以直接接受32位的參數(shù)。

