SDI应用程序中的标签和分割视图实现

在开发SDI应用程序时,经常需要实现标签和分割视图的功能。虽然市面上有许多现成的解决方案,但往往难以找到一个能够将两者完美结合的方案。因此,开发了一个WTL类来简化构建使用标签和分割视图的SDI应用程序的过程。最初,尝试使用标准的窗口标签控件,但后来发现Bjarke Viksoe的CCustomTabCtrl和Daniel Bowen的CDotNetTabCtrl这两个令人惊叹的标签控件实现,决定采用它们。

主要功能

这个类有三个主要功能:

  • 使用拖放操作可以改变标签控件中的标签位置。
  • 可以将一个标签客户视图拖放到另一个客户视图窗格中。
  • 可以将标签客户视图排列在另一个标签窗格的边缘(与其他标签垂直或水平分割)。

如何使用代码

主要类是SplitPane,它添加了上述所有功能。在应用程序中使用它应该不会遇到任何困难。首先,需要在编译器可以访问的地方包含以下文件:

  • atlgdix.h - Bjarke Viksoe编写的额外GDI/USER包装器。
  • CustomTabCtrl.h - 帮助实现具有不同外观的标签控件的基类。由Bjarke Viksoe编写,Daniel Bowen进行了几项改进。
  • DotNetTabCtrl.h - 从CCustomTabCtrl派生的标签控件,旨在看起来像VS.Net中的标签(MDI标签、解决方案资源管理器标签等)。由Daniel Bowen编写。
  • DockTabPane.h - 标签控件和标签窗格实现。使用上述所有包含文件。
  • DockTabSplitPane.h - 分割窗格实现。包括DockTabPane.h。

然后使用ATL/WTL向导创建SDI应用程序项目。必须关闭"在ATL中最小化CRT使用"配置选项。按照以下步骤将SplitPane类添加为主视图:

  1. 在stdafx.h文件中包含DockTabSplitPane.h
  2. 为CMainFrame类添加SplitPane类成员,并从CallBackListener接口类继承:
class CMainFrame : public CFrameWindowImpl , public CUpdateUI , public CMessageFilter , public CIdleHandler , public DockSplitTab::CallBackListener { DockSplitTab::SplitPane mainPane; public: CMainFrame(); };

CallBackListener类的目的在于为SplitPane提供分割窗格通知给所有者或父对象。认为这比win32消息更简单。与MainFrame类继承的同时,可以设计一个特殊的类适配器来实现SplitPane与其所有者之间的所有通信需求。因此,不要忘记像下面这样初始化mainPane:

CMainFrame::CMainFrame() : mainPane(this, true) { // ... }

mainPane构造函数的第二个参数为所有SplitPane包含的标签控件栏设置顶部。要完成mainPane,请将SplitPane窗口创建代码放入CMainFrame::OnCreate事件处理程序,并将其分配给m_hWndClient属性:

LRESULT CMainFrame::OnCreate(UINT, WPARAM, LPARAM, BOOL&) { // ... this->m_hWndClient = this->mainPane.create(this->m_hWnd); // ... }

就是这样。已经完成了作为应用程序主视图窗口的SplitPane定义。不要忘记定义CallBackListener接口的函数处理程序。如何做到这一点,请参考演示项目。

SplitPane类

公共方法:

// 创建一个新的Split Pane窗口,带有parentWnd和rect参数 HWND create(parentWnd, rect); // 将新的客户视图窗口添加到Split Pane。 // 新的客户视图被添加到焦点标签窗格中 bool append(caption, clientViewWnd, tooltip, imageIndex); // 将客户视图窗口从Split Pane分离。 // 此方法将客户窗口视图的父窗口更改为Split Pane父窗口。 bool detachClientView(clientViewWnd); // 返回接收键盘焦点的客户视图窗口 HWND focusedClientView(); // 将键盘焦点设置到指定位置的标签窗格 bool setFocusTo(x, y); // 将键盘焦点设置到指定的客户视图窗口 bool setFocusTo(clientViewWnd); // 返回Split Pane中客户视图窗口的数量 int getClientViewCount(); // 返回指定位置的标签窗格的矩形,如果有的话 bool getClientViewRect(point, ▭); // 将客户视图窗口(sourceWnd)移动到指定客户视图窗口所在的相同标签窗格 void moveClientView(HWND sourceWnd, HWND targetWnd); // 将所有客户视图窗口移动到指定的分割窗格。 void moveClientViewsTo(SplitPane* targetPane); // 用目标客户视图分割源客户视图窗口(sourceWnd) void splitClientView(sourceWnd, targetWnd, targetArea); // 设置和获取图像列表 void setImageList(HIMAGELIST imgList); HIMAGELIST getImageList();

CallBackListener接口类

此类提供了SplitPane与其所有者类之间的通知接口。

// 当客户视图客户视图wnd获得键盘焦点时触发 virtual void clientActivate(childWnd, clientViewWnd) = 0; // 当客户视图客户视图wnd在标签按钮上双击鼠标时触发 virtual void clientDblClick(childWnd, clientViewWnd) = 0; // 当客户视图客户视图wnd的关闭按钮被按下时触发 virtual void clientCloseClick(childWnd, clientViewWnd) = 0; // 拖放通知 virtual void dragStart(childWnd, clientViewWnd, x, y, keysPressed) = 0; virtual void dragOver(childWnd, clientViewWnd, x, y, keysPressed) = 0; virtual void dragDrop(childWnd, clientViewWnd, x, y, keysPressed) = 0; virtual void dragCancel(childWnd, clientViewWnd) = 0; // 使用拖放通知执行拖放跟踪 void trackDragAndDrop(HWND hWnd, POINT startPoint, bool lockWindowUpdate = false);
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485