<Win32_7>由浅入深——滚动条
来源:互联网 发布:excel筛选特定数据求和 编辑:程序博客网 时间:2024/05/02 02:05
本文由BlueCoder编写 转载请说明出处:
http://blog.csdn.net/crocodile__/article/details/9626057
我的邮箱:bluecoder@yeah.net 欢迎大家和我交流编程心得
我的微博:BlueCoder_黎小华 欢迎光临^_^
滚动条在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的滚动条,有谁知道它是怎么来的吗?呵呵,当然,我说这些不具有任何感情色彩,只是我觉得真刀真枪的做才会有意义,各位觉得呢^_^
源代码下载
- <Win32_7>由浅入深——滚动条
- Windows编程之滚动条—滚动条消息
- Qt——滚动条
- 前端——滚动条
- 关于滚动条—固定
- Android【垂直滚动广告条】仿淘宝头条1号店京东—垂直滚动广告条
- Android【垂直滚动广告条】仿淘宝头条1号店京东—垂直滚动广告条
- windows应用开发由浅入深(二)常用控件--进度条、滚动条
- windows编程——滚动条
- OpenCV学习——滚动条
- Fixjs实践——滚动条控件
- Qt——滚动条自动下移
- 关于xcode——滚动条
- Android开发——scrollView滚动条
- CSS——水平(横向滚动条)
- CSS—表格出现滚动条
- JavaScript基础—滚动条事件
- css—水平(横向)滚动条
- 影响网站打开速度的因素有哪些
- PHP内核探索:Apache运行与钩子函数
- 【Cocos2d-X开发学习笔记】第09期:渲染框架之菜单类(CCMenu)的使用
- C++中对象使用new与不使用new的区别
- IIFE (immediate-invoke function expression ) in javascript
- <Win32_7>由浅入深——滚动条
- JavaSe 调用native C/C++ 之 java头文件生成
- 如何制作IOS推送功能
- 多线程编程3 - NSOperationQueue
- php设置和获取cookie
- 磁盘碎片的相关知识
- 复制构造函数在什么时候被调用?
- library cache pin 锁的问题处理
- MFC桌面右下角弹窗不抢当前窗口焦点同时不抢父窗口焦点