簡(jiǎn) 介】
目前基于分割視圖的應(yīng)用開發(fā)十分流行,分割視圖技術(shù)是在同一個(gè)框架窗口下同時(shí)顯示多個(gè)視圖的一項(xiàng)技術(shù)。運(yùn)用分割視圖,可以在較短時(shí)間內(nèi)給用戶更多的信息量,從而使得用戶界面更加的友好,增強(qiáng)了軟件的可操作性。本文提出一個(gè)分割視圖的通用創(chuàng)建框架。
目前基于分割視圖的應(yīng)用開發(fā)十分流行,分割視圖技術(shù)是在同一個(gè)框架窗口下同時(shí)顯示多個(gè)視圖的一項(xiàng)技術(shù)。運(yùn)用分割視圖,可以在較短時(shí)間內(nèi)給用戶更多的信息量,從而使得用戶界面更加的友好,增強(qiáng)了軟件的可操作性。本文提出一個(gè)分割視圖的通用創(chuàng)建框架?! ?
1.分割視圖創(chuàng)建框架
分割視圖的創(chuàng)建大體上分為兩個(gè)步驟:其一是創(chuàng)建分割窗體;然后就是處理鼠標(biāo)和鍵盤等消息。
1) 創(chuàng)建分割窗體
MFC提供分割窗體類CsplitterWnd,它提供了很多對(duì)于分割窗體操作的成員函數(shù),每一個(gè)分割窗體都是一個(gè)CsplitterWnd的對(duì)象。本文提出的框架由于需要對(duì)定制的分割窗體進(jìn)行擴(kuò)充處理,所以首先從CsplitterWnd繼承一個(gè)子類CFixSplitterWnd,然后每個(gè)分割窗體是一個(gè)CfixSplitterWnd的對(duì)象,這樣以后只需要對(duì)CfixSplitterWnd進(jìn)行改寫后就可以增強(qiáng)分割窗體的功能。(后面將提出這種改寫)
創(chuàng)建分割窗體最重要的函數(shù)是主框架類的OnCreateClient函數(shù),它將在主框架創(chuàng)建的時(shí)候調(diào)用,本文將創(chuàng)建一個(gè)如下顯示的分割窗體:
則可以如下實(shí)現(xiàn):
//成員變量聲明
CFixSplitterWnd m_wndSplitterH; //用于橫向切割
CFixSplitterWnd m_wndSplitterV; //用于縱向切割
BOOL m_bCreateSplitter;
//分割窗體的實(shí)現(xiàn)
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
//對(duì)整個(gè)主框架進(jìn)行混合分割視圖
BOOL bResult=m_wndSplitterV.CreateStatic(this,1,2);
ASSERT(bResult);
m_wndSplitterH.CreateStatic(&m_wndSplitterV,4,1,WS_CHILD WS_VISIBLE,m_wndSplitterV.IdFromRowCol(0,1));
//創(chuàng)建各自子窗片的對(duì)應(yīng)的視圖
m_wndSplitterV.CreateView(0,0,RUNTIME_CLASS(CSceneView),CSize(600,600),pContext);
m_wndSplitterH.CreateView(0,0,RUNTIME_CLASS(CPitchView),CSize(100,100),pContext);
m_wndSplitterH.CreateView(1,0,RUNTIME_CLASS(CYawView),CSize(100,100),pContext);
m_wndSplitterH.CreateView(2,0,RUNTIME_CLASS(CRollView),CSize(100,100),pContext);
m_wndSplitterH.CreateView(3,0,RUNTIME_CLASS(CControlView),CSize(100,100),pContext);
//設(shè)置窗格的初始化的大小
m_wndSplitterV.SetRowInfo(0,IDEAL_RAWHEIGHT,0);
m_bCreateSplitter=TRUE;
//激活sceneview使得其可以接受命令消息
m_wndSplitterV.SetActivePane(0,0,NULL);
return bResult;
}
//主框架窗體大小發(fā)生變化,調(diào)節(jié)相應(yīng)的窗體大小
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CMDIFrameWnd::OnSize(nType, cx, cy);
CRect rect;
GetClientRect(rect);
if (m_bCreateSplitter)?
??????{
m_wndSplitterV.SetColumnInfo(0,rect.Width() *3/4,10);
m_wndSplitterV.SetColumnInfo(1,rect.Width() *1/4,10);
m_wndSplitterH.SetRowInfo(0,rect.Height() /6,10);
m_wndSplitterH.SetRowInfo(1,rect.Height() /6,10);
m_wndSplitterH.SetRowInfo(2,rect.Height() /6,10);
m_wndSplitterH.SetRowInfo(3,rect.Height()/2,10);
}
m_wndSplitterV.RecalcLayout();
m_wndSplitterH.RecalcLayout();
}
注意m_wndSplitterH.CreateView 中的第二個(gè)參數(shù),這個(gè)參數(shù)將分割窗體和相應(yīng)的視圖類相對(duì)應(yīng)。
通過(guò)上述的程序代碼即可創(chuàng)建圖1所示的分割窗體,那么由于這里每個(gè)分割窗體都是一個(gè)CfixSplitterWnd對(duì)象,所以可以通過(guò)改寫CfixSplitterWnd類的虛函數(shù)或消息處理函數(shù)來(lái)完成自己特定的應(yīng)用實(shí)現(xiàn)。(注意,如果需要對(duì)定制有特定屬性的分割窗體,一定要派生自己的分割窗體類而不能是MFC的CsplitterWnd類)這里我們需要分割窗體不能隨鼠標(biāo)拖動(dòng)而改變其大小,即所有窗格的大小都是一定的,不能在運(yùn)行時(shí)刻改變。所以必須在CfixSplitterWnd類的實(shí)現(xiàn)中加入如下代碼:
void CFixSplitterWnd::OnMouseMove(UINT nFlags, CPoint point)
{
CWnd::OnMouseMove(nFlags, point); //防止鼠標(biāo)出現(xiàn)拖動(dòng)狀
// CSplitterWnd::OnMouseMove(nFlags, point); //鼠標(biāo)會(huì)在窗體邊界出現(xiàn)拖動(dòng)狀
}
至此,分割窗體已經(jīng)創(chuàng)建完畢,下面需要在分割窗體里處理消息。
2) 分割窗體處理消息
在分割窗體里處理消息和一般的文檔視圖模型處理消息大致一樣,但它也有其特殊之處。具體來(lái)說(shuō),由于各個(gè)分割窗體已經(jīng)與具體的視圖類相聯(lián)系了,所以在需要處理各個(gè)分割窗體中的消息時(shí),可以直接到相應(yīng)的視圖類中進(jìn)行處理;另外,多視圖之間的切換會(huì)導(dǎo)致目標(biāo)焦點(diǎn)之間的變更,這樣會(huì)影響菜單中與視圖有關(guān)的命令的執(zhí)行。比如在圖1中所示的分割窗體中,有一個(gè)“開始”命令必須是焦點(diǎn)在CsceneView視圖上時(shí)才能執(zhí)行,否則就應(yīng)該讓該命令不能執(zhí)行(即該菜單呈現(xiàn)灰色),則實(shí)現(xiàn)時(shí)可以首先對(duì)鼠標(biāo)進(jìn)行點(diǎn)擊測(cè)試,判斷是否在CsceneView視圖范圍內(nèi),如果是的話就允許執(zhí)行,否則就不允許執(zhí)行。
2.結(jié)論
通過(guò)本文提出的分割視圖創(chuàng)建框架,可以滿足對(duì)視圖進(jìn)行復(fù)雜控制的需求,希望本文可以給大家一個(gè)啟發(fā),從而能夠創(chuàng)建更為完美的分割視圖應(yīng)用程序。