最近iMaker2000的界面設計所用的是Doc/VIEw結構,涉及到Single Document的多視圖帶切分的切換。呵呵,光是述說都有點拗口了。VC做界面的確是麻煩啊,不過做好了我相信要比VB或者Delphi要好,靈活度也會更好。不過就工程角度來說,VC做界面學學也就行了,如果要大規模的做,還是簡單快捷的工具比較好。
在網上找了很久相關的代碼,最後終於在CodeGure上面找到了一個實現了相應功能的Project。一看時間,暈!98年的,算了,能實現功能就行了。
建立VIEw的過程就不多說了,這裡主要說說怎麼樣切換的。
不帶切分的切換比較普遍了,VC技術內幕就有一個詳細的代碼,我待會會把代碼也一起貼出來。
帶切分的主要的函數有2個,一個是建立時候的函數,一個是切換的函數,兩個基本上很類似,這裡分析一下切換的函數:
void CMainFrame::OnSwitchVIEw1()
{
// TODO: Add your command handler code here
CRect cr;
GetClIEntRect(&cr);//取得客戶區的顯示區域
CSize paneSize1(3*cr.Width()/4, cr.Height());//設定新vIEw大小
CCreateContext Context;//聲明視圖文檔聯系結構並設定其內容
Context.m_pNewViewClass=RUNTIME_CLASS(CSwitchVIEw1);
Context.m_pCurrentDoc=((CSwitchApp*)AfxGetApp())->m_pDoc;
Context.m_pCurrentFrame=this;
Context.m_pNewDocTemplate=Context.m_pCurrentDoc->GetDocTemplate();
Context.m_pLastView=(CVIEw*)m_wndSplitter.GetPane(0,0);
m_wndSplitter.DeleteView(0, 1);//刪除第1行第2列的VIEw
m_wndSplitter.CreateView(0, 1,RUNTIME_CLASS(CSwitchView1),paneSize1, &Context);//動態創建VIEw1
CSwitchView1 *pView=(CSwitchVIEw1*)m_wndSplitter.GetPane(0,1);//得到切分窗口的指針
pVIEw->GetParentFrame()->RecalcLayout();//重繪主窗口
m_wndSplitter.RecalcLayout();//重繪分隔條窗口
pVIEw->OnInitialUpdate();//估計是一些初始化的操作
m_wndSplitter.SetActivePane(0,1);//激活新的分隔區域
}
不帶切分的代碼如下:
void CMainFrame::SwitchToVIEw(int nForm)
{
//CDocument* pDoc = GetActiveDocument();
CView *pOldActiveView=GetActiveVIEw(); //保存舊視圖
CView *pNewActiveView=(CVIEw*)GetDlgItem(nForm); //取得新視圖
if(pNewActiveVIEw==NULL)
{
switch(nForm)
//這些ID是對話框的標志符,但也可以用其他的標志
{
case IDD_DIALOG1 :
pNewActiveView=(CVIEw*)new TForm;
break;
case IDD_FORMVIEW :
pNewActiveView=(CVIEw*)new TForm2;
break;
}
CCreateContext context; //將文擋和視圖相連
context.m_pCurrentDoc=pOldActiveVIEw->GetDocument();
pNewActiveVIEw->Create(NULL, NULL, WS_BORDER|WS_CHILD ,
CFrameWnd::rectDefault, this, nForm, &context);
pNewActiveVIEw->OnInitialUpdate();
}
SetActiveView(pNewActiveVIEw); //改變活動的視圖
pNewActiveVIEw->ShowWindow(SW_SHOW); //顯示新的視圖
pOldActiveVIEw->ShowWindow(SW_HIDE); //隱藏舊的視圖
if(pOldActiveVIEw->GetRuntimeClass() ==RUNTIME_CLASS(TForm))
pOldActiveVIEw->SetDlgCtrlID(IDD_DIALOG1);
else if(pOldActiveVIEw->GetRuntimeClass() ==RUNTIME_CLASS(TForm2))
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW);
pNewActiveVIEw->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
delete pOldActiveVIEw; //刪除舊視圖
RecalcLayout(); //調整框架窗口
}
比對一下可以看出,帶切分的主要是通過m_wndSplitter這樣一個成員進行操作,而不帶切分的則是直接對整個VIEw進行操作。(因為沒有m_wndSplitter啊,呵呵。)
補充一下:剛剛調試了一下代碼,有點波折,不過還是順利通過了,其實代碼可以簡化很多。
void CMainFrame::OnSwitchVIEw1()
{
m_wndSplitter.DeleteVIEw(1, 0);
m_wndSplitter.CreateVIEw(1, 0,
RUNTIME_CLASS(TForm2),
CSize(0, 0),
NULL);
m_wndSplitter.RecalcLayout();
}
當然,上面這個代碼只涉及到了界面的切換,具體的程序中的應用很可能和文檔有關,而且需要精確一點的控制,就需要看第一個函數了。注意我的VIEw是縱向的2個,所以參數是1,0。