在SDK中如何控制滚动条

=============《Windows 程序设计 第五版》读书笔记 ||  第四章 输出文字 =============

总算领略到SDK的复杂性了,所谓复杂性,即在一个程序中,大大小小的事情都得程序编写者亲力亲为,Windows帮的忙很少,我在想,要是使用文本框之类的组件也得一句一句的写滚动条控制代码,那不累死!

一、滚动条细节问题

滚动条这玩意儿众所周知了,一个滚动条由三个部分组成:向上(左)移动按钮、卷动方块和向下(右)移动按钮,刚看到书上说这个「卷动方块」时还差点儿没明白过来。

滚动条上常用的有五种操作:

1.点击向上(左)移动按钮,向上(左)移动一行

2.点击向下(右)移动按钮,向下(右)移动一行

3.点击卷动方块上方空白处,向上翻一页

4.点击卷动方块下方空白处,向下翻一页

5.拖动卷动方块

 

滚动条分水平滚动条和垂直滚动条,在Windows中就对应WM_HSCROLL和WM_VSCROLL两种消息,其中WM_HSCROLL是供左右移动的消息,WM_VSCROLL是供上下移动的消息。也就是说,响应滚动条的五种操作都是在这两个消息下执行的,比如当用户对垂直滚动条进行操作时,就会给Windows发出一个WM_VSCROLL消息,至于对这个垂直滚动条具体执行的是什么操作,是向上移动一行还是向下移动一行,这就要引出一个「通知码」的概念。

这个「通知码」是怎么来的呢?当发送WM_VSCROLL或WM_HSCROLL消息时,会附带有wParam和lParam参数。其中lParam的作用没太弄明白,至于wParam参数,其分为一个低位字和高位字,我对这两个概念的认识也比较模糊。其中低字组是一个数值,而这个数值就是「通知码」。

「通知码」是以SB(scroll bar)开头的标识符定义(全是大写名称),这些标识符比较好理解,比如SB_UP向上移动一行,SB_DOWN是向下移动一行。那现在如果我要写响应将滚动条向下移动一行的代码,该如何写呢?看看下面的代码:

  1. case WM_VSCROLL: //响应垂直滚动条操作的消息
  2.     switch(LOWORD(wParam))
  3.     {
  4.         case SB_DOWN: //向下移动通知码标识符
  5.              //程序执行代码
  6.              break;
  7.     }

头痛呀,本来有着很清晰的思路,但现在无缘无故多了个LOWORD,书中的前面几章也没讲这东西,只说了这是一个宏,在用GetSystemMetrics获取窗体显示区域大小时,到是用过LOWORD宏,除此之外还有一个HIWORD宏。

  1. case WM_SIZE: 
  2.     x = LOWORD(lParam); 
  3.     y = HIWORD(lParam);

上面这段代码就是用来获取窗体显示区域的宽度和高度,不过使用的参数是lParam。看来要想明明白白的继续滚动条其它的知识点,还得先弄清楚这两个宏,另外还有lParam和wParam这两个参数,也是很常见的参数,得弄清楚。

先了解一下lParam和wParam两个参数,lParam是一个UINT数据类型(unsigned int),wParam是一个LONG数据类型。在这两个参数中分别包含一个16位低位字和一个16位高位字。通过sizeof计算出,一个UINT类型占用4个字节,一个LONG也是占用4个字节,因为1个字节等于8比特,那4个字节的数据类型就是32比特,由此可知UINT和LONG是32位数据类型。我的基础知识不牢,又不得不恶补了一下。知道了lParam和wParam是32位数据类型,再来说说16位低位字和16位高位字。

其中LOWORD是获取一个16位低位字,HIWORD是获取一个16位高位字,我估摸着就是将一个32位的数据类型分解成两个16位数据类型。

通过wParam的低位字和高位字就能获取滚动条的「通知码」和卷动方块位置。

wParam低位值                       wParam高位值

SB_THUMBTRACK            卷动方块时的目前位置

