MFC:窗口和滚动条的基情

来源:互联网 发布:yy挂机软件 编辑:程序博客网 时间:2024/06/16 01:31

MFC:窗口和滚动条的基情


创建带滚动条窗口的步骤:

以竖直方向的标准滚动条为例(横向方向和滚动条控件也类似):

1.创建一个基于对话框的MFC工程,或新建一个对话框资源,在对话框的属性-->外观 选项中把Vertical Scrollbar选项设为True。

滚动

2.在对话框的初始化函数中用SetScrollInfo函数设置滚动条的范围、页面大小、初始位置。

3.捕捉WM_VSCROLL消息,在消息处理函数OnVScroll中根据消息通知码设置滚动条的位置。

4.根据3中滚动条的位置变化调用ScroolWindow函数滚动窗口客户区。

5.ScrollWindow滚动窗口客户区后,Windows自动将滚动新出现的地方无效化,从而产生一条WM_PAINT消息。所以我们还需要在WM_PAINT的消息处理函数中自己绘制新出现的区域。

       ps:若在其他消息处理函数中滚动了窗口客户区,也要记得同步设置滚动条。


详细

要用滚动条,我们需要做什么?

      在程序中使用滚动条,需要程序和Windows共同负责维护滚动条以及滑块在滚动条中的位置。Windows负责的任务如下:

  • 1.处理滚动条中的所以鼠标消息。
  •  2.当用户单击滚动条时,提供一种方向显示的闪烁。
  •  3.当用户拖到滑块时,在滚动条内移动滑块。
  •  4.向拥有滚动条的窗口的窗口过程发现滚动条消息。

程序要负责的任务如下:

  •   1.初始化滚动条的范围和位置。
  •    2.处理传送给窗口过程的滚动条消息。
  •    3.更新滑块的位置。
  •    4.滚据滚动条的变换更新客户区的内容。

 

注意上面windows负责的第3条和程序要负责的第3条。小弟以前理所当然的认为windows应该会负责移动滑块并更新滑块的位置。后来发现如果自己不在消息处理函数中重新设置滑块的位置,当你移动滑块松开鼠标后,滑块会自己回到原来的地方。原来要程序自己负责更新滑块的位置。我现在还想不清楚为什么windows不负责这个,这个不是很简单吗?


滚动条的范围、滑块的位置和窗口客户区的映射:

        滚动条的范围是一对整数,分别代表滚动条的最大值和最小值。位置值滑块在范围中所处的值。当滑块在滚动条的最顶端的时候,滑块的位置是范围的最小值。相应的,滑块在滚动条的底部时,位置是范围的最大值。如果滑块在滚动条的中间,那位置的取值就是介于最大值和最小值的一个中间值了。默认状态下标准滚动条的范围是0~100,默认位置是0,可以通过SetScrollInfo函数来设置。而滚动条控件的默认范围是0~0。

       看来滚动条的范围与滑块的位置和窗口客户区半毛钱关系都没有,全靠我们让它们产生关系。要想让让窗口客户区的内容随着滑块的滑动发生变化,我们必须在滚动条的消息处理函数中或WM_PAINT的消息处理函数中自己重绘窗口客户区的内容。


滚动条消息:

当用户单击滚动条、单击滚动条上的尖头或拖动滑块时,Windows向窗口过程发送WM_VSCROLL消息(垂直滚动条)或WM_HSCROLL消息(水平滚动条)。像其他消息一样WM_VSCROLL消息也伴随着消息参数。不同的消息参数代表了鼠标在滚动条上不同的动作。如果是基于windows sdk的编程方式可以根据窗口过的wParam的地位字判断,如果是MFC中可以根据OnVScroll的nSBCode参数判断。参数如下:(只列举和垂直滚动条有关的)

  • SB_BOTTOM 滑到底部

  • SB_ENDSCROLL 滑动结束.

  • SB_LINEDOWN 向下滑动一行.

  • SB_LINEUP 向上滑动一行.

  • SB_PAGEDOWN 向下滑动一页.

  • SB_PAGEUP 向上滑动一页.

  • SB_THUMBPOSITION 滑动到了现在所在的位置,位置在nPos参数中提供       

  • SB_THUMBTRACK 滑块正在被拖动,滑块现在所处的位置由nPos参数提供

  • SB_TOP 滑块滑动到顶部了

    滚动

    附注:1.SB_THUMBPOSITION和SB_THUMBTRACK可能不好理解,前者是拖动滑块后,放开鼠标按键后才产生的消息。后者是在拖动滑块的过程中一直不停的产生的消息,直到你放开鼠标按键为止。

                  2.在滚动条上的任何鼠标动作都会至少产生两条消息:一条在鼠标按键按下时,另一条在鼠标按键松开时。按照小弟的经验任何动作结束时都会产生带有SB_ENDSCROLL参数的消息。


