WTL MDI 应用程序(带分隔器)






4.90/5 (10投票s)
2002年10月13日
2分钟阅读

147564

3565
本文介绍如何在带有分割窗口的 WTL MDI 应用程序的分割窗格中使用 MDI 客户端。
引言
本文解释如何在 MDI 应用程序中使用 WTL 的 CSplitterWindow
类。本文包含的示例项目是一个向导生成的 MDI 应用程序,它使用双窗格垂直分割器进行了增强。分割器的左侧是“关于”对话框(因此没有“帮助”菜单),右侧是 MDI 客户端窗口。
主框架
使用分割窗口的大部分相关代码都包含在示例项目的 mainframe.h
文件中。分割器通过调用 CreateClient()
方法并在 OnCreate()
中将结果分配给 m_hWndClient
来初始化。CreateClient()
设置左右窗格,发出对 CreateMDIClient()
的调用,并将结果分配给 m_hWndMDIClient
。重要的是将 MDI 客户端的父级更改为分割器,如下所示。
// Create and populate the spltter window HWND CreateClient() { // Get the Client RECT for the entire window as a starting size RECT rcClient; GetClientRect(&rcClient); // Create the vertical splitter. This is the main window m_splitter.Create(m_hWnd, rcClient, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); // Create the About dialog in the left pane m_about.Create(m_splitter.m_hWnd); m_splitter.SetSplitterPane(SPLIT_PANE_LEFT, m_about.m_hWnd); // Create the MDI client in the right pane m_hWndMDIClient = CreateMDIClient(); m_splitter.SetSplitterPane(SPLIT_PANE_RIGHT, m_hWndMDIClient); // IMPORTANT! Make the splitter the parent of the MDI client ::SetParent(m_hWndMDIClient, m_splitter.m_hWnd); m_splitter.SetSplitterPos(132); // from left // Splitter is ultimately the client of Main Frame (m_hWndClient) return m_splitter.m_hWnd; }
此外,对 OnFileNew
处理程序进行修改,以便为子窗口分配适当的父级:pChild->CreateEx(m_hWndMDIClient)
。在这种类型的操作中,使用 MDI 客户端句柄非常重要,因为 m_hWndClient
仅指分割窗口。
子框架
处理子窗口激活的相关代码包含在示例项目的 childfrm.h
文件中。带有编辑控件视图的子窗口在 OnCreate()
中初始化并分配了一个图标。此外,窗口消息 WM_MDIACTIVATE
被覆盖,以确保正确的标题栏和菜单激活和取消激活。 这是处理程序代码
LRESULT OnMDIActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // Child to deactivate ::SendMessage((HWND)wParam, WM_NCACTIVATE, FALSE, 0); // Child to activate ::SendMessage((HWND)lParam, WM_NCACTIVATE, TRUE, 0); // Set focus to the MDI client ::SetFocus(m_hWndMDIClient); // Switch to child window menu or back to default menu if((HWND)lParam == m_hWnd && m_hMenu != NULL) { HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu); MDISetMenu(m_hMenu, hWindowMenu); MDIRefreshMenu(); ::DrawMenuBar(GetMainFrame()); } else if((HWND)lParam == NULL) // last child has closed ::SendMessage(GetMainFrame(), WM_MDISETMENU, 0, 0); bHandled = FALSE; return 1; }
OnMDIActivate()
中调用的 GetMainFrame()
方法是一个简单的包装函数,用于说明分割窗口,如下所示
HWND GetMainFrame() { return ::GetParent(GetMDIFrame()); }
最后,另一个窗口消息 WM_MENUSELECT
被覆盖以允许激活子窗口的系统菜单(左上角的标题栏图标),如下所示
LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&)
{ return ::SendMessage(GetMainFrame(), uMsg, wParam, lParam); }
其他的东西
示例项目在 mainframe.h
中也有一些帮助程序例程,这些例程与 UpdateUI 机制一起工作,以在子窗口及其编辑控件处于活动状态时启用/禁用菜单和工具栏按钮。 WTL 类 CEditCommands
由视图 (mdisplitview.h
) 继承,为编辑控件提供标准的撤消、剪切、复制和粘贴功能。
示例项目还使用两个 WTL 消息映射宏在主框架和子框架之间交换命令。 CHAIN_MDI_CHILD_COMMANDS()
被添加到主框架消息映射,CHAIN_CLIENT_COMMANDS()
被添加到子框架映射,以便可以从主菜单和工具栏以及编辑控件的弹出菜单中使用编辑命令。
使用条款
本文提供的示例应用程序可免费用于任何目的。
本软件按“现状”分发,不提供任何形式的担保。