专栏导航
上一篇:第4章,[标签 Win32] :SysMets3 程序讲解01
下一篇:第4章,[标签 Win32] :SysMets3 程序讲解03,垂直滚屏原理
本节前言
对于本节所讲解的知识,有可能,你会需要时不时地参考本专栏的其它文章。真的遇到了需要参考之前的文章的知识点,请你自行查阅。
我呢,也会提到一部分的参考课节。但是呢,你不应该依赖于我的主动提及。最好呢,你自己能够多去了解和查看本专栏目录。
关于 SysMets3,我个人认为,这是一个比较难的程序。我也认为,这个程序,需要讲解的地方有很多。
本节,我们要来讲解的是,窗口过程函数中的 iVertPos 变量。具体地,本节,我们是讲,在窗口过程函数中,处理 WM_VSCROLL 时候,iVertPos 的使用。
WM_HSCROLL 消息中,iVertPos 变量的运用,我就不讲了,因为它与 WM_VSCROLL 消息中的使用方法是一个道理。这就需要你举一反三了。不会的话请自行掌嘴。
我们开始。
一. 不同的通知码 中的iVertPos 变量
这一部分,我认为是比较简单的。
图1
档窗口过程接收到 WM_VSCROLL 以后,首先呢,要获取滚动条的信息,所用的掩码,是 SIF_ALL 。也就是,要获取 SIF_RANGE,SIF_PAGE,SIF_POS,SIF_TRACKPOS 几个标志所对应的信息。函数返回时,滚动条的范围,页面大小,位置,跟踪位置,就全都包含在滚动条结构体 SCROLLINFO 的变量 si 的对应字段中了。
其中,si.nPos,保存的,便是滚动条的原本的位置值。
注意哦,是原本的位置值。我们无论是拖动滚动条滑块,还是单击垂直滚动条滑块上下的空白位置,在窗口过程函数执行到 111 行的时候,si.nPos,所保存的值,都是滚动条滑块原来的位置值,而不是处理好以后的位置值。
所以呢,在程序的 115 行位置,iVertPos 变量,所保存的,是滚动条滑块的旧位置值,简称旧位置。
获取了滑块的旧位置以后,接下来,是针对不同的通知码,来对 si.nPos 作出不同的处理。我们来看代码截图。
图2
图3
如果通知码是 SB_LINEUP 和 SB_LINEDOWN,那就分别让 si.nPos 减 1 和 加 1 。也就是,单击滚动条上方的向上三角号,产生的滚动条消息的通知码是 SB_LINEUP,程序对其的处理是让 si.nPos 减 1 。单击滚动条下方的向下三角号,产生的滚动条消息的通知码是 SB_LINEDOWN,程序对其的处理是让 si.nPos 加 1 。
对于其余的通知码,我们也在下方一并阐述。
单击滚动条滑块的上方,而又位于滚动条区域的空白位置,产生的滚动条消息的通知码是 SB_PAGEUP,程序对其的处理是,令 si.nPos 减去页面大小 si.nPage 。
单击滚动条滑块的下方,而又位于滚动条区域的空白位置,产生的滚动条消息的通知码是 SB_PAGEDOWN,程序对其的处理是,令 si.nPos 加上页面大小 si.nPage 。
滚动滚动条滑块,则在我们拖动滚动条滑块时,滑块的动态位置会由系统自动保存在 si.nTrackPos 中,并且程序会产生通知码为 SB_THUMBTRACK 的滚动条消息。程序对其的处理是,将滑块的动态位置 si.nTrackPos 保存在 si.nPos 中。
对于 SB_TOP 和 SB_BOTTOM,其实这是在使用了键盘接口以后,才会涉及的东西。具体知识,我们在键盘章节再来细说。本节暂不讨论这俩通知码,而仅仅是在程序中给它俩留个位置。
根据不同的通知码,对 si.nPos 进行了赋值以后,程序窗口中的滚动条位置,还并未发生改变。想要使得修改后的 si.nPos 变为滚动条的新位置,我们还需要通过调用 SetScrollInfo 函数,来设置滚动条的位置。对此,我们在下一节来展开。
二. 滚动条位置的设置与再获取
当我们在图2 和图3 所对应的代码里面,根据不同的通知码,设置好了 si.nPos 以后,我们还需要通过调用 SetScrollInfo 函数,来设置滚动条的新位置。我们来看代码截图。
图4
图4 中,代码 153 行和 154 行,是通过设置掩码 SIF_POS,来调用 SetScrollInfo 函数,来设置滚动条的新位置的。这里,SetScrollInfo 函数的第四个参数是 TRUE,也就是,调用此函数的时候,要求重绘滚动条。之所以在此处设置重绘标志,是因为,此 SetScrollInfo 函数以后,再无其他的 SetScrollInfo 函数,所以,直接设置 TRUE 重绘标志即可。
153 行和 154 行的执行,会让 si.nPos 的值,设置为滚动条的新位置。
有意思的地方来了。设置好了滚动条位置以后,在程序的 155 行,再一次执行了 GetScrollInfo 函数。为何要再次获取呢?
这是因为,我们在 154 行调用 SetScrollInfo 函数以后,滚动条的新位置,不见得就是调用时的 si.nPos 值。
为何调用 SetScrollInfo 函数时候的 si.nPos 值,与调用结束之后的 si.nPos 值不见得会一致呢?
假定,页面大小为 30,范围的最小值和最大值分别为 0 和 74,则根据 SetScrollInfo 和 GetScrollInfo API 函数的使用规则,Windows 会将滚动条滑块的最大值限定为 si.nMax - si.nPage + 1,也就是 74 - 30 + 1,45 。实际的滚动条滑块位置值可以等于 45,但是不可以大于 45 。可以等于 0,但不可以小于 0 。我们还假定,在某一程序静止时刻,滚动条滑块的位置是 36,然后呢,在后续的某一时刻,我们单击了一下滑块下方的空白位置。这时,按照正常的逻辑,程序会让 si.nPos,也就是位置值 36,加上页面大小 30,结果为 66 。可是,滚动条滑块位置的最大值被限定为 45,66 大于 45 。由此,Windows 会帮我们重新设置 si.nPos 的值,令其 等于 45 。
再比如,页面大小为 30,范围的最小值和最大值分别为 0 和 74,则根据 SetScrollInfo 和 GetScrollInfo API 函数的使用规则,Windows 会将滚动条滑块的最大值限定为 si.nMax - si.nPage + 1,也就是 74 - 30 + 1,45 。实际的滚动条滑块位置值可以等于 45,但是不可以大于 45 。可以等于 0,但不可以小于 0 。我们还假定,在某一程序静止时刻,滚动条滑块的位置是 10,然后呢,在后续的某一时刻,我们单击了一下滑块上方的空白位置。这时,按照正常的逻辑,程序会让 si.nPos,也就是位置值 10,减去页面大小 30,结果为 -20 。可是,滚动条的范围最小值是 0,-20 小于 0 。由此,Windows 会帮我们重新设置 si.nPos 的值,令其 等于 0 。
这就是我们在调用了 SetScrollInfo 函数以后,需要再次调用 GetScrollInfo 函数,来获取滚动条滑块的新位置值的原因。
结束语
本节,是我原创的部分,佩措尔德原教材里面是没有讲的。之所以没有讲,我估计,佩措尔德先生觉得这太简单,太小儿科了,所以,就没有去讲。
对于大神来讲,许多的代码块,常人看起来有一定难度的东西,他们可能会认为简单得不值一提。
在我这里,我也不见得什么代码块都讲。不过,我还是会尝试着多讲一些。以便说,能理解的人,不需要我的讲解的人,可以学好。未能够凭借自己的能力来理解的人,通过我的讲解,也能够学好。
讲课时,应当在合理范围内,尽量地本着低心态,照顾每一个学习者吧。