第七章 Creating MDI Apps

來源:互聯網
上載者:User

 

Creating MDI Apps

在 Multi-SDI 之前就有了 MDI , WTL 基於 CFramewindowImplBase基類提供了一系列相關類使得程式員編寫 MDI 應用程式尤其的簡單。Figure9 展示了 WTL 的 MDI 視窗架構.

Figure 9: MDI Windowing Hierarchy of WTL

 

CMDIWwindow 類是 MDI 應用程式的介面類, 繼承自 CWindow 基類並添加了兩個資料成員分別儲存 MDI 客戶區視窗控制代碼和 MDI 架構菜單控制代碼:
class CMDIWindow : public ATL::CWindow
{
public:
// Data members
    HWND m_hWndMDIClient;
    HMENU m_hMenu;
···
}
該類也封裝了 MDI 視窗特有的 WM_MDIXXX 訊息家族的發送處理請求, 以成員函數形式把相關功能提供給程式員使用, 成員函數命名為 MDIXXX().
MDI 應用程式由視窗架構, 管理 MDI 子視窗的架構客戶區以及 MDI 子視窗組成.(如 Figure 10 所示)

Figure 10: MDI Application Consisting of Frame, Client Area, and MDI Children

 

為了建立 MDI 子視窗, 需要從 CMDIChildWindowImpl 類派生自己的視窗類別.
class CChildFrame : public CMDIChildWindowImpl<CChildFrame> {

public:
    DECLARE_FRAME_WND_CLASS(NULL, IDR_MDICHILD)

    CHtmlView m_view;

    virtual void OnFinalMessage(HWND /*hWnd*/) {
        delete this;
    }

    BEGIN_MSG_MAP(CChildFrame)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        CHAIN_MSG_MAP(CMDIChildWindowImpl<CChildFrame>)
    END_MSG_MAP()

    LRESULT OnCreate(UINT,WPARAM,LPARAM,BOOL&) {
        m_hWndClient = m_view.Create(m_hWnd, rcDefault,
_T("http://www.microsoft.com"),
WS_CHILD | WS_VISIBLE, WS_EX_CLIENTEDGE);

        bHandled = FALSE; // Let base class have a crack
        return 1;
    }
    …
};
MDI 子架構視窗與 SDI 架構視窗很相似(MDI 子架構視窗類別一般命名為 CChildFrame). 比如, 通過傳遞菜單資源 ID 給 DECLARE_FRAME_WND_CLASS 宏來管理相關資源的建立, 正如在 SDI 架構視窗中所做的那樣. 同樣地, 我們在 WM_CREATE 訊息映射函數中建立視圖. 然而有所不同的是, 建立了視圖之後, 必須設定 bHandled 為 FALSE, 因為我們需要 MDI 子視窗基類繼續處理 WM_CREATE 訊息.
LRESULT CChildFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
    bHandled = FALSE;
    ···
}
最後, 在虛擬函數 OnFinalMessage() 中, MDI 子架構視窗類別對其自身調用 delete 操作符, 以此釋放相關資源.
void CChildFrame::OnFinalMessage(HWND /*hWnd*/)
{
    delete this;
}

按照我們的設計, CMDIFrameWindowImpl 類作為所有 MDI 架構視窗類別的基類, 實現了 MDI 架構和 MDI 客戶區. 如下樣本:
class CMainFrame : public CMDIFrameWindowImpl<CMainFrame> {
public:
    DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
    BEGIN_MSG_MAP(CMainFrame)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
        COMMAND_ID_HANDLER(ID_WINDOW_CASCADE, OnWindowCascade)
        …
        CHAIN_MSG_MAP(CMDIFrameWindowImpl<CMainFrame>)
    END_MSG_MAP()

    LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&)
    {

        // Create command bar window, toolbar and statusbar
        …

        // Create MDI client   
        CreateMDIClient();
m_CmdBar.SetMDIClient(m_hWndMDIClient);
        …
        return 0;
    }

    LRESULT OnFileNew(WORD, WORD, HWND, BOOL&)
    {
            // Create MDI child
        CChildFrame* pChild = new CChildFrame;
        pChild->CreateEx(m_hWndMDIClient);
        return 0;
    }

    LRESULT OnWindowCascade(WORD,WORD,HWND, BOOL&)
    {
        MDICascade();
        return 0;
    }

};
在 WM_CREATE 訊息映射函數中, 調用了基類 CMDIFrameWindowImpl 的成員函數 CreateMDIClient() 建立 MDI 客戶區並設定 m_hWndMDIClient 資料成員. MDI 客戶區是作為所有 MDI 子架構視窗的父視窗存在的. 而所有 MDI 子視窗都是在訊息處理函數 OnFileNew() 中被建立的, 每個 MDI 子視窗都是 MDI 子視窗類的一個執行個體, 並且以 MDI 客戶區作為其父視窗. 最後, 在 WinMain() 中我們建立 MDI 架構視窗, 這與 SDI 相似.

 

Divide and Conquer with Splitters

To be continued...  






聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.