=============《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是向下移动一行。那现在如果我要写响应将滚动条向下移动一行的代码,该如何写呢?看看下面的代码:
- case WM_VSCROLL: //响应垂直滚动条操作的消息
- switch(LOWORD(wParam))
- {
- case SB_DOWN: //向下移动通知码标识符
- //程序执行代码
- break;
- }
头痛呀,本来有着很清晰的思路,但现在无缘无故多了个LOWORD,书中的前面几章也没讲这东西,只说了这是一个宏,在用GetSystemMetrics获取窗体显示区域大小时,到是用过LOWORD宏,除此之外还有一个HIWORD宏。
- case WM_SIZE:
- x = LOWORD(lParam);
- 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); //获取卷动方块的位置
下面给个简单的示例代码:
- 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_TOP: //将卷动方块移置顶部
- iVscrollPos = 0;
- break;
- case SB_BOTTOM: //将卷动方块移置底部
- break;
- case SB_THUMBPOSITION: //拖动卷动方块释放鼠标后
- break;
- case SB_THUMBTRACK: //托运卷动方块
- break;
- case SB_ENDSROLL: //完成滚动操作?
- break;
- }
上面的代码只是修改了iVscrollPos的值,要想让滚动条发生视觉改变,还得使用SetScrollPos来重新定位卷动方块的位置。
- //用min和max宏来调控iVscrollPos,确保iVscrollPos的值在SetScrollRange设置的范围之内
- iVscrollPos = max (0, min (iVscrollPos, NUMLINES - 1)) ;
- if (iVscrollPos != GetScrollPos (hwnd, SB_VERT)) //如果卷动方块有变动
- {
- //SB_VERT表示设置垂直滚动条的卷动方块位置,用SB_HORZ标识符是设置水平滚动条的卷动方块位置
- SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
- //滚动条的卷动方块已经作了改变,现在得设置重绘显示区域大小了
- //在这里是使用InvalidateRect来设置整个显示区域为无效,即重绘整个显示区域
- InvalidateRect (hwnd, NULL, TRUE) ;
- }
好了,这第一种控制滚动条的方法就这么着了,其实就用到了SetScrollPos和SetScrollRange两个函数,相对比较简单。书中说这是一种很古老的方法了,在WIN32 API中新提供了两个操作滚动条的函数:SetScrollInfo和GetScrollInfo函数。这两个函数可以完成上面几个函数的功能,而且还多了两个特性:
第一个特性
可以修改卷动方块大小,主要是修改卷动方块的高度。
第二个特性
可以接受32位参数。在前面的方法中,是在一个32位数据类型中提取一个16位低位字和一个16位高位字来获取滚动条的各种信息,比如卷动方块位置,通知码等,而使用WIN32 API中这两个新的函数可以直接接受32位的参数。
三、控制滚动条方法二
……
以下约有二千字左右的内容,因博客保存文章失败,导致内容丢失,也懒得再打了。以后需要用到这方面的应用时再补上
……