在可停靠窗格中使用對話框來實現可視化設計

摘要:本文將介紹如何在可停靠窗口(Dockable Pane)中使用對話框來來實現可視化設計,即將一個對話框(Dialog)做爲子窗口填充在可停靠窗格之中,這樣作的好處是使得能夠經過Visual Studio的對話框資源編輯功能可視化地設計窗口,並輕鬆地實現控件的消息處理程序。框架

關鍵字:Dockable Pane, Dialog, 可視化設計ide

 

1、使用可停靠窗格開發用戶界面函數

不少程序中都使用可停靠窗格做爲用戶界面中的重要組成部分,最熟悉的例子莫過於使用最多的Visual Studio。從VS2008 SP1和VS2010開始,新版的MFC框架中已經提供了一系列的類實現這樣的功能,其中最值得關注的是CDockablePane類。this

CDockablePane類表明了一個可停靠窗格,其用法能夠經過閱讀Visual Studio的「MFC應用程序嚮導」自動生成的源代碼來習得。建立一個可停靠窗格的步驟大體分爲五步:設計

(1) 定義一個類繼承自CDockablePane以實現特定的功能。code

(2) 在CMainFrame中定義上述類型成員變量。orm

(3) 在CMainFrame的OnCreate函數中調用CDockablePane的Create函數建立窗格。對象

(4) 調用CDockablePane的EnableDocking函數配置可停靠位置。blog

(5) 調用CMainFrame的DockPane函數停靠此窗格。繼承

詳情可參考Visual Studio生成的代碼,此處再也不贅述。

美中不足的是,Visual Studio並未提供對可停靠窗格進行可視化設計的支持。不過,若是須要,能夠經過對話框的功能來間接實現。

2、設計思路

依照使用方便、代碼可重用的設計原則,有如下幾個方面須要考慮:

(1) 應當提供用戶一個類來繼承使用(CDockableForm),爲了設計在對話框編輯視圖中添加控件關聯變量和事件處理程序,CDockableForm類應該是CDialog類的子類。

(2) 用戶建立此類的對象時,CDockablePane類的對象也應該隨之建立。該類提供一個Create函數,在該函數中應該同時完成可停靠窗格和對話框的建立過程。

(3) 對話框應該鋪滿可停靠窗格,並隨可停靠窗格隱藏而隱藏、顯示而顯示。這須要將對話框設置爲可停靠窗格的子窗口,並添加一個類(CDockablePaneAsContainer)繼承自CDockablePane,在其WM_SIZE消息處理函數中調整對話框的位置。

(4) 在可停靠窗格銷燬時,應該同時銷燬對話框。能夠可停靠窗格的WM_DESTROY消息處理函數中銷燬對話框。

(5) CDockablePane類應該提供一個成員函數使得用戶能夠訪問其CDockablePane成員,以實現其在主框架窗口(CMainFrame)中的停靠功能。

依上所述,設計的類如圖所示。

cd_thumb1

圖2-1 類圖

CDockableForm類和CDockablePaneAsContainter類的實現代碼見附錄1-4。

使用方法分爲四步:

(1) 建立、編輯對話框資源,添加對話框類,基類選擇CDialog類。

(2) 在項目中添加DockableForm.h和DockableForm.cpp(見附錄5),在對話框類的頭文件中包含DockableForm.h,將對話框類的基類改成CDockableForm,將對話框類的頭文件和源代碼文件中全部CDialog替換爲CDockableForm,同時也要修改一個對話框類的構造函數,由於CDockableForm類的構造函數與CDialog類的不同。

(3) 在CMainFrame類中添加第二步生成的類的成員,在其OnCreate函數中調用該成員的Create函數建立可停靠窗格,調用GetDockablePane方法獲得其可停靠窗格的引用以實現停靠功能。

使用示例見附錄5。

附錄

1. CDockableForm類的聲明代碼

class CDockablePaneAsContainer : public CDockablePane
{
public:
    CDockablePaneAsContainer(CDialog* pDialog) : m_pDialog(pDialog) { }
 
private:
    CDialog* m_pDialog;
 
public:
    DECLARE_MESSAGE_MAP()
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnDestroy();
};

 

2. CDockableForm的實現代碼。

BEGIN_MESSAGE_MAP(CDockablePaneAsContainer, CDockablePane)
    ON_WM_SIZE()
    ON_WM_DESTROY()
END_MESSAGE_MAP()
 
void CDockablePaneAsContainer::OnSize(UINT nType, int cx, int cy)
{
    CDockablePane::OnSize(nType, cx, cy);
     
    // TODO: 在此處添加消息處理程序代碼
    if (m_pDialog->GetSafeHwnd())
    {
        CRect rc;
        GetClientRect(rc);
        m_pDialog->MoveWindow(rc);
    }
}
 
void CDockablePaneAsContainer::OnDestroy()
{
    CDockablePane::OnDestroy();
 
    // TODO: 在此處添加消息處理程序代碼
    m_pDialog->DestroyWindow();
}

3. CDockableForm類的聲明代碼

class CDockableForm : public CDialog
{
public:
    CDockableForm(UINT nIDTemplate);
     virtual BOOL Create(
    LPCTSTR lpszCaption,
         CWnd* pParentWnd,
        const RECT& rect,
        BOOL bHasGripper,
        UINT nID, 
        DWORD dwStyle,
        DWORD dwTabbedStyle = AFX_CBRS_REGULAR_TABS,
        DWORD dwControlBarStyle = AFX_DEFAULT_DOCKING_PANE_STYLE,
        CCreateContext* pContext = NULL);
    CDockablePane& GetDockablePane() { return m_wndPane; }
private:
    CDockablePaneAsContainer m_wndPane;
};

 

4. CDockablePaneAsContainer的實現代碼

CDockableForm::CDockableForm(UINT nIDTemplate)
: CDialog(nIDTemplate, &m_wndPane)
, m_wndPane(this)
{
}
 
BOOL CDockableForm::Create(LPCTSTR lpszCaption, CWnd *pParentWnd, const RECT &rect, BOOL bHasGripper, UINT nID, DWORD dwStyle, DWORD dwTabbedStyle, DWORD dwControlBarStyle, CCreateContext *pContext)
{
    m_wndPane.Create(lpszCaption, pParentWnd, rect, bHasGripper, nID, dwStyle, dwTabbedStyle, dwControlBarStyle, pContext);
    CDialog::Create(m_nIDHelp, &m_wndPane);
    SetParent(&m_wndPane);
    ShowWindow(SW_SHOW);
    return TRUE;
}

 

5. 示例代碼

相關文章
相關標籤/搜索