滚动条在Win32程序中是非常常见的一个控件,它的功能和地位也就不言而喻了,在文本输出中算是一个难点……
我将借用P先生的思路讲述两种不同风格滚动条,下面切入主题:(实例程序都是显示一张位图 当然,位图比客户区大得多,以显示出滚动条的作用)
(1)不可变长的滚动条
这是16windows中的版本,windows1.0就有了这个玩意儿
它的使用主要依托以下两个API函数:
设定滚动条范围:
BOOL SetScrollRange(
HWND hWnd, // 窗口句柄
int nBar, // 滚动条的类型(SB_VERT、SB_HORZ、SB_CTL)
int nMinPos, // 范围的下边界
int nMaxPos, // 范围的上边界
BOOL bRedraw // 是否重绘滚动条块
);
设定滚动条的位置:
int SetScrollPos(
HWND hWnd,
int nBar,
int nPos, // 滚动条的新位置
BOOL bRedraw
);
获取滚动条的位置:
int GetScrollPos(
HWND hWnd,
int nBar
);
我们先来瞧一瞧这种风格的滚动条的效果:
它们的使用应该还是比较简单,只是要注意两点:
1)图片显示移动的方向和滚动条的滚动方向应该是相反的,所以代码中你会看到贴位图的位置是一个负值
BitBlt(hdc, -iHscrollPos, -iVscrollPos, cxBitmap, cyBitmap, hdcMem, 0, 0, SRCCOPY);
2)这种风格的滚动条需要我们程序员自行控制它的范围,使显示的位置始终在规定的范围内
iVscrollPos = max(0, min(iVscrollPos, cyBitmap - cyClient));//垂直滚动条位置
iHscrollPos = max(0, min(iHscrollPos, cxBitmap - cxClient));//水平滚动条位置
主要代码详解:
加载位图,这个和之前讲的位图的应用是一样的
case WM_CREATE:
//加载位图
hInstance = ((LPCREATESTRUCT)lParam)->hInstance;
hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
GetObject(hBitmap, sizeof(BITMAP), &bitmap);
cxBitmap = bitmap.bmWidth;
cyBitmap = bitmap.bmHeight;
return 0 ;
设定滚动条参数
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
//当窗口大小改变时 , 重新判断水平、垂直滚动条位置是否超出范围
iVscrollPos = max(0, min(iVscrollPos, cyBitmap - cyClient));
iHscrollPos = max(0, min(iHscrollPos, cxBitmap - cxClient));
//设定水平滚动条
SetScrollRange(hwnd, SB_HORZ, 0, cxBitmap - cxClient, FALSE);
SetScrollPos(hwnd, SB_HORZ, iHscrollPos, TRUE);
//设定垂直滚动条
SetScrollRange(hwnd, SB_VERT, 0, cyBitmap - cyClient, FALSE);
SetScrollPos(hwnd, SB_VERT, iVscrollPos, TRUE);
return 0;
滚动条消息处理(这里只给出垂直的,水平的类似)
//处理垂直滚动条消息
case WM_VSCROLL:
switch(LOWORD(wParam))
{
case SB_LINEUP:
iVscrollPos -= 10 ;//每一行滚动10个像素
break ;
case SB_LINEDOWN:
iVscrollPos += 10 ;
break ;
case SB_PAGEUP://翻页就是一个客户区大小
iVscrollPos -= cyClient ;
break ;
case SB_PAGEDOWN:
iVscrollPos += cyClient ;
break ;
case SB_THUMBTRACK:
iVscrollPos = HIWORD (wParam) ;
break ;
default :
break ;
}
//保证滚动条的位置在规定的范围内
iVscrollPos = max(0, min(iVscrollPos, cyBitmap - cyClient));
//iVscrollPos与当前滚动条位置不同时 , 才更新滚动条的位置
if (iVscrollPos != GetScrollPos (hwnd, SB_VERT))
{
SetScrollPos (hwnd, SB_VERT, iVscrollPos, TRUE) ;
InvalidateRect (hwnd, NULL, FALSE) ;
//由于这里是图片, 就不要刷背景了(也就是最后一个参数设为FALSE), 免得闪屏很厉害
}
return 0;
(2)可变长的滚动条
Win32的标准风格
它要稍微复杂点儿,它同样有一套API来维护,以下是相关的API函数:
设定滚动条信息
int SetScrollInfo(
HWND hwnd, // 窗口句柄
int fnBar, // 滚动条类型
LPCSCROLLINFO lpsi, // 滚动条信息结构体(稍后详解)
BOOL fRedraw // 是否重绘滚动条方块
);
获取滚动条信息
BOOL GetScrollInfo(
HWND hwnd, // handle to window
int fnBar, // scroll bar type
LPSCROLLINFO lpsi // scroll bar parameters
);
滚动窗口(这里是指窗口的客户区)
BOOL ScrollWindow(
HWND hWnd, // handle to window
int XAmount, // 水平滚动距离
int YAmount, // 垂直滚动距离
CONST RECT *lpRect, // 滚动区域范围(一般就是设为NULL,指客户区)
CONST RECT *lpClipRect // 剪裁区域(今天用不到,设定为NULL)
);
SCROLLINFO结构体
typedef struct tagSCROLLINFO {
UINT cbSize;//SCROLLINFO类型大小(主要是windows为了以后能兼容),也就是sizeof(SCROLLINFO)
UINT fMask; //设定滚动条需要设置的参数
int nMin; //滚动条上边界
int nMax; //滚动条下边界
UINT nPage; //每一页的大小(主要用于计算滚动条块的大小)
int nPos; //滚动条的位置
int nTrackPos; //滚动条滚动的位置
} SCROLLINFO, *LPSCROLLINFO;
typedef SCROLLINFO CONST *LPCSCROLLINFO;
同样,我们还是先来看看它的效果:
你会发现随着窗口大小的变化,滚动条方块也随着变化了,它变化的依据如下:
有一点需要注意的是:windows帮你做了以下一个设计 —— 滚动条实际滚动的范围是:nMax - nPage + 1,这主要是避免过多的滚动,当显示内容在后一行在客户区最后一行就行了,所以我们只需要从我们的视角来设定nMin和nMax,不要自己去考虑滚动条滚动的实际范围,windows都为我们做好了。
主要代码详解:
初始化滚动条参数
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
//设定垂直滚动条范围和页面大小
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = cyBitmap;
si.nPage = cyClient;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
//设定水平滚动条范围和页面大小
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE;
si.nMin = 0;
si.nMax = cxBitmap;
si.nPage = cxClient;
SetScrollInfo(hwnd, SB_HORZ, &si, TRUE);
return 0;
处理滚动条消息(同样也实现垂直的)
//处理垂直滚动条消息
case WM_VSCROLL:
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hwnd, SB_VERT, &si);
iVertPos = si.nPos;
switch(LOWORD(wParam))
{
case SB_TOP: //置顶(先按下Shift键不放,然后点击滚动条方块上侧区域就能置顶)
si.nPos = si.nMin ;
break ;
case SB_BOTTOM://置底(同置顶)
si.nPos = si.nMax ;
break ;
case SB_LINEUP:
si.nPos -= 10 ;//每一行滚动10个像素
break ;
case SB_LINEDOWN:
si.nPos += 10 ;
break ;
case SB_PAGEUP://翻页就是一个客户区大小
si.nPos -= cyClient ;
break ;
case SB_PAGEDOWN:
si.nPos += cyClient ;
break ;
case SB_THUMBTRACK:
si.nPos = HIWORD (wParam) ;
break ;
default :
break ;
}
si.fMask = SIF_POS;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
GetScrollInfo(hwnd, SB_VERT, &si);
if(iVertPos != si.nPos)
{
//这里InvalidateRect、ScrollWindow,效果相同
InvalidateRect(hwnd, NULL, FALSE);
//ScrollWindow(hwnd, 0, iVertPos - si.nPos, NULL, NULL);
}
return 0;
有过Java开发的朋友可能知道,在Java中添加一个滚动条是多么容易啊,几行代码就OK了,但我想说的是:真正的程序员是了解自己编写的程序整个的来龙去脉,那么,试问Java的滚动条,有谁知道它是怎么来的吗?呵呵,当然,我说这些不具有任何感情色彩,只是我觉得真刀真枪的做才会有意义,各位觉得呢^_^
源代码下载
分享到:
相关推荐
Photoshop_CS6经典教程——由浅入深_通俗易懂.
<br><br>Asp.net完全入门,Doc格式,简体中文<br><br><br><br>1、由浅入深的介绍领先的asp.net技术;<br><br><br><br>2、坚实的基础知识阐述,是读者进入.net技术的必经之门;<br><br><br><br>3、理论与实践相结合的...
标记库<br>JSP由浅入深(12)—— 表单编辑<br>JSP语法(1)——HTML注释<br>JSP语法(2)——隐藏注释<br>JSP语法(3)——声明<br>JSP语法(4)——表达式<br>JSP语法(5)——Scriptlet<br>JSP语法(6)——Page ...
<br>Asp.net完全入门,Doc格式,简体中文<br><br>1、由浅入深的介绍领先的asp.net技术;<br><br>2、坚实的基础知识阐述,是读者进入.net技术的必经之门;<br><br>3、理论与实践相结合的典范,大量的例子详细地阐明每...
- <item identifier="i_18-022Fall-2005.CourseHome.chp_vector_add.jpg" identifierref="r_NR.rdonlyres.Mathematics.18-022Fall-2005.42D44686-7621-4F3D-8E41-7EDFA08B0A68.0.chp_vector_add.jpg"> <title>...
由浅入深——Java 2自学教程 配书光盘.rar 包含所有工程素材和源码
由浅入深——Java 2自学教程
<br><br>2、坚实的基础知识阐述,是读者进入.net技术的必经之门;<br><br>3、理论与实践相结合的典范,大量的例子详细地阐明每一个技术重点;<br><br>4、详细的数据库访问、操作说明和例子;<br><br>5、详细的高级...
<br><br>2、坚实的基础知识阐述,是读者进入.net技术的必经之门;<br><br>3、理论与实践相结合的典范,大量的例子详细地阐明每一个技术重点;<br><br>4、详细的数据库访问、操作说明和例子;<br><br>5、详细的高级...
<br>.iso文件,使用WinRAR打开,解压后为.pdg格式<br><br>http://img.verycd.com/posts/0607/post-342793-1153962298.gif<br><br>《中文版Excel 2003宝典》 <br><br>英文原名: Excel 2003 Bible<br> <br>本书是一本...
一本很好的软件书哦!
为何要升级IP 1<br>1.1 IP的影响 1<br>1.1.1 什么是IP 2<br>1.1.2 IP应用在哪些地方 3<br>1.1.3 有多少人在使用IP 3<br>1.1.4 当IP发生变化时...br>1.2.3 IP安全性议题 6<br>1.2.4 自动配置 6<br>1.3 紧迫感 7<br>第2章...
ThinkPHP5.0数据库和模型由浅入深
C程序100例<br>程序1】<br>题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?<br>1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。...<br> }<br>}<br>由浅入深
《例说STM32》以ALIENTEK MiniSTM32开发板为实验平台,结合28个具体实例,由浅入深,一步步讲解STM32的各个外设.随书附带的光盘带有全部实验的源码,另外还有一些 扩展实例,...希望<<例说STM32>>能带您进入Cortex M3 的殿堂
高清的《例说STM32》 ,以ALIENTEK MiniSTM32开发板为实验平台,结合28个具体实例,由浅入深,一步步讲解STM32的各个外设.随书附带的光盘带有全部实验的源码,另外还有一些...希望<<例说STM32>>能带您进入Cortex M3 的殿堂.
由浅入深学C语言——基础、进阶与必做430题,建议用于练习
CSS Mastery 精通CSS 中文版高清晰 +英文版 +源码下载<br>CSS Mastery<br>作者: Andy Budd / Simon Collison / Cameron Moll<br>副标题: Advanced Web Standards Solutions (Solutions)<br><br>简介 ······ ...
CSS Mastery 精通CSS 中文版高清晰 +英文版 +源码下载<br>CSS Mastery<br>作者: Andy Budd / Simon Collison / Cameron Moll<br>副标题: Advanced Web Standards Solutions (Solutions)<br><br>简介 ······ ...
CSS Mastery 精通CSS 中文版高清晰 +英文版 +源码下载<br>CSS Mastery<br>作者: Andy Budd / Simon Collison / Cameron Moll<br>副标题: Advanced Web Standards Solutions (Solutions)<br><br>简介 ······ ...