http://www.sxzhongrui.com/software/191.html

?? 回顾上一节,鸡啄米讲的是组合框控件Combo Box的使用。本节详解滚动条控件Scroll Bar的相关内容。

???????滚动条控件简介

?????? 滚动条大家也很熟悉了,Windows窗口中很多都有滚动条。前面讲的列表框和组合框设置了相应属性后,如果列表项显示不下也会出现滚动条。滚动条分为水平滚动条(Horizontal Scroll Bar)和垂直滚动条(Vertical Scroll Bar)两种。滚动条中有一个滚动块,用于标识滚动条当前滚动的位置。我们可以拖动滚动块,也可以用鼠标点击滚动条某一位置使滚动块移动。

?????? 从滚动条的创建形式来分,有标准滚动条和滚动条控件两种。像列表框和组合框设置了WS_HSCROLL 或WS_VSCROLL风格以后出现的滚动条,不是一个独立的窗口,而是这些窗口的一部分,这就是标准滚动条。而滚动条控件是一个独立的窗口,它可以获得焦点,响应某些操作。

???????滚动条控件的创建

???????MFC也为滚动条控件的操作提供了类,即为CScrollBar类。

?????? 滚动条控件的创建依然有两种方式,一种是直接在Toolbox中将滚动条控件拖入对话框模板,然后添加控件变量使用,另一种就是用CScrollBar类的Create成员函数动态创建。这两种方式适用于不同的场合。

?????? CScrollBar类的成员函数Create的函数原型如下:

virtual BOOL Create( ?? DWORD dwStyle, ?? const RECT& rect, ?? CWnd* pParentWnd, ?? UINT nID? );

?????? 此函数与其他控件类的Create函数原型基本相同。参数dwStyle指定滚动条控件的风格,rect指定滚动条控件的位置和尺寸,pParentWnd为指向滚动条控件父窗口的指针,nID指定滚动条控件的ID。下面鸡啄米简单介绍几个主要的滚动条控件风格,更加具体的可以查阅MSDN。

?????? SBS_HORZ:指定滚动条为水平滚动条。如果没有指定SBS_BOTTOMALIGN或SBS_TOPALIGN风格,则滚动条的高度、宽度和位置由Create函数的rect参数给出。 ???????SBS_VERT:指定滚动条为垂直滚动条。如果没有指定SBS_RIGHTALIGN或SBS_LEFTALIGN风格,则滚动条的高度、宽度和位置由Create函数的rect参数给出。 ???????SBS_TOPALIGN:与SBS_HORZ配合使用。滚动条的上边缘与Create函数的rect参数指定矩形的上边缘对齐。滚动条高度为系统滚动条的默认高度。 ???????SBS_BOTTOMALIGN:与SBS_HORZ配合使用。滚动条的下边缘与Create函数的rect参数指定矩形的下边缘对齐。滚动条高度为系统滚动条的默认高度。 ?????? SBS_LEFTALIGN:与SBS_VERT配合使用。滚动条的左边缘与Create函数的rect参数指定矩形的左边缘对齐。滚动条宽度为系统滚动条的默认宽度。 ?????? SBS_RIGHTALIGN:与SBS_VERT配合使用。滚动条的右边缘与Create函数的rect参数指定矩形的右边缘对齐。滚动条宽度为系统滚动条的默认宽度。

?????? dwStyle参数可以是以上风格中某几个的组合,另外一般也会用到WS_CHILD、WS_VISIBLE风格。例如,创建一个水平滚动条控件,dwStyle参数应该为WS_CHILD|WS_VISIBLE|SBS_HORZ,创建垂直滚动条控件时dwStyle参数应该为WS_CHILD|WS_VISIBLE|SBS_VERT。

???????CScrollBar类的主要成员函数

???????BOOL GetScrollInfo(LPSCROLLINFO lpScrollInfo, UINT nMask = SIF_ALL);

?????? 获取的滚动条的参数信息,该信息为SCROLLINFO结构体的形式。参数lpScrollInfo为指向SCROLLINFO结构体变量的指针。SCROLLINFO结构体的定义如下:

C++代码

