WTL 吸附式分割窗口






3.29/5 (7投票s)
2003年2月15日
2分钟阅读

60199

1450
一个简单的WTL CSplitterWindow改编,增加了吸附支持。
引言
我在开发一个使用日历控件的应用程序,需要控制包含日历控件的分割窗口的行为,所以我考虑创建一个支持吸附行为的分割窗口。
背景
我最初的想法把我带入了歧途,因为我试图将整个CSplitterWindow
重新实现为一个新类,这时我突然想到,只需重写OnMouseMove
方法即可。所以这就是我们现在所处的阶段。这是一个简单的代码更改,但我认为它会是一个有趣的贡献,所以我决定把它打包并提交到CodeProject。
使用代码
这段代码非常简单易用。你像使用CSplitterWindow
类一样使用它,但是还有一个额外的SetSnapSize
方法来控制吸附的大小。代码会处理你是使用垂直分割器还是水平分割器。
对这个类“最大”的改动是在从CSplitterWindow
派生的CSnapSplitterWindow
类中添加了几行代码。在OnSize
方法中添加了以下代码来支持吸附位置。变量m_nSnapSize
保存程序员希望窗口吸附到的尺寸。在鼠标移动过程中,我确定分割器的新位置是否大于吸附尺寸的一半,如果是,则将分割器调整到下一个吸附位置。这是一个简单的操作,但这确实是代码的“核心”。
// this is all that is required to make it snappable if( static_cast<UINT>(abs( xyNewSplitPos - m_xySplitterPos )) > ( m_nSnapSize / 2 )) { if( xyNewSplitPos < m_xySplitterPos ) xyNewSplitPos = m_xySplitterPos - m_nSnapSize; else xyNewSplitPos = m_xySplitterPos + m_nSnapSize; } else xyNewSplitPos = m_xySplitterPos;
要使用这段代码,如果想要一个在左右移动时吸附的垂直分割器,则声明一个CSnapSplitterWindow
变量;如果要创建一个在上下移动时吸附的水平分割器,则使用CHorSnapSplitterWindow
。以下代码将放置在你的CMainFrame
类的OnCreate
方法中。
class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>, public CMessageFilter, public CIdleHandler { public: DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME) CSnapSplitterWindow m_splitterContent; ... LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { ... m_hWndClient = m_splitterContent.Create( m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE ); m_splitterContent.SetSnapSize( 75 ); ... } ... };
关注点
一旦我克服了最初重写整个CSplitterWindow
类的尝试,编写这个类并不难,但我遇到的一个问题是使用CMonthCalendarCtrl
类。我调用了GetMinReqRect
,期望得到控件显示自身所需的最小尺寸。我认为最小尺寸就是设置水平和垂直吸附尺寸所需的一切,但我注意到控件不会显示另一个月份。所以我不得不尝试不同的高度和宽度调整,直到找到一些尽可能小的值,并且仍然允许控件在吸附到更大尺寸时按预期工作。
历史
版本 | 注释 |
1.0 - 2003年2月14日 | 第一个发行版本。 |