C++實(shí)例:SDK中控制滾動條

字號:

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ù)。