等等,上面的页面大小是什么?

      你也许注意到在你浏览网页或者有滚动条的对话框时,随着网页页面内容的变多,滑块大小会变小。因为滑块的大小与显示在窗口中内容的多少是成比例的。

关系为 :滑块大小/滚动条长度 约等于 页面大小/范围  约等于 窗口客户区大小/所有要显示的内容多少

    根据这个公式你可以决定什么时候该滚动窗口客户区的多少内容。


滚动条初始化建议:

        可以在初始化函数中设置滚动条的范围、位置、页面大小。比如WM_INITDIALOG、WM_CREATE的消息处理函数中设置。但建议在WM_SIZE消息的处理函数中设置。因为对话框创建后再WM_CREATE消息之后会紧接着发送一条WM_SIZE消息,在WM_SIZE小的处理函数中照样能初始化,而且窗口大小一般都会变化,每一次窗口客户区大小变化时,滚动条的页面大小和范围也要跟着变化才合理。


和滚动条相应的窗口客户区绘制建议:

      可以在处理滚动条消息是直接绘制客户区,但大师Charles Petzold的建议是:“程序应该把所有的客户区绘制工作都限制在处理WM_PAINT消息时。因为程序必须能在收到WM_PAINT消息时绘制整个客户区,因而在处理其他消息时进行绘制很可能是在重复WM_PAINT消息的代码。”所以可以在滚动条消息处理函数中将需要重新绘制的区域通过InvalidateRect函数放到WM_PAINT的处理函数中绘制。如果想加快WM_PAIN消息的处理,可以在InvalidateRect函数之后调用UpdateWindow函数。


用方向键控制滚动条(待续。。。)


可能要用到的函数

(SetScrollRange,GetScrollRange,SetScrollPos和GetScrollPos已过时,不建议使用,用SetScrollinfo替代更好)

 SetScrolllnfo

函数功能:该函数设置滚动条参数,包括滚动位置的最大值和最小值,页面大小,滚动按钮的位置。如被请求,函数也可以重画滚动条。

int SetScrollInfo(

__in HWND hwnd,

__in int fnBar,

__in LPCSCROLLINFO lpsi,

__in BOOL fRedraw

);

参数:

hWnd:滚动条控件或带标准滚动条的窗体句柄,由fnBar参数决定。

fnBar:指定被设定参数的滚动条的类型。这个参数可以是下面值,含义如下:

SB_CTL:设置滚动条控件。而参数hwnd必须是滚动条控件的句柄。

SB_HORZ:设置所给定的窗体上标准水平滚动条参数。

SB_VERT:设置所给定的窗体上标准垂直滚动条参数。

lpsi:指向SCROLLINFO结构。在调用SetScrollInfo之前,设置SCROLLINFO结构中cbSize成员以标识结构大小,设置成员fMask以说明待设置的滚动条参数,并且在适当的成员中制定新的参数值。成员fMask可以为下面所列复合值,含义如下:

typedef struct tagSCROLLINFO

{

UINT cbSize;

UINT fMask;

int nMin;

int nMax;

UINT nPage;

int nPos;

int nTrackPos;

} SCROLLINFO, FAR *LPSCROLLINFO;

SIF_DfSABLENOSCROLL:如果滚动条的新参数使其为没必要,则使滚动条无效而不再移动它。

SIF_PAGE:设置滚动页码值到由Ipsi指向的SCROLLINFO结构的nPage成员中。

SIF_POS:设置滚动位置值到由lpsi指向的SCROLLINFO结构的nPos成员中。

SIF_RANGE:设置滚动范围值到由lpsl指向的SCROLLINFO结构的nMin和nMax成员中。

fRedraw:指定滚动条是否重画以反映滚动条的变化。如果这个参数为TRUE,滚动条将被重画,否则不被重画。 


GetScrollInfo

函数功能:滚动条的参数,包括滚动条位置的最小值、最大值,页面大小,滚动滑块的位置。

BOOL GetScrollInfo(

__in HWND hwnd,

__in int fnBar,

__inout LPSCROLLINFO lpsi

);

参数:

hWnd:滚动条控制或有标准滚动条的窗体句柄,由fnBar参数确定。

fnBar:指定待找回滚动条参数的类型,此参数可以为如下值,其值含义:

SB_CTL:找回滚动条控制参数。其中参数hwnd一定是处理滚动条控制的句柄。

SB_HORZ:找回所指定窗体的标准水平滚动条参数。

