虽然在现代应用程序中,多重文档界面(MDI)的使用不如以前那么普遍,但它仍然是高级应用程序的强大选择。为了简化MDI子窗口的排列,MDISnapper工具在MDI客户端区域边界和其他子窗口上添加了“磁力边缘”,使得窗口排列变得更加容易。
最好的方法是尝试使用示例应用程序。打开一些窗口并将它们平铺(使用[H]键进行水平平铺,使用[V]键进行垂直平铺),然后进行操作!
要使用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特定内容。
以下是一些关键函数的文档说明:
通过键盘移动不使用“磁力”特性(但至少现在可以使用了)。
在当前实现中,即使它们“相距甚远”,边缘也会吸附到其他边缘(在示例应用程序中打开七个窗口,垂直平铺,关闭中间的两个,然后操作,您将看到意思)。这种行为是有意为之(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.