typedef?struct?tagSCROLLINFO?{? ??????UINT?cbSize;?????????//?结构的尺寸(字节为单位)???????UINT?fMask;??????????//?说明结构中的哪些参数是有效的,可以是屏蔽值的组合,如SIF_POS|SIF_PAGE,若为SIF_ALL则整个结构都有效???????int??nMin;???????????//?滚动范围最小值,当fMask?中包含SIF_RANGE?时有效???????int??nMax;???????????//?滚动范围最大值,当fMask?中包含SIF_RANGE?时有效???????UINT?nPage;??????????//?页尺寸,用来确定比例滚动框的大小,当fMask中包含SIF_PAGE时有效???????int??nPos;???????????//?滚动框的位置,当fMask?中包含SIF_POS?有效???????int??nTrackPos;??????//?滚动时滚动框的位置,当fMask?中包含SIF_TRACKPOS?时有效,该参数只能查询,不能设置,最好不要用该参数来查询拖动时滚动框的位置???}???SCROLLINFO,?*LPSCROLLINFO;? ??typedef?SCROLLINFO?CONST?*LPCSCROLLINFO;??

?????? 参数nMask 的含义与SCROLLINFO 结构体中的fMask一样。该函数在获取信息成功则返回TRUE,否则返回FALSE。

???????BOOL SetScrollInfo(LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE);

?????? 用于设置滚动条的各种参数信息。参数lpScrollInfo为指向SCROLLINFO结构体变量的指针,参数bRedraw表示是否需要重绘滚动条,如果为TRUE,则重绘。该函数操作成功则返回TRUE,否则返回FALSE。

???????int GetScrollPos( ) const;

?????? 获取滚动块的当前位置。如果失败则返回0。

???????int SetScrollPos(int nPos, BOOL bRedraw = TRUE);

?????? 将滚动块移动到指定位置。参数nPos指定了滚动块的新位置,参数bRedraw 表示是否需要重绘滚动条,如果为TRUE,则重绘。函数返回滚动框原来的位置,若操作失败则返回0。

???????void GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos) const;

???????获取滚动条的滚动范围。参数lpMinPos指向滚动条滚动范围的最小值,参数lpMaxPos指向滚动条滚动范围的最大值。

???????void SetScrollRange(int nMinPos, int nMaxPos, BOOL bRedraw = TRUE);

?????? 用于指定滚动条的滚动范围。参数nMinPos 和nMaxPos 分别指定了滚动范围的最小值和最大值,两者的差不得超过32767。当两者都为0 时,滚动条将被隐藏。参数bRedraw 表示是否需要重绘滚动条,如果为TRUE,则重绘。

???????OnHScroll()与OnVScroll()函数

?????? 无论是标准滚动条,还是滚动条控件,滚动条的通知消息都是用WM_HSCROLL 和WM_VSCROLL消息发送出去的。对这两个消息的默认处理函数是CWnd::OnHScroll和CWnd::OnVScroll,一般需要在派生类中对这两个函数进行重载,以实现滚动功能。也就是说,假设在一个对话框中放入了一个水平滚动条,我们可以在对话框类中重载OnHScroll函数,并在OnHScroll函数中实现滚动功能。

?????? 这两个函数的声明如下:

?????? afx_msg void OnHScroll(UINT nSBCode,UINT nPos,CScrollBar* pScrollBar); ?????? afx_msg void OnVScroll(UINT nSBCode,UINT nPos,CScrollBar* pScrollBar);

?????? 参数nSBCode是通知消息码,主要通知码及含义的介绍下面已列出。nPos 是滚动框的位置,只有在nSBCode为SB_THUMBPOSITION或SB_THUMBTRACK时,该参数才有意义。如果通知消息是滚动条控件发来的,那么pScrollBar 是指向该控件的指针,如果是标准滚动条发来的,则pScrollBar 为NULL。

?????? SB_BOTTOM/SB_RIGHT:滚动到底端(右端) ?????? SB_TOP/SB_LEFT:滚动到顶端(左端) ?????? SB_LINEDOWN/SB_LINERIGHT:向下(向右)滚动一行(列) ?????? SB_LINEUP/SB_LINELEFT:向上(向左)滚动一行(列) ?????? SB_PAGEDOWN/SB_PAGERIGHT:向下(向右)滚动一页 ?????? SB_PAGEUP/SB_PAGELEFT:向上(向左)滚动一页 ?????? SB_THUMBPOSITION:滚动到指定位置 ???????SB_THUMBTRACK:滚动框被拖动。可利用该消息来跟踪对滚动框的拖动 ?????? SB_ENDSCROLL:滚动结束

???????CScrollBar类应用实例

?????? 讲完了基础知识,鸡啄米还是给大家一个简单的实例。例子非常简单,就是在一个对话框中加入一个水平滚动条控件和一个编辑框控件,无论滚动条控件是在滚动还是静止,编辑框中都显示滚动块的当前位置。以下是具体开发步骤:

?????? 1. 创建一个基于对话框的MFC工程,名称设置为“Example26”。

