转自:http://www.jizhuomi.com/software/191.html

滚动条控件简介

滚动条大家也很熟悉了,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 < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->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(, );
// 设置水平滚动条的初始位置为20
m_horiScrollbar.SetScrollPos();
// 在编辑框中显示20
SetDlgItemInt(IDC_HSCROLL_EDIT, ); return TRUE; // return TRUE unless you set the focus to a control
}
 

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

OnHScroll函数重写后如下:

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 -= ;
break;
// 如果向右滚动一列,则pos加1
case SB_LINERIGHT:
pos += ;
break;
// 如果向左滚动一页,则pos减10
case SB_PAGELEFT:
pos -= ;
break;
// 如果向右滚动一页,则pos加10
case SB_PAGERIGHT:
pos += ;
break;
// 如果滚动到最左端,则pos为1
case SB_LEFT:
pos = ;
break;
// 如果滚动到最右端,则pos为100
case SB_RIGHT:
pos = ;
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. 编译运行程序,弹出结果对话框,可以自己拖动滚动块看是否能正常滚动,并且编辑框中也显示了正确的数值。效果如下:

至于垂直滚动条,其实与水平滚动条类似,大家可以自己写写垂直滚动条的例子。滚动条控件的内容就讲到这里了,比较基础,但这些是以后应用滚动条控件的必知内容。

PS:关于OnHScroll函数重写的几个疑问。

1、注释掉while循环中部分代码,程序运行没有影响。

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 -= ;
break;
// 如果向右滚动一列,则pos加1
case SB_LINERIGHT:
pos += ;
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);
}

2、关于default的注释应该写错了,改成:

//最下面的CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);执行时会第二次进入此函数,最终确定滚动块位置,并且会直接到default分支,所以在此处设置编辑框中显示数值

如果把 SetDlgItemInt(IDC_HSCROLL_EDIT, pos); 语句拿出来(剪切)放到 m_horiScrollbar.SetScrollPos(pos);  下面,其余代码不变,则程序运行无影响。

最新文章

  1. mybatis关联映射
  2. Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3)
  3. Distributed1:Linked Server 添加和删除
  4. 修改 C:\Users\[account name] 目录名称
  5. oracle 模糊查询中的转义字符用法
  6. 我 &amp;&amp; yii2 (路由优化)
  7. hdu 1733 分层网络流 ****
  8. MyCAT安装指南
  9. 别样的checkbox
  10. [C/CPP系列知识] C++中extern “C” name mangling -- Name Mangling and extern “C” in C++
  11. javaIO(05)字节流和字符流的区别
  12. Spring MVC控制层的返回类型--String类型与Bean类型
  13. 时区 : America/Mexico_City 中文:美国中部时间(墨西哥城) 的夏令时
  14. nest &#39;for&#39; loop.
  15. RR模式下利用区间锁防止幻读,RC模式没有区间锁会出现幻读
  16. WPF单线程定时器 简单实例
  17. 如何在Android Studio中指定NDK位置?
  18. sublime 配置过程
  19. mosquitto broker 安装服务后启动失败
  20. BFS 路径记录

热门文章

  1. 自定义Java annotation
  2. Change myself to be better
  3. Linux环境相关
  4. css导行下拉动画
  5. 微信小程序自定义导航栏组件,完美适配所有手机,可实现各种功能和情况
  6. http经典解析
  7. Delphi GDI对象之脱屏位图(Offscreen Bitmaps)
  8. C语言itoa()函数和atoi()函数详解(整数转字符C实现)【转载】
  9. NX二次开发-创建直线UF_CURVE_create_line与NXOpen-&gt;CreateLine
  10. NX二次开发-打开part对话框UF_UI_open_part