dedecms织梦内容管理系统    
首页 | java | C/C++ | PHP | 操作系统 | ajax | 脚本编程 | 安全技术 | 本站下载页 | flex | CRM | 专题 | QQ群 | 测试中心 | 会员中心 | 积分规则
  当前位置:主页>C/C++>C/C++技术资料>文章内容
VC++学习:用SDK实现分隔条
来源:CSDN     作者:    
Windows中的分隔条是一种被广泛使用的控件,绝大多数Explorer式样的应用程序都使用了这种控件。然而却很少有相关的资料对它的完整实现进行介绍,于是我自己实现了一个,希望对SDK的爱好者们有所帮助。

  事实上,分隔条也是一个很普通的窗口,它也拥有自己的窗口类、自己的窗口过程——就像所有的预定义控件一样。也就是说,要创建一个分隔条,也需要进行窗口类的注册和窗口的创建。以下的示例代码示范了如何注册一个分隔条的窗口类:

 WNDCLASS wc;
 wc.cbClsExtra = 0;
 wc.cbWndExtra = 0;
 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW; // 1
 wc.hCursor = LoadCursor(NULL, IDC_SIZEWE); // 2
 wc.hIcon = NULL;
 wc.hInstance = hInstance;
 wc.lpfnWndProc = (WNDPROC)ProcSplitter; // 3
 wc.lpszClassName = "MySplitter"; // 4
 wc.lpszMenuName = NULL;
 wc.style = 0;
 RegisterClass(&wc);

  这段代码相信大家已经很熟悉了,所以在此我只简要说明四点:1、分隔条的背景颜色,这里我取默认的对话框背景色;2、分隔条的鼠标指针,这里我取水平的调整大小;3、这是分隔条的窗口过程,所有的秘密都在这个回调之中;4、分隔条的窗口类名称,你可以随便取一个你喜欢的名字。

  在成功地注册窗口类之后,就可以创建分隔条了。以下是我的示例界面,它由一个树形视图、一个分隔条、一个列表视图以及一个状态栏组成,下文的所有代码都是以这个界面为基础的。

  在编写分隔条的窗口过程之前,我先来处理对话框的WM_SIZE消息作为分隔条窗口过程的一个热身。代码如下(你会发现在整个的代码中我没有对hTree、hStatus、hSplitter以及hList做任何的声明,那是因为对于这个简单的示例,我将所有的这些东西都声明为了全局变量):
case WM_SIZE:
 {
 HDWP hdwp;
 RECT rect, rectStatus, rectTree;
 hdwp = BeginDeferWindowPos(4);
 GetClientRect(hDlg, &rect);
 GetClientRect(hStatus, &rectStatus);
 GetWindowRect(hTree, &rectTree);
 DeferWindowPos(hdwp, hStatus, NULL, 0, rect.bottom - rectStatus.bottom, rect.right, rectStatus.bottom,   SWP_NOZORDER);
 DeferWindowPos(hdwp, hTree, NULL, 0, 0, rectTree.right - rectTree.left, rect.bottom - rectStatus.bottom,  SWP_NOMOVE | SWP_NOZORDER);
 DeferWindowPos(hdwp, hSplitter, NULL, rectTree.right - rectTree.left, 0, 2, rect.bottom - rectStatus.bottom,  SWP_NOZORDER);
 DeferWindowPos(hdwp, hList, NULL, rectTree.right - rectTree.left + 2, 0, rect.right - rectTree.right + rectTree.left -  2, rect.bottom - rectStatus.bottom, SWP_NOZORDER);
 EndDeferWindowPos(hdwp);
 }
 break;

  你肯定已经注意到了,这段代码的大部分篇幅都是在和矩形做游戏。的确是这样,因为调整窗口大小的过程就是一个改变各个子窗口的位置和大小的过程。这个过程用语言叙述就是:1、首先,将状态栏放置在对话框的最下方;2、第二步,不改变树形视图的位置和宽度,重设它的高度;3、不改变分隔条的位置和宽度,重设它的高度;4、使列表视图占满剩余的客户区。

  如果你弄懂了上面的代码,那么分隔条的窗口过程也就没有任何难度了:

 LRESULT CALLBACK ProcSplitter(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
 switch (Msg)
 {
 case WM_LBUTTONDOWN:
 SetCapture(hwnd);
break;
 case WM_LBUTTONUP:
 ReleaseCapture();
 break;
 case WM_MOUSEMOVE:
 {
 if ((wParam & MK_LBUTTON) == MK_LBUTTON && GetCapture() == hwnd)
 {
 HDWP hdwp;
 RECT rect, rectStatus, rectTree;
 hdwp = BeginDeferWindowPos(3);
 GetClientRect(GetParent(hwnd), &rect);
 GetClientRect(hStatus, &rectStatus);
 GetWindowRect(hTree, &rectTree);
 DeferWindowPos(hdwp, hTree, NULL, 0, 0, rectTree.right - rectTree.left + (short)LOWORD(lParam), rect.bottom  - rectStatus.bottom, SWP_NOMOVE | SWP_NOZORDER);
 DeferWindowPos(hdwp, hSplitter, NULL, rectTree.right - rectTree.left + (short)LOWORD(lParam), 0, 0, 0,  SWP_NOSIZE | SWP_NOZORDER);
 DeferWindowPos(hdwp, hList, NULL, rectTree.right - rectTree.left + (short)LOWORD(lParam) + 2, 0, rect.right -  rectTree.right + rectTree.left - (short)LOWORD(lParam) - 2, rect.bottom - rectStatus.bottom, SWP_NOZORDER);
 EndDeferWindowPos(hdwp);
 }
 }
 break;
 default:
 return DefWindowProc(hwnd, Msg, wParam, lParam);
 }
 return 0;
 }

  SetCapture和ReleaseCapture是分别在鼠标左键按下与释放的时候捕获和释放鼠标,这是分隔条的一般要求。这段代码中的核心部分就是在处理鼠标移动的,就是当鼠标左键按下并且分隔条捕获鼠标的时候来改变三个相关窗口的位置和宽度。具体的矩形操作与主窗口WM_SIZE的代码原理相似,我就不多说了。

  我之所以不使用MoveWindow之类的函数来实现改变大小,就是因为这些会使窗体的多次重绘而导致整个窗体的闪烁——而事实上我并不希望状态栏也一起闪烁。

 

 

上一篇:一个对Winsock完成端口模型封装的类   下一篇:在VC中透明浮动按键的实现
[收藏] [推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
用户名: 新注册) 密码: 匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论
  热点文章
·C语言数组排序小结
·Python 与 C++ 程序的简单实例对
·c++ 数组与指针
·C++中的内存管理(new、delete、
·如何用C语言开发DSP嵌入式系统
·如何用C语言开发DSP嵌入式系统
·Linux下C语言编程
·学习arm的话先看哪本书?
·C++初学者应该关心的优秀图书一
·利用C语言小程序来解决大问题
·用C语言写PHP扩展的步骤
·用C语言扩展PHP功能
  相关文章
·一个对Winsock完成端口模型封装
·在VC中透明浮动按键的实现
·重载函数的应用与深入剖析
·在视图中同步显示鼠标的位置
·Gzip Zlib PNG 压缩算法,源码详
·无闪烁刷屏技术的实现
·窗口类的诞生(注册自己的窗口类)
·利用VC编程在界面上实现3D文字
·窗口类的诞生(注册自己的窗口类)
·让你的控制台程序也支持自动补齐
·显示内存中的HTML内容
·ado方式访问带密码数据库的方法
  相关信息
copy right @ 百家拳软件项目研究室 2007 辽ICP备07011763