?????? 2. 在自动生成的对话框模板IDD_EXAMPLE26_DIALOG中,删除“TODO: Place dialog controls here.”静态文本控件、“OK”按钮和“Cancel”按钮。添加一个Horizontal Scroll Bar控件,ID设置为IDC_HORI_SCROLLBAR。再添加一个静态文本控件和一个编辑框,静态文本控件的Caption属性设为“滚动块当前位置:”,编辑框的ID设为IDC_HSCROLL_EDIT,Read Only属性设为True。此时的对话框模板如下图:

?????? ?????? 3. 为滚动条IDC_HORI_SCROLLBAR添加CScrollBar类型的控件变量m_horiScrollbar。

?????? 4. 在对话框初始化时,我们需要设置滚动条的滚动范围和初始位置,并在编辑框中显示初始位置,那么需要修改CExample26Dlg::OnInitDialog()函数为:

C++代码

BOOL?CExample26Dlg::OnInitDialog() ??{ ??????CDialogEx::OnInitDialog(); ????????//?Add?"About..."?menu?item?to?system?menu.?????????//?IDM_ABOUTBOX?must?be?in?the?system?command?range.???????ASSERT((IDM_ABOUTBOX?&?0xFFF0)?==?IDM_ABOUTBOX); ??????ASSERT(IDM_ABOUTBOX?AppendMenu(MF_SEPARATOR); ??????????????pSysMenu->AppendMenu(MF_STRING,?IDM_ABOUTBOX,?strAboutMenu); ??????????} ??????} ????????//?Set?the?icon?for?this?dialog.??The?framework?does?this?automatically???????//??when?the?application's?main?window?is?not?a?dialog???????SetIcon(m_hIcon,?TRUE);?????????//?Set?big?icon???????SetIcon(m_hIcon,?FALSE);????????//?Set?small?icon?????????//?TODO:?Add?extra?initialization?here???????//?设置水平滚动条的滚动范围为1到100???????m_horiScrollbar.SetScrollRange(1,?100); ??????//?设置水平滚动条的初始位置为20???????m_horiScrollbar.SetScrollPos(20); ??????//?在编辑框中显示20???????SetDlgItemInt(IDC_HSCROLL_EDIT,?20); ????????return?TRUE;??//?return?TRUE??unless?you?set?the?focus?to?a?control???}??

?????? 5. 现在滚动条还不能正常滚动,并且编辑框中数字也不随滚动改变。根据上面所讲,我们可以重载CExample26Dlg类的OnHScroll函数。具体操作为,在CExample26Dlg类的属性页面的工具栏上点“Messages”按钮,找到WM_HSCROLL消息,添加响应函数就可以了。OnHScroll函数重写后如下:

C++代码

void?CExample26Dlg::OnHScroll(UINT?nSBCode,?UINT?nPos,?CScrollBar*?pScrollBar)??{??????//?TODO:?Add?your?message?handler?code?here?and/or?call?default??????int?pos?=?m_horiScrollbar.GetScrollPos();????//?获取水平滚动条当前位置????????switch?(nSBCode)???????{???????????//?如果向左滚动一列,则pos减1??????????case?SB_LINELEFT:???????????????pos?-=?1;???????????????break;???????????//?如果向右滚动一列,则pos加1??????????case?SB_LINERIGHT:???????????????pos??+=?1;???????????????break;???????????//?如果向左滚动一页,则pos减10??????????case?SB_PAGELEFT:???????????????pos?-=?10;???????????????break;???????????//?如果向右滚动一页,则pos加10??????????case?SB_PAGERIGHT:???????????????pos??+=?10;???????????????break;???????????//?如果滚动到最左端,则pos为1??????????case?SB_LEFT:???????????????pos?=?1;???????????????break;???????????//?如果滚动到最右端,则pos为100??????????case?SB_RIGHT:???????????????pos?=?100;???????????????break;?????????????//?如果拖动滚动块滚动到指定位置,则pos赋值为nPos的值??????????case?SB_THUMBPOSITION:???????????????pos?=?nPos;???????????????break;???????????//?下面的m_horiScrollbar.SetScrollPos(pos);执行时会第二次进入此函数,最终确定滚动块位置,并且会直接到default分支,所以在此处设置编辑框中显示数值??????????default:???????????????SetDlgItemInt(IDC_HSCROLL_EDIT,?pos);??????????????return;???????}?????????//?设置滚动块位置??????m_horiScrollbar.SetScrollPos(pos);????????CDialogEx::OnHScroll(nSBCode,?nPos,?pScrollBar);??}

?????? 6. 编译运行程序,弹出结果对话框,可以自己拖动滚动块看是否能正常滚动,并且编辑框中也显示了正确的数值。效果如下:

??????? 至于垂直滚动条,其实与水平滚动条类似,大家可以自己写写垂直滚动条的例子,鸡啄米就不再举例了。

??????? 滚动条控件的内容就讲到这里了,比较基础,但这些是以后应用滚动条控件的必知内容。鸡啄米欢迎大家常来此学习交流,谢谢。

近期,因工作需要,时隔多年,重新使用VS2010进行开发。

在调查既存项目bug的时候,发现DataGridView的滚动条已经设置了,画面上也显示滚动条的样子,但是不能使用。网上查了很多方法也没解决。

仔细看VS2010,感觉滚动条的设置并没有出错。但是,注意到了DataGridView的一个属性【Enable】。

这是个全局属性,会影响DataGridView的整体功能,滚动条之所以不能用,就是因为Enable被设为了false。

把Enable属性改为true,滚动条就可以使用了。bug解决。

VS2010 C++学习(1):滚动条的设计总结

?

学习VC++编制的滚动条程序.。

一、??????????主要内容:

1.???????对话框中的滚动条设计;

2.???????编辑框中的滚动条设计;

3.???????列表框中的滚动条设计;

?

二、??????????设计实现:

?

1、? 对话框中的滚动条设计;

?

·????????在资源编辑器中,选择在属性对话框中的水平滚动和垂直滚动样式。

·????????选择调整大小的边框样式,以使该对话框可调整其大小。

·????????重写 WM_VSCROLL和 WM_HSCROLL 消息处理程序。

·????????重写设置滚动条区域,如果大小减小到小于原始大小的 WM_SIZE消息处理程序。

?

名称 属性 Border Resizing Horizontal Scrollbar True Vertical Scrollbar True

?

?

1)添加成员变量到对话框类中

?

int m_nCurHeight;? //存储对话框中的当前高度

int m_nScrollPos;? //存储当前垂直滚动位置

int m_nCurWidth;?? //存储对话框中的当前宽度

int m_hScrollPos;? //存储当前水平滚动位置

CRect m_rect;???? //对话框原始大小

?

2)若要获取原始窗口的大小,请将下行添加到OnInitDialog方法:

