Visual C++中Tab View的多種實(shí)現(xiàn)方法
本文實(shí)例講述了Visual C++中Tab View的多種實(shí)現(xiàn)方法,分享給大家供大家參考。具體如下:
一、引言
標(biāo)簽控件(Tab Control)是VC++編程中經(jīng)常使用的控件之一,它允許在單個(gè)對(duì)話(huà)框或窗口中設(shè)置多個(gè)頁(yè)面,每個(gè)頁(yè)面代表一組控件。當(dāng)某個(gè)頁(yè)面的標(biāo)簽被選中時(shí),該頁(yè) 面內(nèi)的控件就會(huì)被顯示出來(lái)。標(biāo)簽控件使得在有限的窗口空間內(nèi)可以顯示更多的信息,而且分類(lèi)清晰。同時(shí),VC++提供了以文檔/視圖 (Document/View)結(jié)構(gòu)方式開(kāi)發(fā)應(yīng)用程序的簡(jiǎn)單方法,在文檔中保存數(shù)據(jù),在視圖中顯示數(shù)據(jù)。無(wú)論是在SDI還是MDI的程序中,每個(gè)文檔可以 對(duì)應(yīng)一個(gè)或多個(gè)是視圖,但常常在顯示數(shù)據(jù)時(shí),需要將同一組數(shù)據(jù)用不同的視圖顯示,如列表視圖、樹(shù)型視圖等,或者用一個(gè)視圖顯示一部分?jǐn)?shù)據(jù),用另一個(gè)視圖顯 示另一部分?jǐn)?shù)據(jù),并且希望能在同一個(gè)顯示區(qū)顯示,在需要時(shí)進(jìn)行切換。將標(biāo)簽控制運(yùn)用到多視圖的切換中,就形成了Tab View。
通過(guò)上面的分析,我們不難發(fā)現(xiàn),實(shí)現(xiàn)一個(gè)Tab View主要要完成以下兩方面的工作:
① 實(shí)現(xiàn)一個(gè)標(biāo)簽窗口。它要具有繪制窗口、響應(yīng)用戶(hù)選擇、判斷處理用戶(hù)選擇等功能。本文對(duì)Tab View 實(shí)現(xiàn)方法的分類(lèi)就是根據(jù)標(biāo)簽窗口不同劃分的。
② 多個(gè)視圖之間的切換。根據(jù)標(biāo)簽窗口判斷用戶(hù)選擇的結(jié)果,從多個(gè)視圖中選擇一個(gè),在顯示區(qū)中顯示。
本文分析和總結(jié)了三種Tab View的實(shí)現(xiàn)方法:
1)利用CTabCtrl控件實(shí)現(xiàn)Tab View.
2)利用CSheetCtrl標(biāo)簽選擇窗口實(shí)現(xiàn)Tab View.
3)利用靜態(tài)分割窗口實(shí)現(xiàn)Tab View.
二、CTabCtrl控件實(shí)現(xiàn)Tab View
CTabCtrl是MFC類(lèi)庫(kù)中定義的標(biāo)準(zhǔn)控件類(lèi),通過(guò)對(duì)消息TCN-SELCHANGE的處理以及運(yùn)用函數(shù)GetCurSel()、 SetCurSel()等,可以很好地完成響應(yīng)、判斷和設(shè)置標(biāo)簽控制的工作,因此利用CTabCtrl控件實(shí)現(xiàn)Tab View是較容易的方法。
1.實(shí)現(xiàn)的主要類(lèi)
class CMyView1 : public CListView
class CMyView2 : public CView
//派生的標(biāo)簽控件類(lèi)
class CViewTabCtrl : public CTabCtrl
//定義了Tab view的主窗口
class CTabCtrlView : public CWnd
{
protected:
CViewTabCtrl m_TabCtl;
…
}
class CMainFrame : public CFrameWnd
{
CTabCtrlView m_TabView;
…
}
2.窗口之間的父子關(guān)系以及位置關(guān)系
下述代碼確定各窗口之間的位置關(guān)系。
{ …
CRect rect;
// CTabCtrlView窗口的客戶(hù)區(qū)大小
GetClientRect(&rect);
m_TabCtl.RecalcLayout(rect, pWnd);
…
}
void CViewTabCtrl::RecalcLayout(CRect & rect, CWnd * wnd)
{
//標(biāo)簽控件占據(jù)CTabCtrlView窗口的客戶(hù)區(qū)
SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, SWP_NOZORDER);
//調(diào)整要顯示的視窗口位置,使其占據(jù)標(biāo)簽控件的顯示區(qū)
AdjustRect(FALSE, &rect);
wnd->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, SWP_NOZORDER);
}
3.多個(gè)視之間切換的實(shí)現(xiàn)
視的切換主要完成下面的工作:
CView* pOldActiveView = GetActiveView();
::SetWindowLong(pOldActiveView->m_hWnd, GWL_ID, m_nCurrentExample);
// 步驟2:生成一個(gè)新的與所選擇的視窗口對(duì)應(yīng)的運(yùn)行時(shí)類(lèi)
CRuntimeClass* pNewViewClass;
switch (nViewID)// nViewID各個(gè)視圖的標(biāo)識(shí)
{
case ID_MYVIEW1:
pNewViewClass = RUNTIME_CLASS(CMyView1);
break;
case ID_MYVIEW2:
pNewViewClass = RUNTIME_CLASS(CMyView2);
break;
default:
ASSERT(0);
return;
}
// 步驟3:準(zhǔn)備新視圖類(lèi)的相關(guān)上下文,創(chuàng)建新的視
CCreateContext Context;
Context.m_pNewViewClass = pNewViewClass;
Context.m_pCurrentDoc = GetActiveDocument();
CView* pNewView = m_TabView.CreateView(pNewViewClass, CSize(100,100), &Context);
if (pNewView != NULL)
{
// 步驟4:顯示新的視圖
pNewView->ShowWindow(SW_SHOW);
SetActiveView(pNewView);
…
// 步驟5:關(guān)閉舊的視圖
pOldActiveView->DestroyWindow();
}
在視圖切換過(guò)程中,都需要重新生成新視圖,關(guān)閉舊的視圖。但在某些情況下,希望多個(gè)視圖窗口能夠同時(shí)存在,在某時(shí)刻只顯示一個(gè),而隱藏其它的窗口??梢酝ㄟ^(guò)定義下面的數(shù)據(jù)結(jié)構(gòu)和變量,將每次加入的新視圖的窗口信息保存。
{
CWnd *pWnd; //窗口指針
char szLabel[32]; //標(biāo)簽窗口對(duì)應(yīng)該視圖的字符串
}TCB_ITEM;
//將每次如入的視圖信息保存到列表中
CList <TCB_ITEM *,TCB_ITEM *> m_Views;
在切換時(shí),通過(guò)函數(shù)SetWindowPos()中設(shè)置參數(shù)SWP_SHOWWINDOW或SWP_HIDEWINDOW來(lái)顯示選中的新視圖,或隱藏舊視圖。采用這種方法,使對(duì)視圖操作更加靈活,可以很方便在Tab View中添加和刪除不同視圖。
三、CSheetCtrl標(biāo)簽選擇窗口實(shí)現(xiàn)Tab View
CSheetCtrl不是MFC類(lèi)庫(kù)中的類(lèi),用它來(lái)實(shí)現(xiàn)Tab View的方法和上一個(gè)方法基本相同。在程序員大本營(yíng)網(wǎng)站的VC編程源代碼集的[其它控制]分類(lèi)中,” A Tab-like Sheet Ctrl”程序含有該類(lèi)源代碼,但在使用時(shí)要將窗口的切換改為視圖切換。
1.標(biāo)簽窗口的創(chuàng)建
CSheetCtrl實(shí)現(xiàn)的Attach( )函數(shù),是它與外部的接口。在CTabSheetCtrl 中定義CSheetsWnd m_Sheet ,初始化過(guò)程中,通過(guò)調(diào)用m_Sheet.Attach( this)將CSheetCtrl創(chuàng)建為CTabSheetCtrl窗口的子窗口。
{
//確定了標(biāo)簽窗口的大小和位置
CRect rect = GetRect(pWndParent);
…
BOOL bResult = Create( … , rect , …);
…
return bResult;
}
CRect CSheetsWnd::GetRect(CWnd* pWndParent)
{
CRect rect;
pWndParent->GetClientRect(rect);
rect.top = rect.bottom - GetSystemMetrics(SM_CYVTHUMB);
return rect;
}
2.查找所選視圖窗口
CSheetCtrl實(shí)現(xiàn)了類(lèi)似于CTabCtrl的功能,如繪制標(biāo)簽窗口、判斷用戶(hù)的選擇等。它本身并沒(méi)有保存任何有關(guān)視圖的信息,在視圖切換時(shí),它通過(guò)其父窗口來(lái)查找用戶(hù)所選的視圖窗口。
CWnd* CSheetsWnd::GetFirstView()
{
m_pViewFind = GetParent()->GetWindow(GW_CHILD);
// m_hWnd存放的是CSheetCtrl標(biāo)簽窗口
//排除CSheetCtrl標(biāo)簽窗口
while (m_pViewFind && m_pViewFind->m_hWnd == m_hWnd)
m_pViewFind = m_pViewFind->GetWindow(GW_HWNDNEXT);
return m_pViewFind;
}
//得到下一個(gè)視圖窗口指針函數(shù)
CWnd* CSheetsWnd::GetNextView()
{
if (m_pViewFind)
{
m_pViewFind = m_pViewFind->GetWindow(GW_HWNDNEXT);
while (m_pViewFind && m_pViewFind->m_hWnd == m_hWnd)
m_pViewFind = m_pViewFind->GetWindow(GW_HWNDNEXT);
return m_pViewFind;
}
return NULL;
}
按一定的順序得到所有父窗口(CTabSheetCtrl)的子窗口(CMyView1、CMyView2)指針后,根據(jù)每個(gè)子窗口的標(biāo)題所占空間位置,來(lái)確定所選擇的視圖窗口。
CWnd* pChild = GetFirstView();
while (pChild)
{
CRect rect(cx,0,0,0);
//rect返回繪制該窗口的標(biāo)題所需的矩形大小
pDC->DrawText(GetViewTitle(pChild), rect, DEFAULTFORMATDRAWTEXT | DT_CALCRECT);
rect.top = 0;
rect.bottom = m_DrawRect.Height();
if ((aPointX > cx - LRB) && (aPointX <= cx + rect.Width() + LRB))// aPointX鼠標(biāo)位置的橫坐標(biāo)
break;//找到所選視圖
//獲得下一個(gè)視圖窗口的指針
pChild = GetNextView();
int next = rect.Width() + 6 + LRB;
cx += next;
}
四、靜態(tài)分割窗口實(shí)現(xiàn)Tab View
用靜態(tài)分割窗口CSplitterWnd實(shí)現(xiàn)Tab View,其主要的設(shè)計(jì)思想是通過(guò)分割窗口,使用splitter窗口的Pane(0,0)作為切換視的顯示區(qū),Pane(0,1)顯示類(lèi)似圖3的高級(jí)標(biāo) 簽窗口CWndTab。CSplitterWnd窗口完成了上面兩種方法中CTabCtrlView和CTabSheetView的工作,作為視的窗口和 標(biāo)簽窗口的容器。此方法的源代碼,在程序員大本營(yíng)網(wǎng)站也有。
五、結(jié)束語(yǔ)
筆者通過(guò)分析了多個(gè)相關(guān)程序的源代碼,并且在實(shí)際編程過(guò)程中,根據(jù)需要實(shí)現(xiàn)了自己的Tab View。在此簡(jiǎn)要地總結(jié)了三種實(shí)現(xiàn)Tab View 的方法,希望對(duì)讀者的編程能有所幫助。
上一篇:C++模板類(lèi)的用法
欄 目:C語(yǔ)言
下一篇:C++基于對(duì)話(huà)框的程序的框架實(shí)例
本文標(biāo)題:Visual C++中Tab View的多種實(shí)現(xiàn)方法
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/3233.html
您可能感興趣的文章
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)數(shù)怎么表達(dá)
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎么打出三角函數(shù)的值
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10APUE筆記之:進(jìn)程環(huán)境詳解
- 01-10c++中inline的用法分析
- 01-10如何尋找數(shù)組中的第二大數(shù)


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法