SB_VERT:找回所指定窗体的标准垂直滚动条参数。

lpsi:指向SCROLLINFO结构。

(5)ShowScrollBar

函数功能:该函数显示或隐藏所指定的滚动条.

BOOL ShowScrollBar(

__in HWND hWnd,

__in int wBar,

__in BOOL bShow

);

参数:

hWnd:根据参数wBar值,处理滚动条控制或带有标准滚动条窗体。

wBar:指定滚动条是被显示还是隐藏。这个参数将是下面值之一,具体含义如下:

SB_BOTH:显示或隐藏窗体的标准的水平或垂直滚动条。

SB_CTL:显示或隐藏滚动条控制。参数hWnd必须是指向滚动条控制的句柄。

SB_HORZ:显示或隐藏窗体的标准的水平滚动条。

SB_VERT:显示或隐藏窗体的标准的垂直滚动条。

bShow:指定滚动条是被显示还是隐藏。此参数为TRUE,滚动条将被显示,否则被隐藏。

返回值:如果函数运行成功,返回值为非零;如果函数运行失败,返回值为零。若想获得更多的错误信息,请调用GetLastError函数。



ScrollWindow函数

函数功能该函数滚动所指定的窗口客户区域内容。函数提供了向后兼容性,新的应用程序应使用ScrollWindowEx函数

BOOL ScrollWindow(

__in HWND hWnd,

__in int XAmount,

__in int YAmount,

__in const RECT *lpRect,

__in const RECT *lpClipRect

);

hWnd

  [in]客户区域将被滚动的窗口的句柄。

  XAmount

  [in]指定水平滚动的距离,以设备单位计。如果窗口类风格为CS_OWNDC或CS_CLASSDC,则此参数则使用逻辑单位而非设备单位。当向左滚动窗体内容时,参数值必须为负。

  YAmount

  [in]指定垂直滚动的距离,以设备单位计。如果窗口类风格为CS_OWNDC或CS_CLASSDC,则此参数则使用逻辑单位而非设备单位。当向上滚动窗体内容时,参数值必须为负。

  lpRect

  [in]指向RECT结构的指针,该结构指定了将要滚动的客户区范围。若此参数为NULL,则整个客户区域将被滚动。

  lpClipRect

[in]指向RECT结构的指针,该结构指定了要滚动的裁剪区域。只有这个矩形中的位才会被滚动。在矩形之外的位不会被影响,即使它们是在lpRect矩形之内。(见代码"测试一")假如lpClipRect为NULL,则不会在滚动矩形上进行裁剪。

返回值:

如果函数运行成功,返回值为非零;如果函数运行失败,返回值为零。若想获得更多的错误信息,请调用GetLastError函数。



 ScrollWindowEx

函数功能:滚动窗口客户区

int ScrollWindowEx(

__in HWND hWnd,

__in int dx,

__in int dy,

__in const RECT *prcScroll,

__in const RECT *prcClip,

__in HRGN hrgnUpdate,

__out LPRECT prcUpdate,

__in UINT flags

);

参数:

hWnd:客户区域将被滚动的窗体句柄。

dx:在设备单元中,指定水平滚动数量。在向左滚动时此参数必须为负。

dy:在设备单元中,指定垂直滚动数量。在向上滚动时此参数必须为负。

prcScroll:指向RECT结构,它指定了将被滚动的客户区域部分。

prcClip:指向包含了类似于被剪下矩形的RECT结构。只有在剪下内部的小块图形才受影响。从矩形外向内部的滚动部分将被着色;而从内向外的滚动部分将不再被着色。

hrgnUpdate:处理已被修改的区域,保存这些由于滚动而无效的区域。此参数可以为空。

prcUpdate:指向RECT结构,它接收由于滚动使得矩形无效部分的边界。此参数值可以为空。

flags:指定控制滚动的标志。这个参数可以是下面的值:

SW_ERASE:通过发送WM_ERASEBKGND消息给窗体。

SW_INVALIDATE:在滚动后,使得由参数hrgnUpdate标识的无效区域被擦除。

SW_SCROLLCHILDREN:动所有由参数prcScroll指出交叉重叠矩形的子窗体。子窗体按照dx和dy规定的像素个数滚动。系统发送消息给所有由prcScroll指出交叉重叠矩形的子窗体,即使他们不移动。

返回值:如果函数运行成功,返回值为SIMPLEREGION(矩形的无效区域),COMPLEXREGION(非矩形的无效区域)或NULLREGION(没有使无效的区域)如果函数运行成功,返回值为ERROR。若想获得更多的错误信息,请调用GetLastError函数。





 MFC 窗口 滚动 基情
原创粉丝点击