用SDK实现分隔条

news/2024/7/5 0:58:28

VC++学习:用SDK实现分隔条
[2004-6-12]
  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之类的函数来实现改变大小,就是因为这些函数会使窗体的多次重绘而导致整个窗体的闪烁——而事实上我并不希望状态栏也一起闪烁。
SDK实现的分割条


http://www.niftyadmin.cn/n/4820574.html

相关文章

UBuntu8.04的ACE5.6编译和环境配置

ACE历时20年,耗费数千万美金,在中间件领域享有盛誉。更可贵的是,ACE彻底的开源,且没有任何限制条件,完全是共产主义的精神,让人钦佩。 ACE的Wrapper Facade模式解决了夸平台的c编程问题。虽然我们现在有标准…

AndFix热补丁修复

AndFix热补丁修复 AndFix,全称是Android hot-fix。是阿里开源的一个热补丁框架,允许APP在不重新发布版本的情况下修复线上的bug。支持Android 2.3 到 6.0,并且支持arm 与 X86系统架构的设备。完美支持Dalvik与ART的Runtime,补丁文…

在应用中嵌入Python - lf8289的专栏 - CSDNBlog

在应用中嵌入Python - lf8289的专栏 - CSDNBlog " 在应用中嵌入Python收藏 新一篇: 软件在线升级设计方案及演变过程分析 | 旧一篇: 在windows下面关闭subprocess打开的子进程 在应用中嵌入Python 翻译: gashero前面的章节讨论如何扩展Python,如何生成适合…

Gradle认识

Gradle认识 Android Studio 的核心是Google新推出的Gradle编译系统。gradle用于替代Eclipse所使用的ant作为android的编译工具,相对于ant编译工具,gradle吸纳了ant的脚本特性、Maven丰富的依赖管理策略和强大的插件式环境。所以它比ant上手要难。 grad…

VS2010配置QT

用了这么久的Qt,IDE一直都是 VS 与 Creator 并用(实际开发以VS为主),至于哪个更好这里不发表看法,各有所长,而且也因人而异,萝卜青菜,各有所爱。 Qt5发布很久之后,才把版…

ACE内存映射技术

内存映射文件 多个操作系统平台都提供了内存映射文件,这是一个简单的将数据结构保存到文件中的机制。同时由于32位操作系统的进程虚拟内存最大只能4GB,用内存映射文件的方式就可以突破这个限制,可以用来打开超过4GB的大文件。 而且&#xff0…

征服Python—语言基础与典型应用

书名&#xff1a; 征服Python—语言基础与典型应用 出版社&#xff1a;人民邮电出版社作者&#xff1a;孙广磊出版日期&#xff1a;2007年9月版次&#xff1a;第1版ISBN&#xff1a;978-7-115-216657-9/TP定价&#xff1a;59.00元 想读&#xff1a; <script src"htt…

SecureCRT 与Linux基本命令介绍

SecureCRT SecureCRT是常用得瑟终端仿真程序&#xff0c;就是windows下登陆Linux或Unix服务器主机的软件 SecureCRT的安装教程大家可以百度&#xff0c;就不详细描述了&#xff0c;可以参考http://jingyan.baidu.com/article/49ad8bce69ad285834d8fa9a.html Linux基础命令的…