SB_THUMBPOSITION       使用者释放鼠标键后卷动方块的最终位置

其它的卷动列操作                忽略

这样一来就明白了上面switch语句的作用。

二、控制滚动条操作方法一

SetScrollRange (hwnd, iBar, iMin, iMax, bRedraw) ; //设置滚动条卷动方块滚动范围

SetScrollPos (hwnd, iBar, iPos, bRedraw) ; //设置卷动方块的位置

BOOL GetScrollRange(HWND hWnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos); //获取滚动条卷动广场滚动范围

int GetScrollPos(HWND hWnd, int nBar); //获取卷动方块的位置

下面给个简单的示例代码:

  1. int iVscrollPos; //滚动条卷动方块位置
  2. SetScrollRange (hwnd, SB_VERT, 0, 20, FALSE) ; //滚动条最大范围为20
  3. SetScrollPos   (hwnd, SB_VERT, iVscrollPos, TRUE) ; //初始化滚动条位置
  4. case WM_VSCROLL: //垂直滚动条操作消息
  5.     switch (LOWORD (wParam))  //wParam 16位低位值,即「通知码」
  6.     {
  7.         case SB_LINEDOWN: //滚动条向下移动一行
  8.             iVscrollPos += 1;
  9.             break;
  10.         case SB_LINEUP:  //滚动条向上移动一行
  11.             iVscrollPos -= 1;
  12.             break;
  13.         case SB_PAGEDOWN:  //滚动条向下翻一页
  14.             break;
  15.         case SB_PAGEUP:  //滚动条向上翻一页
  16.             break;
  17.         case SB_TOP:  //将卷动方块移置顶部
  18.             iVscrollPos = 0;
  19.             break;
  20.         case SB_BOTTOM:  //将卷动方块移置底部
  21.             break;
  22.         case SB_THUMBPOSITION: //拖动卷动方块释放鼠标后
  23.             break;
  24.         case SB_THUMBTRACK:  //托运卷动方块
  25.             break;
  26.         case SB_ENDSROLL:  //完成滚动操作?
  27.             break;
  28.     }

上面的代码只是修改了iVscrollPos的值,要想让滚动条发生视觉改变,还得使用SetScrollPos来重新定位卷动方块的位置。

  1. //用min和max宏来调控iVscrollPos,确保iVscrollPos的值在SetScrollRange设置的范围之内
  2. iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ; 
  3.         
  4. if (iVscrollPos != GetScrollPos (hwnd, SB_VERT)) //如果卷动方块有变动
  5.     {
  6.         //SB_VERT表示设置垂直滚动条的卷动方块位置,用SB_HORZ标识符是设置水平滚动条的卷动方块位置
  7.         SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
  8.         //滚动条的卷动方块已经作了改变,现在得设置重绘显示区域大小了
  9.         //在这里是使用InvalidateRect来设置整个显示区域为无效,即重绘整个显示区域
  10.         InvalidateRect (hwnd, NULL, TRUE) ;
  11.     }

好了,这第一种控制滚动条的方法就这么着了,其实就用到了SetScrollPos和SetScrollRange两个函数,相对比较简单。书中说这是一种很古老的方法了,在WIN32 API中新提供了两个操作滚动条的函数:SetScrollInfo和GetScrollInfo函数。这两个函数可以完成上面几个函数的功能,而且还多了两个特性:

第一个特性

可以修改卷动方块大小,主要是修改卷动方块的高度。

第二个特性

可以接受32位参数。在前面的方法中,是在一个32位数据类型中提取一个16位低位字和一个16位高位字来获取滚动条的各种信息,比如卷动方块位置,通知码等,而使用WIN32 API中这两个新的函数可以直接接受32位的参数。

三、控制滚动条方法二

……

以下约有二千字左右的内容,因博客保存文章失败,导致内容丢失,也懒得再打了。以后需要用到这方面的应用时再补上

……

posted @ 2008-10-17 15:31  冷寒生  阅读(832)  评论(0编辑  收藏  举报
IT知识库