MDI窗口管理与MDISnapper工具的使用

虽然在现代应用程序中,多重文档界面(MDI)的使用不如以前那么普遍,但它仍然是高级应用程序的强大选择。为了简化MDI子窗口的排列,MDISnapper工具在MDI客户端区域边界和其他子窗口上添加了“磁力边缘”,使得窗口排列变得更加容易。

MDISnapper工具的体验

最好的方法是尝试使用示例应用程序。打开一些窗口并将它们平铺(使用[H]键进行水平平铺,使用[V]键进行垂直平铺),然后进行操作!

使用MDISnapper

要使用MDISnapper,请在您的项目中包含以下内容:

Declare a variable CMDISnapper m_mdiSnap accessible from all (e.g., in CFooApp or CMainFrame object) Adjust the snap width by calling m_mdiSnap.SetSnapWidth(int) . For CChildFrame (and other CMDIChildWnd derived classes you use), override WindowProc , and call m_mdiSnap.OnMessage before passing the message to the base class implementation.

实现概述

struct SNAPINFO实现了单个窗口的逻辑,并保存所需的状态变量。一个典型的调用(例如,在WM_SIZING/WM_MOVING中)如下所示:

//----- 1. Init ----- SNAPINFO sninf; // old, new position, size of catch area sninf.Init(rectOld, rectNew, snapWidth); //----- 2. provide horizontal/vertical "snap" lines ----- sninf.SnapVLine(0); // snap to left border sninf.SnapHLine(0); // snap to top border sninf.SnapVLine(clientArea.right); // snap to right border sninf.SnapHLine(clientArea.bottom); // snap to bottom border // ... additional snap lines // ... e.g. the borders of other MDI child windows //----- 3. finish ----- sninf.EndSnap(); rectNew = sninf.rout; rectNew could then be used as corrected position of the window.

CMDISnapper实现了MDI子窗口的确切逻辑。它假设并使用MDI客户端区域坐标,并进行适当的转换。

在其他项目/环境中的集成

SNAPINFO可以在任何Windows项目中使用,并执行基本计算。CMDISnapper使用MFC类,但可以轻松移植到例如ATL或Win32 API,因为它不依赖于MFC特定内容。

文档

以下是一些关键函数的文档说明:

  • struct SNAPINFO Init(RECT const & oldRect, RECT const & newRect, DWORD snapWidth) - 准备调整窗口大小或移动时的计算。
  • Init(RECT const & r, DWORD snapWidth, bool moveOnly) - 准备调整单个窗口的计算,与变化无关。
  • void SnapHLine(long y) - 指定水平线y坐标,窗口边缘可以吸附到该线。如果线足够接近窗口的顶部或底部边缘,将考虑该线。
  • void SnapVLine(long y) - 指定垂直线y坐标,窗口边缘可以吸附到该线。
  • RECT & EndSnap() - 返回包含最终坐标的rect的引用,调用EndSnap后。
  • class CMDISnapper CMDISnapper(DWORD snapWidth = 8) - MDISnapper构造函数,如果您已经知道您想要什么,可以指定吸附宽度。
  • void SetSnapWidth(DWORD snapWidth) - 设置/检索吸附宽度。它将用于下一个相关消息(目前是WM_SIZING和WM_MOVING)处理。
  • LRESULT OnMessage(CWnd * wnd, UINT msg, WPARAM wp, LPARAM lp) - 在应该吸附的窗口的窗口处理程序中调用此函数。传递窗口、发送的消息及其参数。可以忽略返回值。转发以下消息到特定处理程序:WM_SIZING, WM_MOVING, WM_ENTERSIZEMOVE, WM_EXITSIZEMOVE。
  • void Sizing(CWnd * wnd, RECT & rnew) - 从WM_SIZING和WM_MOVING处理程序调用;检索当前rect,遍历所有可见的兄弟窗口,并调整在rnew中指定的新大小/位置矩形。

通过键盘移动不使用“磁力”特性(但至少现在可以使用了)。

在当前实现中,即使它们“相距甚远”,边缘也会吸附到其他边缘(在示例应用程序中打开七个窗口,垂直平铺,关闭中间的两个,然后操作,您将看到意思)。这种行为是有意为之(sic!)。如果您只想吸附到“近”边缘,可以在CMDISnapper::Sizing中执行以下操作,当您遍历子窗口时:

Store a copy of the original rect of the sizing window, inflated by a few pixels (snapWidth comes into mind). Call SnapHLine only when the y coordinate falls into this inflated rect, similar for SnapVLine.
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485