?????? GetWindowRect(m_rect);

?????? m_nScrollPos = 0;?? //垂直滚动位置0

?????? m_hScrollPos = 0;? //水平滚动位置0

?

3) OnSize方法中添加消息处理程序。

判断当前对话框的大小,并与对话框原始大小进行比较。然后计算出垂直和水平滚动条的最大值,写入SCROLLINFO中去。

?

4) 将 WM_VSCROLL消息的消息处理程序添加到OnVScroll方法中,WM_HSCROLL 消息的消息处理程序添加到OnHScroll方法中。

设计响应滚动条的事件。

?

5) 使用的函数

l???????SetScrollInfo(SB_HORZ, &hsi, TRUE);?

l???????SetScrollPos(SB_HORZ,m_hScrollPos,TRUE);

l???????ScrollWindow(-nDelta,0);

?

函数原型:int SetScrollInfo(HWNDhWnd,int fnBar,LPSCROLLINFOlpsi,BOOL fRedraw);

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

参数:

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

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

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

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

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

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

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

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

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

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

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

返回值:返回值是滑块的当前位置。

?

?

2、? 编辑框中的滚动条设计;

单行编辑框控件无滚动条,多行编辑框控件才有滚动条。

1)Edit1属性:

名称 属性 说明 Multiline True 多行编辑框 Horizontal Scroll True ? Vertical Scroll True ? Auto HScroll True ? Auto VScroll True ?

?

?

2)多行编辑框类的方法:

??? 设置好后多行编辑框控件自动管理滚动条。

3、? 列表框中的滚动条设计;

1)垂直滚动条设计

只需设置属性即可:

?

名称 属性 说明 Vertical Scroll True ?

?

2)水平滚动条设计

注意:需要将水平滚动条的属性设为真,否则即使调用下面的函数也不会出现水平滚动条。

?

名称 属性 说明 Horizontal Scroll True ?

?

?

通过调用SendDlgItemMessage向对话框发送设置水平滚动条宽度信息来显示水平滚动条 。???

?

函数SendDlgItemMessage(IDC_LIST2, LB_SETHORIZONTALEXTENT, (WPARAM)www.sxzhongrui.com,0);

?

函数原型:LRESULT SendDlgItemMessage( int nID, UINTmessage, WPARAM wParam = 0, LPARAM lParam = 0 );

?

?

LB_SETHORIZONTALEXTENT 为设置滚动条宽度信息。发送消息时,wParam为滚动条的长度(以像素为单位,可通过计算得出准确的长度)。lParam无用。