多重 MDI






3.83/5 (8投票s)
为您的 WTL 应用程序提供一些样板代码。
引言
好的,我们同意 WTL 是进行现代 UI 开发的正确选择,特别是当您想保持原生、精简且高效时。不是吗? WTL 向导可以很好地为您选择的应用程序类型提供样板代码,包括 MDI,这也是本文的重点。 话虽如此,只有一件事困扰着我:您获得的 MDI 文档应用程序允许您使用同一模板的多个副本,也就是说,您只能拥有一种类型的文档/窗体/您选择的任何窗口(顺便说一句,MFC 对应的向导也为您提供了几乎相同的东西),因此一遍又一遍地获得相同的功能。 我的意思是,这有用吗? 但当然,这个框架将允许您开发类似 Office 的应用程序。
问题在于,MS Word、MS Excel 等都已经开发出来了,坦白说,普通程序员不太可能为它们开发下一代替代品。 在现实世界中,我们最有可能从事开发处理特定任务的应用程序,这些任务最终将需要独立的窗口/窗体,所有这些都是同一个主应用程序框架的子级。 在这一点上,WTL 或 MFC MDI 向导提供的样板代码不会有太大帮助。 VB 程序员几乎可以免费获得此功能,尽管我不会深入探讨细节。 对于 C++,特别是使用 WTL,有许多解决方法。 在本文中,我将提供一个对我来说相当直接的解决方案。
背景
这是第一个版本,使用 VS 2003 和 WTL 7.5 开发(可从 sourceforge.net 获取)。
使用代码
基本思想依赖于继承,但在我们深入研究之前,让我们检查一下 WTL MDI 向导用来构建应用程序的三个主要类
CMainFrame
提供应用程序的主窗口。CChildFrame
正如其名称所暗示的那样:为子窗口提供框架。CXXXView
- 在随附的示例中,CMDI2View
是应用程序的“精髓”。 用 MFC 术语来说,它将构成文档和视图。 这是您程序操作发生的地方。
关键是:要在您的应用程序中拥有多种类型的文档/窗体/其他任何内容,您只需从视图类继承,如下所示
class CMDI2View1 : public CMDI2View
和
class CMDI2View2 : public CMDI2View
就是这样!... 并非真的;您需要提供一些东西才能使其正常工作
- 将代码添加到继承的视图中以提供不同的功能。
在演示应用程序中,我通过重写
OnPaint
方法来做到这一点,如下所示,在CMDI2View1
中LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CPaintDC dc(m_hWnd); RECT r; GetClientRect(&r); dc.SetBkColor(RGB(0,0,192)); dc.SetBkMode(TRANSPARENT); dc.SetTextColor(RGB(255,255,255)); CBrush brush; brush.CreateSolidBrush(RGB(0,0,192)); dc.SelectBrush(brush); dc.Rectangle(0,0,r.right, r.bottom); dc.DrawText(_T("Documento tipo Uno"),-1, &r,DT_VCENTER | DT_CENTER | DT_SINGLELINE); return 0; }
...在
CMDI2View2:
中。LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { CPaintDC dc(m_hWnd); RECT r; GetClientRect(&r); dc.SetBkColor(RGB(192,0,0)); dc.SetBkMode(TRANSPARENT); dc.SetTextColor(RGB(192,192,192)); CBrush brush; brush.CreateSolidBrush(RGB(192,0,0)); dc.SelectBrush(brush); dc.Rectangle(0,0,r.right, r.bottom); dc.DrawText(_T("Documento tipo Dos"),-1, &r,DT_VCENTER | DT_CENTER | DT_SINGLELINE); return 0; }
- 我们需要将
CChilFrame
的m_view
成员重新定义为指向其基类 (CMDIView
) 的指针。 因此,向导生成的行CMDI2View m_view
变成
CMDI2View* m_view
这对于允许视图类中的多态行为是必要的。
- 我们需要在
CChildFrame
类中定义一个变量,该变量允许选择要构造的视图类型,因此int iType; //View selector ... //Define a constructor that allows iType member initialization, //and a destructor that deletes the view. CChildFrame(int iiType = 1) : m_view(0), iType(iiType) { } ~CChildFrame() { if (m_view) delete m_view; }
- 我们需要修改
CChildFrame
类的OnCreate
方法,我这样做了LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { if (iType == 1) m_view = new CMDI2View1; else m_view = new CMDI2View2; m_hWndClient = m_view->Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE); char buf[256] = {0}; if (iType == 1) strcpy(buf, _T("Documento tipo I")); else strcpy(buf, _T("Documento tipo II")); SetWindowText(buf); if (iType == 1) { SetIcon(LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MDICHILD))); } else { SetIcon(LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MDICHILD2))); } bHandled = FALSE; return 1; } //The icon part and the Settitle part are not mandatory. //They just contribute to highlight differences between views.
- 最后,我们需要一种方法来选择将在
CMainFrame
类中启动哪个视图。 为了实现这一点,我在 IDID_FILE_NEW2
下添加了一个菜单项(以及工具栏图标)。随后,我像这样处理它
//Message map COMMAND_ID_HANDLER(ID_FILE_NEW2, OnFileNew2) ... //Original OnFileNew, remains unmodified, just takes //advantage of the default CChildFrame constructor LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { CChildFrame* pChild = new CChildFrame; pChild->CreateEx(m_hWndClient); // TODO: add code to initialize document return 0; } //Added to provide for the construction of CMDI2View2, //the key is CChildFrame construction parameter (2) LRESULT OnFileNew2(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { CChildFrame* pChild = new CChildFrame(2); pChild->CreateEx(m_hWndClient); return 0; }
现在... 真的就是这样了。
附注
有很多方法可以实现相同的功能,我只是发现这个例子快速而简单。 当然,您可以根据应用程序的需要添加任意数量的视图类型,但就本文而言,两个就足够了。 而 CFormView
将是视图的一个更好的基类,使用它不会增加太多难度,也不会增加显着的开销。 同样,我选择了一个原始视图以使其保持简单。
希望这有所帮助。