SDK实现分隔条

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

时间: 2024-10-01 10:55:30

SDK实现分隔条的相关文章

在mfc中使用CSplitterWnd分割窗口问题,想要拖动分隔条怎么使小窗口的大小和控件随着变化

问题描述 在mfc中使用CSplitterWnd分割窗口问题,想要拖动分隔条怎么使小窗口的大小和控件随着变化 如上所述,我现在已经把一个界面分割成2行3列的6个小窗口,用来显示曲线图.但是,当我拖动分隔条的时候主要查看某一个小窗口的时候,里面的控件和位置都没有变化,现在怎么才能使其窗口和里面的控件随着我的拖动放大缩小呢..求救啊!!!谢谢啦!! 解决方案 处理View中的WM_SIZE消息等,然后再等比例的MoveWindow等来调整控件的大小位置

jquery插件jquery.beforeafter.js实现左右拖拽分隔条对比图片的方法_jquery

本文实例讲述了jquery插件jquery.beforeafter.js实现左右拖拽分隔条对比图片的方法.分享给大家供大家参考.具体如下: 左右拖拽切换对比图片效果,运行效果后,图片中间有个拖动条,拖动左右滑动,可看到图片不一样的效果,女模特的脸变嫩了,呵呵,其实是用了两张背景图片实现的,这就需要jquery.beforeafter.js插件了,拖动时候的小图标不见了,路径可以在jquery.beforeafter.js中设置,不多说了. 运行效果截图如下: 在线演示地址如下: http://d

jquery 中splitter,点击分分割条左侧不见了,但同时整个分隔条也不见了,为什么

问题描述 jquery 中splitter,点击分分割条左侧不见了,但同时整个分隔条也不见了,为什么 jquery jqxsplitter,点击分分割条左侧是隐藏了,但同时整个分隔条也不见了,没法再点击,让左侧出现,为什么

vc学习教程

·VC基础学习:初学者指针指南 ·Visual C++ 入门精解 ·VC中的常用的20个方法 ·新手必学:windows网络编程经典入门 ·新手看过来:VC对话框控件属性的修改 ·学好VC++的十大良好习惯 ·VC高级学习:编程本质论 ·VC++学习经验:也谈编程本质 ·VC用ADO访问数据库全攻略 ·VC下ADO开发实践之一 ·VC下ADO开发实践之二 ·VC最常用操作程序20项列举 ·VC++学习:分析MFC中的映射 ·VC++学习:用vc实现生产者消费者问题 ·VC++学习:用SDK实现分

马士兵J2SE-第六章-常用类-基本数据类型包装类、Maths类、File类

基本数据类型包装类 public class test { public static void main(String[] args) { Integer i=new Integer(100); Double d=new Double("123.456"); int j=i.intValue()+d.intValue(); float f=i.floatValue()+d.floatValue(); System.out.println(j); System.out.println(

可以显示多行文字的工具条

界面显示效果如图一: 图一 例子程序运行画面 CToolBar不支持多行文字,本文将通过一个定制的MFC/C++类 CMTToolBar 实现在工具条中显示多行文字.其思路是先把文字变成位图,再替换原来的工具条位图,达到显示多行文字的效果.这个类中最主要的一个成员函数是ShowText(UINT nIDResource),其定义如下: // 显示工具条文字BOOL CMTToolBar::ShowText(UINT nIDResource){ // determine location of t

MFC程序员WTL指南(8)分隔窗口

介绍 随着使用两个分隔的视图管理文件系统的资源管理器在Windows 95中第一次出现,分隔窗口逐渐成为一种流行的界面元素.MFC也有一个复杂的功能强大的分隔窗口类,但是要掌握它的用法确实有点难,并且它和文档/视图框架联系紧密.在第七章我将介绍WTL的分隔窗口,它比MFC的分隔窗口要简单一些.WTL的分隔窗口没有MFC那么多特性,但是易于使用和扩展. 本章的例子工程是用WTL重写的ClipSpy,如果你对这个程序不太熟悉,现在可以快速浏览一下本章内容,因为我只是复制了ClipSpy的功能而没用深

硕思闪客菜单制作flash导航条图文教程

如何利用硕思闪客菜单制作flash导航条?具体步骤是怎样的呢? 一:创建完全自定义的flash导航条. 1.打开硕思闪客菜单软件,新建"水平菜单"或者"垂直菜单", 菜单编辑界面将会出现原始菜单按钮. 2.对菜单项按钮属性进行设置.在右侧的任务栏内可以对原始菜单的字体.边框.背景颜色.样式等各项元素属性进行设置.各选项你点击进去就会设置,友好的用户界面让你能够轻松使用硕思闪客菜单的任意功能! 3.为flash导航条添加子菜单项.在菜单项前后插入分隔条等. 在菜单编辑

AndroidUI设计之 布局管理器 - 详细解析布局实现

写完博客的总结 : 以前没有弄清楚的概念清晰化 父容器与本容器属性 : android_layout...属性是本容器的属性, 定义在这个布局管理器的LayoutParams内部类中, 每个布局管理器都有一个LayoutParams内部类, android:... 是父容器用来控制子组件的属性. 如android:layout_gravity 是控制组件本身的对齐方式, android:gravity是控制本容器子组件的对齐方式; . 作者 :万境绝尘  转载请注明出处 : http://blo