[cpp] view plaincopyprint?關鍵字:CDockablePane, Visual Studio風格的Gui界面,,CDoackable裡嵌套FormView表單視圖步驟 www.2cto.com
關鍵字:CDockablePane, Visual Studio風格的Gui界面,,CDoackable裡嵌套FormView表單視圖步驟[cpp] view plaincopyprint?轉載注意作者原創:K_Linux_Man
轉載注意作者原創:K_Linux_Man
一直比較喜歡Visual Studio兩側的窗口,可以來回滑動,並且和點擊圖釘,釘住懸浮的窗口。那就嘗試著如何去做出來。
VC++6.0如果要去實現的話,不是不可以,但是得借助第三方的類庫,比如說,ToolKit,但是非常的麻煩。。。
Visual Studio裡面的新建Demo就可以實現這一功能,何樂而不為呢!!!
那停靠窗口裡面用什麼填充呢? 樹形控件??新建的Demo裡有了。更直觀一點的話,還是用FormView吧。。。好的。。。開始
要不先來個最終的效果圖..... 自己添加的解決方案停靠窗口,裡面嵌套FormView視圖窗口.而文件視圖,類視圖,還有屬性,Demo裡面默認生成的。只有解決方案那個是自己添加的。
新建兩個文件,SolutionWnd.h SolutionWnd.cpp
在資源窗口裡新建一個FormView的Dialog,修改ID為IDD_FORMVIEW,建立一個與FormView相關聯的的類, 利用類向導,添加一個名為CMfcFormView,選擇基類為CFormView. 生成在SolutionWnd.h和SolutionWnd.cpp文件裡。
SoulutionWnd.h
[cpp]
#pragma once
#include "Resource.h"
// CMfcFormView 窗體視圖
class CMfcFormView : public CFormView
{
<SPAN style="COLOR: rgb(255,0,0)">DECLARE_DYNCREATE</SPAN>(CMfcFormView)//<SPAN style="BACKGROUND-COLOR: rgb(255,0,0)">具有動態創建對象的能力</SPAN>
public:
CMfcFormView(): CFormView(CMfcFormView::IDD)
{}// 動態創建所使用的受保護的構造函數
~CMfcFormView()
{}
public:
public:
enum { IDD = IDD_FORMVIEW };
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
#pragma once
#include "Resource.h"
// CMfcFormView 窗體視圖
class CMfcFormView : public CFormView
{
DECLARE_DYNCREATE(CMfcFormView)//具有動態創建對象的能力
public:
CMfcFormView(): CFormView(CMfcFormView::IDD)
{}// 動態創建所使用的受保護的構造函數
~CMfcFormView()
{}
public:
public:
enum { IDD = IDD_FORMVIEW };
#ifdef _DEBUG
virtual void AssertValid() const;
#ifndef _WIN32_WCE
virtual void Dump(CDumpContext& dc) const;
#endif
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()[cpp] view plaincopyprint?};
};
SolutionWnd.cpp
[cpp]
#include "stdafx.h"
#include "SolutionWnd.h"
// CMfcFormView
<SPAN style="COLOR: #ff0000">IMPLEMENT_DYNCREATE</SPAN>(CMfcFormView, CFormView)
void CMfcFormView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMfcFormView, CFormView)
END_MESSAGE_MAP()
// CMfcFormView 診斷
#ifdef _DEBUG
void CMfcFormView::AssertValid() const
{
CFormView::AssertValid();
}
#ifndef _WIN32_WCE
void CMfcFormView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
#endif
#endif //_DEBUG
// CMfcFormView 消息處理程序
#include "stdafx.h"
#include "SolutionWnd.h"
// CMfcFormView
IMPLEMENT_DYNCREATE(CMfcFormView, CFormView)
void CMfcFormView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMfcFormView, CFormView)
END_MESSAGE_MAP()
// CMfcFormView 診斷
#ifdef _DEBUG
void CMfcFormView::AssertValid() const
{
CFormView::AssertValid();
}
#ifndef _WIN32_WCE
void CMfcFormView::Dump(CDumpContext& dc) const
{
CFormView::Dump(dc);
}
#endif
#endif //_DEBUG
// CMfcFormView 消息處理程序
至此我們已經把FormView派生出的CMfcFormView類建好了。
我們需要建立一個CDockablePane的派生類,予以容納FormView,建立派生出的CDockablePane類為CSolutionWnd
利用類向導,添加名為CSolutionWnd,基類為CDockablePane...生成文件SolutionWnd.h和SolutionWnd.cpp
SolutionWnd.h裡又添加了如下代碼
[cpp]
class CSolutionWnd : public CDockablePane
{
DECLARE_DYNAMIC(CSolutionWnd)
//構造函數
public:
CSolutionWnd();
//析構函數
~CSolutionWnd();
//特性
public:
protected:
CMfcFormView* m_pformView;
public:
DECLARE_MESSAGE_MAP()
};
class CSolutionWnd : public CDockablePane
{
DECLARE_DYNAMIC(CSolutionWnd)
//構造函數
public:
CSolutionWnd();
//析構函數
~CSolutionWnd();
//特性
public:
protected:
CMfcFormView* m_pformView;
public:
DECLARE_MESSAGE_MAP()
};
SolutionWnd.cpp
新添加的代碼
[cpp]
BEGIN_MESSAGE_MAP(CSolutionWnd, CDockablePane)
END_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(CSolutionWnd, CDockablePane)
CSolutionWnd::CSolutionWnd()
{
m_pformView = (CMfcFormView*) (RUNTIME_CLASS(CMfcFormView)->CreateObject());
}
CSolutionWnd::~CSolutionWnd()
{
}
BEGIN_MESSAGE_MAP(CSolutionWnd, CDockablePane)
END_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(CSolutionWnd, CDockablePane)
CSolutionWnd::CSolutionWnd()
{
m_pformView = (CMfcFormView*) (RUNTIME_CLASS(CMfcFormView)->CreateObject());
}
CSolutionWnd::~CSolutionWnd()
{
}
接著
1.在MainFrm.cpp裡添加m_wndSolution變量,類型為CSolutionWnd
2.在MainFrm.cpp裡的CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)函數裡添加代碼
[cpp]
// 創建停靠窗口
if (!CreateDockingWindows()) _
{
TRACE0("未能創建停靠窗口\n");
return -1;
}
m_wndFileView.EnableDocking(CBRS_ALIGN_ANY);
m_wndClassView.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndFileView); |
CDockablePane* pTabbedBar = NULL; |
m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);
m_wndOutput.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndOutput);
m_wndProperties.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndProperties);_
<SPAN style="COLOR: #ff0000">m_wndSolution.EnableDocking(CBRS_ALIGN_ANY);
m_wndSolution.AttachToTabWnd(&m_wndProperties, DM_SHOW, TRUE, &pTabbedBar);</SPAN><PRE class=cpp name="code"> // 紅色為自己添加</PRE><P></P>
<PRE></PRE>
<BR>
<BR>
<P></P>
<P>3.在MainFrm.cpp裡的CMainFrame::CreateDockingWindows()中添加代碼</P>
<P></P>
<PRE class=cpp name="code"><SPAN style="COLOR: #ff0000">//創建解決方案窗口
CString strSolutionWnd;
bNameValid = strSolutionWnd.LoadString(IDS_SOLUTION_WND);
ASSERT(bNameValid);
if(!</SPAN><SPAN style="COLOR: #3333ff">m_wndSolution.Create</SPAN><SPAN style="COLOR: #ff0000">(strSolutionWnd,this,CRect(0,0,200,200),TRUE,1234,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{
TRACE0("未能創建“解決方案窗口\n");
return FALSE;
}</SPAN></PRE>既然我們要創建CDockablePane那必然需要改寫OnCreate函數和OnSize函數,原因是,通過CDockablePane的創建必然會調用OnCreate函數,在OnCreate函數裡創建FormView,在OnSize裡面調整FormView的大小,覆蓋整個CDockablePane。
<P></P>
<P>利用類向導在CSolution聲明裡添加消息映射函數</P>
<P></P>
<PRE class=cpp name="code">public:
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);</PRE><BR>
<PRE class=cpp name="code">int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
return 0;
}
void CSolutionWnd::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
// TODO: 在此處添加消息處理程序代碼
}
</PRE><BR>
利用類向導在CMfcFormView裡添加消息映射函數OnCreate以及改寫虛函數Create
<P></P>
<P></P>
<PRE class=cpp name="code">afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);</PRE><BR>
<PRE class=cpp name="code">// CMfcFormView 消息處理程序
int CMfcFormView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
return 0;
}
BOOL CMfcFormView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: 在此添加專用代碼和/或調用基類
return CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}</PRE>
<P></P>
<P>在CSolution.h裡聲明CMfcFormView*類型的指針變量 </P>
<P></P>
<PRE class=cpp name="code">protected:
CMfcFormView* m_pformView;</PRE><BR>
在CSolution的構造函數裡創建CMfcFormView對象
<P></P>
<P></P>
<PRE class=cpp name="code">CSolutionWnd::CSolutionWnd()
{
m_pformView = (CMfcFormView*) (RUNTIME_CLASS(CMfcFormView)->CreateObject());
}
</PRE><BR>
在CSolution的OnCreate函數裡創建FormView
<P></P>
<P></P>
<PRE class=cpp name="code">int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
<SPAN style="COLOR: #ff0000">RECT rect;
GetClientRect(&rect);
m_pformView->Create(NULL, NULL, WS_CHILD|WS_VISIBLE, rect, this, 123, NULL);</SPAN>
return 0;
}</PRE><BR>
在CSolution的OnSize函數裡調整FormView填充整個DockablePane區域
<P></P>
<P></P>
<PRE class=cpp name="code">void CSolutionWnd::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
// TODO: 在此處添加消息處理程序代碼
if (GetSafeHwnd() == NULL)
{
return;
}
if(m_pformView->GetSafeHwnd()!=NULL)
{
CRect rect;
GetClientRect(rect);
m_pformView->SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOACTIVATE | SWP_NOZORDER);
}
}</PRE><BR>
<BR>
<P></P>
<P>至此結束。。。回答一些疑問。</P>
<P>為什麼要改寫CMfcFormView的Create虛函數呢?</P>
<P>因為我們要用到這句函數。</P>
<P><SPAN style="COLOR: rgb(255,0,0)">m_pformView->Create(NULL, NULL, WS_CHILD|WS_VISIBLE, rect, this, 123, NULL);</SPAN></P>
<P></P>
<P>調用到FormView::Create函數。由於FormView的Create函數是protected類型的.所以我們必須改寫FormView::Create函數為Publc類型。雖然我們在Create函數裡什麼也沒有做什麼。如果不重寫Create函數的話,那麼會出現編譯錯誤。</P>
<P><BR>
</P>
<P><BR>
</P>
// 創建停靠窗口
if (!CreateDockingWindows()) _
{
TRACE0("未能創建停靠窗口\n");
return -1;
}
m_wndFileView.EnableDocking(CBRS_ALIGN_ANY);
m_wndClassView.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndFileView); |
CDockablePane* pTabbedBar = NULL; |
m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);
m_wndOutput.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndOutput);
m_wndProperties.EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndProperties);_
m_wndSolution.EnableDocking(CBRS_ALIGN_ANY);
m_wndSolution.AttachToTabWnd(&m_wndProperties, DM_SHOW, TRUE, &pTabbedBar);[cpp] view plaincopyprint?// 紅色為自己添加 // 紅色為自己添加
3.在MainFrm.cpp裡的CMainFrame::CreateDockingWindows()中添加代碼
[cpp]
<SPAN style="COLOR: #ff0000">//創建解決方案窗口 CString strSolutionWnd; bNameValid = strSolutionWnd.LoadString(IDS_SOLUTION_WND); ASSERT(bNameValid); if(!</SPAN><SPAN style="COLOR: #3333ff">m_wndSolution.Create</SPAN><SPAN style="COLOR: #ff0000">(strSolutionWnd,this,CRect(0,0,200,200),TRUE,1234,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI)) { TRACE0("未能創建“解決方案窗口\n"); return FALSE; }</SPAN> //創建解決方案窗口
CString strSolutionWnd;
bNameValid = strSolutionWnd.LoadString(IDS_SOLUTION_WND);
ASSERT(bNameValid);
if(!m_wndSolution.Create(strSolutionWnd,this,CRect(0,0,200,200),TRUE,1234,WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI))
{
TRACE0("未能創建“解決方案窗口\n");
return FALSE;
}既然我們要創建CDockablePane那必然需要改寫OnCreate函數和OnSize函數,原因是,通過CDockablePane的創建必然會調用OnCreate函數,在OnCreate函數裡創建FormView,在OnSize裡面調整FormView的大小,覆蓋整個CDockablePane。
利用類向導在CSolution聲明裡添加消息映射函數
[cpp]
public: DECLARE_MESSAGE_MAP() afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSize(UINT nType, int cx, int cy); public:
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSize(UINT nType, int cx, int cy);
[cpp]
int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDockablePane::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您專用的創建代碼 return 0; } void CSolutionWnd::OnSize(UINT nType, int cx, int cy) { CDockablePane::OnSize(nType, cx, cy); // TODO: 在此處添加消息處理程序代碼 } int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
return 0;
}
void CSolutionWnd::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
// TODO: 在此處添加消息處理程序代碼
}
利用類向導在CMfcFormView裡添加消息映射函數OnCreate以及改寫虛函數Create
[cpp]
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
[cpp]
// CMfcFormView 消息處理程序 int CMfcFormView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFormView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您專用的創建代碼 return 0; } BOOL CMfcFormView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { // TODO: 在此添加專用代碼和/或調用基類 return CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext); } // CMfcFormView 消息處理程序
int CMfcFormView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
return 0;
}
BOOL CMfcFormView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: 在此添加專用代碼和/或調用基類
return CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}
在CSolution.h裡聲明CMfcFormView*類型的指針變量
[cpp]
protected: CMfcFormView* m_pformView; protected:
CMfcFormView* m_pformView;
在CSolution的構造函數裡創建CMfcFormView對象
[cpp]
CSolutionWnd::CSolutionWnd() { m_pformView = (CMfcFormView*) (RUNTIME_CLASS(CMfcFormView)->CreateObject()); } CSolutionWnd::CSolutionWnd()
{
m_pformView = (CMfcFormView*) (RUNTIME_CLASS(CMfcFormView)->CreateObject());
}
在CSolution的OnCreate函數裡創建FormView
[cpp]
int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDockablePane::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您專用的創建代碼 <SPAN style="COLOR: #ff0000">RECT rect; GetClientRect(&rect); m_pformView->Create(NULL, NULL, WS_CHILD|WS_VISIBLE, rect, this, 123, NULL);</SPAN> return 0; } int CSolutionWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
RECT rect;
GetClientRect(&rect);
m_pformView->Create(NULL, NULL, WS_CHILD|WS_VISIBLE, rect, this, 123, NULL);
return 0;
}
在CSolution的OnSize函數裡調整FormView填充整個DockablePane區域
[cpp]
void CSolutionWnd::OnSize(UINT nType, int cx, int cy) { CDockablePane::OnSize(nType, cx, cy); // TODO: 在此處添加消息處理程序代碼 if (GetSafeHwnd() == NULL) { return; } if(m_pformView->GetSafeHwnd()!=NULL) { CRect rect; GetClientRect(rect); m_pformView->SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOACTIVATE | SWP_NOZORDER); } } void CSolutionWnd::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
// TODO: 在此處添加消息處理程序代碼
if (GetSafeHwnd() == NULL)
{
return;
}
if(m_pformView->GetSafeHwnd()!=NULL)
{
CRect rect;
GetClientRect(rect);
m_pformView->SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOACTIVATE | SWP_NOZORDER);
}
}
至此結束。。。回答一些疑問。
為什麼要改寫CMfcFormView的Create虛函數呢?
因為我們要用到這句函數。
m_pformView->Create(NULL, NULL, WS_CHILD|WS_VISIBLE, rect, this, 123, NULL);
調用到FormView::Create函數。由於FormView的Create函數是protected類型的.所以我們必須改寫FormView::Create函數為Publc類型。雖然我們在Create函數裡什麼也沒有做什麼。如果不重寫Create函數的話,那麼會出現編譯錯誤。
分享到: