1)CTabView本質(zhì)上就是一種窗口容器,基于CCtrlView實現(xiàn),能夠容納類型為CWnd的所有窗口,并作為它的子窗口(為描述方便,在這特稱為視圖頁面),每個標簽對應(yīng)一個視圖頁面。
2)擴展了標準的標簽項數(shù)據(jù)結(jié)構(gòu)TC_ITEM,即自定義了一個TC_EXTRA_ITEM擴展數(shù)據(jù)結(jié)構(gòu),該結(jié)構(gòu)除包含標準的數(shù)據(jù)結(jié)構(gòu)(第1個成員)外,還包括視圖頁面對象、內(nèi)部標志、視圖頁面標題、視圖頁面關(guān)聯(lián)數(shù)據(jù)4種類型數(shù)據(jù),擴展數(shù)據(jù)大小需要在創(chuàng)建后插入標簽前調(diào)用SetItemExtra設(shè)定。
3)支持容納外部窗口和創(chuàng)建內(nèi)部窗口,前者是指容納外面已經(jīng)創(chuàng)建好的窗口;后者是根據(jù)窗口類型信息,由CTabView自己來管理創(chuàng)建視圖頁面。
4)對于內(nèi)部窗口的管理,為方便區(qū)分并有利于消息映射處理,因此窗口ID是唯一的,即在創(chuàng)建時分派一個新的不同的ID,銷毀時回收到ID數(shù)組中。而外部窗口ID則由外部管理。
5)提供激活視圖頁面后的自定義處理,表現(xiàn)為OnViewActivated虛函數(shù)。
6)提供右鍵單擊Tab標簽后的自定義處理,表現(xiàn)為OnTabContextMenu虛函數(shù)。
7)提供Tab標簽提示信息的自定義處理,表現(xiàn)為UpdateTooltipText虛函數(shù)。
8)提供CTabView視圖類的自繪處理(須設(shè)定TCS_OWNERDRAWFIXED樣式),表現(xiàn)為DrawItem虛函數(shù)。
9)Tab標簽的文本默認是簡寫的,即當長度超過最大值時,多余部分用省略號...代替,同時也支持自定義處理,表現(xiàn)為ShortenTitle虛函數(shù)。
10)對上述特點7,為了能支持派生類自定義處理,由于提示文本消息的發(fā)送者是CToolTipCtrl窗口,而不是CTabView本身,所以不能像TCN_SELCHANGE,NM_RCLICK等通知消息可以使用反射宏來實現(xiàn),因此使用了窗口子類化來捕獲父窗口的TTN_GETDISPINFO通知消息實現(xiàn)的。這一行為也可以通過UpdateTooltipText來定制,當其返回值是TRUE時,表示允許消息默認被父窗口接收處理,否則,反之。
11)對上述特點8,本可以重載OnChildNotify來實現(xiàn)WM_DRAWITEM消息的回調(diào),但為了簡潔,如同TTN_GETDISPINFO通知消息,也是使用窗口子類化來捕獲實現(xiàn)的。
12)對上述10和11的消息捕獲處理,使用了CBasicSubClassWnd類來實現(xiàn),表現(xiàn)為重寫其SubWindowProc虛函數(shù)。
接下來看看CTabView類的接口定義,如下所示
1
#ifndef _TABVIEW_H
2
#define _TABVIEW_H
3
4
#include <afxwin.h>
5
#include "basic_subclasswnd.h"
6
7
#define WC_TABVIEWA "SysTabControl32"
8
#define WC_TABVIEWW L"SysTabControl32"
9
10
#if (defined(_UNICODE)||defined(UNICODE))
11
#define WC_TABVIEW WC_TABVIEWW
12
#else
13
#define WC_TABVIEW WC_TABVIEWA
14
#endif
15
16
class CTabView : public CCtrlView,private CBasicSubClassWnd
17
{
18
DECLARE_DYNCREATE(CTabView)
19
20
struct TAB_VIEW
21
{
22
CWnd* pWnd; // 視圖頁面句柄
23
BOOL bInner; // 視圖頁面是否內(nèi)部創(chuàng)建
24
LPTSTR pszTitle; // 視圖頁面標題
25
LPVOID pData; // 視圖頁面數(shù)據(jù)
26
};
27
28
//擴展TC_ITEM數(shù)據(jù),第一個成員必須為TCITEMHEADER類型
29
struct TC_EXTRA_ITEM
30
{
31
TCITEMHEADER header;
32
TAB_VIEW view;
33
operator LPTCITEM() { return (LPTCITEM)this; }
34
};
35
36
public:
37
CTabView();
38
virtual ~CTabView();
39
40
CTabCtrl& GetTabCtrl() const;
41
42
//在最后增加視圖頁面
43
CWnd* AddView(CRuntimeClass* pClass,CCreateContext* pContext=NULL,LPCTSTR pszTitle=NULL,
44
int iImage=-1,LPVOID pData=NULL,BOOL bActivate=TRUE);
45
BOOL AddView(CWnd* pWnd,LPCTSTR pszTitle=NULL,int iImage=-1,LPVOID pData=NULL,BOOL bActivate=TRUE);
46
//在某處插入視圖頁面
47
CWnd* InsertView(int iIndex,CRuntimeClass* pClass,CCreateContext* pContext=NULL,LPCTSTR pszTitle=NULL,
48
int iImage=-1,LPVOID pData=NULL,BOOL bActivate=TRUE);
49
BOOL InsertView(int iIndex,CWnd* pWnd,LPCTSTR pszTitle=NULL,int iImage=-1,
50
LPVOID pData=NULL,BOOL bActivate=TRUE);
51
52
//移除視圖頁面
53
void RemoveView(int iIndex,BOOL bDestroy=TRUE);
54
void RemoveView(CWnd* pWnd,BOOL bDestroy=TRUE);
55
//移除所有視圖頁面
56
void RemoveAllView();
57
58
//獲取活動視圖頁面
59
CWnd* GetActiveView() const;
60
int GetActiveViewIndex() const;
61
//設(shè)置活動視圖頁面
62
void SetActiveViewIndex(int iIndex);
63
void SetActiveView(const CWnd* pWnd);
64
65
//按索引獲取某個視圖頁面
66
CWnd* GetView(int iIndex) const;
67
//按窗口獲取視圖頁面的索引
68
int GetIndex(const CWnd* pWnd) const;
69
70
//獲取視圖頁面數(shù)量
71
int GetViewCount() const;
72
73
//設(shè)置視圖頁面的標題
74
BOOL SetViewTitle(int iIndex,LPCTSTR pszTitle);
75
BOOL SetViewTitle(const CWnd* pWnd,LPCTSTR pszTitle);
76
//獲取視圖頁面的標題
77
BOOL GetViewTitle(const CWnd* pWnd,LPTSTR& pszTitle) const;
78
BOOL GetViewTitle(int iIndex,LPTSTR& pszTitle) const;
79
80
//設(shè)置圖像列表
81
CImageList* SetImageList(CImageList* pImageList);
82
//獲取圖像列表
83
CImageList* GetImageList() const;
84
//設(shè)置視圖頁面的圖像
85
BOOL SetViewImage(const CWnd* pWnd,int iImage);
86
BOOL SetViewImage(int iIndex,int iImage);
87
//獲取視圖頁面的圖像
88
BOOL GetViewImage(const CWnd* pWnd,int& iImage) const;
89
BOOL GetViewImage(int iIndex,int& iImage) const;
90
91
//設(shè)置視圖頁面的數(shù)據(jù)
92
BOOL SetViewData(int iIndex,LPVOID pData);
93
BOOL SetViewData(const CWnd* pWnd,LPVOID pData);
94
//獲取視圖頁面的數(shù)據(jù)
95
BOOL GetViewData(int iIndex,LPVOID& pData) const;
96
BOOL GetViewData(const CWnd* pWnd,LPVOID& pData) const;
97
98
//是否為內(nèi)部創(chuàng)建的視圖頁面
99
BOOL IsInnerView(const CWnd* pWnd,BOOL& bInner) const;
100
BOOL IsInnerView(int iIndex,BOOL& bInner) const;
101
102
//設(shè)置tab標簽可顯示的最大文本長度
103
void SetTabMaxTextLen(size_t len);
104
//獲取tab標簽可顯示的最大文本長度
105
size_t GetTabMaxTextLen() const;
106
107
virtual void ShortenTitle(LPCTSTR pszTitle,CString& strShortTitle);
108
109
protected:
110
BOOL SetViewInner(const CWnd* pWnd,BOOL bInner);
111
BOOL SetViewInner(int iIndex,BOOL bInner);
112
DWORD GetUniqueId();
113
BOOL IsValidViewIndex(int iIndex) const;
114
void UpdateLayout();
115
116
protected:
117
virtual BOOL SubWindowProc(UINT uMsg,WPARAM wParam,LPARAM lParam);
118
virtual int CalcTabHeight();
119
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItem);
120
virtual void OnViewActivated(int iIndex);
121
virtual void OnTabContextMenu(int iIndex,CPoint point);
122
virtual BOOL UpdateTooltipText(LPNMTTDISPINFO pTTDI);
123
124
protected:
125
DECLARE_MESSAGE_MAP()
126
afx_msg int OnCreate(LPCREATESTRUCT lpcs);
127
afx_msg void OnDestroy();
128
afx_msg void OnNMRclick(NMHDR *pNMHDR, LRESULT *pResult);
129
afx_msg void OnTcnSelChange(NMHDR* pNMHDR,LRESULT *pResult);
130
afx_msg void OnSize(UINT nType, int cx, int cy);
131
afx_msg void OnSetFocus(CWnd* pOldWnd);
132
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
133
134
public:
135
virtual void OnInitialUpdate();
136
137
private:
138
CArray<UINT,UINT> m_UniqueIDs;
139
int m_iActiveView;
140
int m_cyTabHeight;
141
size_t m_nMaxTabTextLen;
142
};
143
144
#endif
#ifndef _TABVIEW_H2
#define _TABVIEW_H3

4
#include <afxwin.h>5
#include "basic_subclasswnd.h"6

7
#define WC_TABVIEWA "SysTabControl32" 8
#define WC_TABVIEWW L"SysTabControl32"9

10
#if (defined(_UNICODE)||defined(UNICODE)) 11
#define WC_TABVIEW WC_TABVIEWW12
#else13
#define WC_TABVIEW WC_TABVIEWA14
#endif15

16
class CTabView : public CCtrlView,private CBasicSubClassWnd17
{18
DECLARE_DYNCREATE(CTabView)19

20
struct TAB_VIEW21
{22
CWnd* pWnd; // 視圖頁面句柄23
BOOL bInner; // 視圖頁面是否內(nèi)部創(chuàng)建24
LPTSTR pszTitle; // 視圖頁面標題25
LPVOID pData; // 視圖頁面數(shù)據(jù)26
};27

28
//擴展TC_ITEM數(shù)據(jù),第一個成員必須為TCITEMHEADER類型29
struct TC_EXTRA_ITEM30
{31
TCITEMHEADER header;32
TAB_VIEW view;33
operator LPTCITEM() { return (LPTCITEM)this; }34
};35

36
public:37
CTabView();38
virtual ~CTabView();39

40
CTabCtrl& GetTabCtrl() const;41

42
//在最后增加視圖頁面43
CWnd* AddView(CRuntimeClass* pClass,CCreateContext* pContext=NULL,LPCTSTR pszTitle=NULL,44
int iImage=-1,LPVOID pData=NULL,BOOL bActivate=TRUE);45
BOOL AddView(CWnd* pWnd,LPCTSTR pszTitle=NULL,int iImage=-1,LPVOID pData=NULL,BOOL bActivate=TRUE);46
//在某處插入視圖頁面47
CWnd* InsertView(int iIndex,CRuntimeClass* pClass,CCreateContext* pContext=NULL,LPCTSTR pszTitle=NULL,48
int iImage=-1,LPVOID pData=NULL,BOOL bActivate=TRUE);49
BOOL InsertView(int iIndex,CWnd* pWnd,LPCTSTR pszTitle=NULL,int iImage=-1,50
LPVOID pData=NULL,BOOL bActivate=TRUE);51

52
//移除視圖頁面53
void RemoveView(int iIndex,BOOL bDestroy=TRUE);54
void RemoveView(CWnd* pWnd,BOOL bDestroy=TRUE);55
//移除所有視圖頁面56
void RemoveAllView();57

58
//獲取活動視圖頁面59
CWnd* GetActiveView() const;60
int GetActiveViewIndex() const;61
//設(shè)置活動視圖頁面62
void SetActiveViewIndex(int iIndex);63
void SetActiveView(const CWnd* pWnd);64

65
//按索引獲取某個視圖頁面66
CWnd* GetView(int iIndex) const;67
//按窗口獲取視圖頁面的索引68
int GetIndex(const CWnd* pWnd) const;69

70
//獲取視圖頁面數(shù)量71
int GetViewCount() const;72
73
//設(shè)置視圖頁面的標題74
BOOL SetViewTitle(int iIndex,LPCTSTR pszTitle);75
BOOL SetViewTitle(const CWnd* pWnd,LPCTSTR pszTitle);76
//獲取視圖頁面的標題77
BOOL GetViewTitle(const CWnd* pWnd,LPTSTR& pszTitle) const;78
BOOL GetViewTitle(int iIndex,LPTSTR& pszTitle) const;79

80
//設(shè)置圖像列表81
CImageList* SetImageList(CImageList* pImageList);82
//獲取圖像列表83
CImageList* GetImageList() const;84
//設(shè)置視圖頁面的圖像85
BOOL SetViewImage(const CWnd* pWnd,int iImage);86
BOOL SetViewImage(int iIndex,int iImage);87
//獲取視圖頁面的圖像88
BOOL GetViewImage(const CWnd* pWnd,int& iImage) const;89
BOOL GetViewImage(int iIndex,int& iImage) const;90

91
//設(shè)置視圖頁面的數(shù)據(jù)92
BOOL SetViewData(int iIndex,LPVOID pData);93
BOOL SetViewData(const CWnd* pWnd,LPVOID pData);94
//獲取視圖頁面的數(shù)據(jù)95
BOOL GetViewData(int iIndex,LPVOID& pData) const;96
BOOL GetViewData(const CWnd* pWnd,LPVOID& pData) const;97

98
//是否為內(nèi)部創(chuàng)建的視圖頁面99
BOOL IsInnerView(const CWnd* pWnd,BOOL& bInner) const;100
BOOL IsInnerView(int iIndex,BOOL& bInner) const;101

102
//設(shè)置tab標簽可顯示的最大文本長度103
void SetTabMaxTextLen(size_t len); 104
//獲取tab標簽可顯示的最大文本長度105
size_t GetTabMaxTextLen() const; 106

107
virtual void ShortenTitle(LPCTSTR pszTitle,CString& strShortTitle);108

109
protected:110
BOOL SetViewInner(const CWnd* pWnd,BOOL bInner);111
BOOL SetViewInner(int iIndex,BOOL bInner);112
DWORD GetUniqueId();113
BOOL IsValidViewIndex(int iIndex) const;114
void UpdateLayout();115
116
protected:117
virtual BOOL SubWindowProc(UINT uMsg,WPARAM wParam,LPARAM lParam);118
virtual int CalcTabHeight();119
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItem);120
virtual void OnViewActivated(int iIndex);121
virtual void OnTabContextMenu(int iIndex,CPoint point);122
virtual BOOL UpdateTooltipText(LPNMTTDISPINFO pTTDI);123

124
protected:125
DECLARE_MESSAGE_MAP()126
afx_msg int OnCreate(LPCREATESTRUCT lpcs);127
afx_msg void OnDestroy();128
afx_msg void OnNMRclick(NMHDR *pNMHDR, LRESULT *pResult);129
afx_msg void OnTcnSelChange(NMHDR* pNMHDR,LRESULT *pResult);130
afx_msg void OnSize(UINT nType, int cx, int cy);131
afx_msg void OnSetFocus(CWnd* pOldWnd);132
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);133

134
public:135
virtual void OnInitialUpdate();136

137
private:138
CArray<UINT,UINT> m_UniqueIDs;139
int m_iActiveView;140
int m_cyTabHeight;141
size_t m_nMaxTabTextLen; 142
};143

144
#endif1)增加視圖頁面:AddIView,有2個重載形式,其中帶CRuntimeClass和CCreateConext類型參數(shù)的用于創(chuàng)建內(nèi)部窗口,成功返回對應(yīng)的窗口,否則為NULL;帶CWnd參數(shù)的用于容納外部窗口,成功返回TRUE,否則返回FALSE。
2)插入視圖頁面:InsertView,有2個重載形式,其中帶CRuntimeClass和CCreateConext類型參數(shù)的用于創(chuàng)建內(nèi)部窗口,成功返回對應(yīng)的窗口,否則為NULL;帶CWnd參數(shù)的用于容納外部窗口,成功返回TRUE,否則返回FALSE。
3)移除某個視圖頁面:RemoveView,有2個重載形式,其中int類型參數(shù)的用于按索引移除,CWnd類型的用于按窗口對象移除。
4)移除所有視圖頁面:RemoveAllView。5)獲取活動視圖頁面:有2個方法,GetActiveView如果無活動視圖頁面,則返回NULL,否則返回對應(yīng)的窗口;GetActiveViewIndex如果無活動視圖頁面,則返回-1,否則返回>=0的索引值。
5)設(shè)置活動視圖頁面:有2個方法:SetActiveView按窗口來設(shè)置,SetActiveViewIndex按索引來設(shè)置。
6)視圖頁面窗口與索引的相互轉(zhuǎn)換:GetView由窗口得到其索引,操作失敗返回-1,否則返回>=0的索引值。GetIndex由索引得到窗口,失敗返回NULL,否則返回對應(yīng)的窗口。
7)獲取視圖頁面的數(shù)量:GetViewCount。
8)設(shè)置視圖頁面的標題:SetViewTitle,有2個重載形式,int類型參數(shù)的按索引設(shè)置,CWnd類型參數(shù)的按窗口設(shè)置,成功返回TRUE,否則返回FALSE。
9)獲取視圖頁面的標題:GetViewTitle,有2個重載形式,int類型參數(shù)的按索引獲取,CWnd類型參數(shù)的按窗口獲取,成功返回TRUE,否則返回FALSE。
10)設(shè)置圖像列表:SetImageList。
11)獲取圖像列表:GetImageList。
12)設(shè)置視圖頁面的圖像:有2個重載形式,int類型參數(shù)的按索引設(shè)置,CWnd類型參數(shù)的按窗口設(shè)置,成功返回TRUE,否則返回FALSE。
13)獲取視圖頁面的圖像:有2個重載形式,int類型參數(shù)的按索引獲取,CWnd類型參數(shù)的按窗口獲取,成功返回TRUE,否則返回FALSE。
14)設(shè)置視圖頁面的數(shù)據(jù):有2個重載形式,int類型參數(shù)的按索引設(shè)置,CWnd類型參數(shù)的按窗口設(shè)置,成功返回TRUE,否則返回FALSE。
15)獲取視圖頁面的數(shù)據(jù):有2個重載形式,int類型參數(shù)的按索引獲取,CWnd類型參數(shù)的按窗口獲取,成功返回TRUE,否則返回FALSE。
16)視圖頁面內(nèi)部標志查詢:有2個重載形式,int類型參數(shù)的按索引查詢,CWnd類型參數(shù)的按窗口查詢,成功返回TRUE,否則返回FALSE,當操作成功時,參數(shù)bInner為TRUE表示為CTabView內(nèi)部創(chuàng)建的窗口,否則表示外部窗口。
最后列出主要部分的實現(xiàn)代碼,如下所示
1
CTabCtrl& CTabView::GetTabCtrl() const
2
{
3
return *(CTabCtrl*)this;
4
}
5
6
CWnd* CTabView::AddView(CRuntimeClass* pClass,CCreateContext* pContext,LPCTSTR pszTitle,
7
int iImage,LPVOID pData,BOOL bActivate)
8
{
9
return InsertView(GetViewCount(),pClass,pContext,pszTitle,iImage,pData,bActivate);
10
}
11
12
BOOL CTabView::AddView(CWnd* pWnd,LPCTSTR pszText,int iImage,LPVOID pData,BOOL bActivate)
13
{
14
return InsertView(GetViewCount(),pWnd,pszText,iImage,pData,bActivate);
15
}
16
17
CWnd* CTabView::InsertView(int iIndex,CRuntimeClass* pClass,CCreateContext* pContext,
18
LPCTSTR pszTitle,int iImage,LPVOID pData,BOOL bActivate)
19
{
20
ASSERT(::IsWindow(CCtrlView::m_hWnd));
21
ASSERT(pClass!=NULL);
22
ASSERT(pClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)));
23
ASSERT(AfxIsValidAddress(pClass,sizeof(CRuntimeClass),FALSE));
24
25
CWnd* pWnd = (CWnd*)pClass->CreateObject();
26
if (NULL==pWnd) return NULL;
27
ASSERT(pWnd->IsKindOf(RUNTIME_CLASS(CWnd)));
28
29
CCreateContext context;
30
if(pContext==NULL)
31
{
32
CView* pOldView=(CView*)GetActiveView();
33
if(pOldView!=NULL && pOldView->IsKindOf(RUNTIME_CLASS(CView)))
34
{
35
ASSERT(context.m_pCurrentFrame==NULL);
36
context.m_pLastView=pOldView;
37
context.m_pCurrentDoc=pOldView->GetDocument();
38
if(context.m_pCurrentDoc!=NULL)
39
{
40
context.m_pNewDocTemplate=context.m_pCurrentDoc->GetDocTemplate();
41
}
42
}
43
pContext=&context;
44
}
45
if (!pWnd->Create(NULL,NULL,WS_CHILD,CRect(0,0,0,0),this,GetUniqueId(),pContext))
46
{
47
delete pWnd; return NULL;
48
}
49
if (!InsertView(iIndex,pWnd,pszTitle,iImage,pData,bActivate))
50
{
51
pWnd->DestroyWindow(); return NULL;
52
}
53
SetViewInner(iIndex,TRUE);
54
return pWnd;
55
}
56
57
BOOL CTabView::InsertView(int iIndex,CWnd* pWnd,LPCTSTR pszTitle,int iImage,LPVOID pData,BOOL bActivate)
58
{
59
ASSERT(::IsWindow(CCtrlView::m_hWnd));
60
ASSERT(pWnd&&::IsWindow(pWnd->m_hWnd));
61
62
CString str;
63
ShortenTitle(pszTitle,str);
64
65
TC_EXTRA_ITEM ti;
66
ti.header.mask = TCIF_PARAM|TCIF_TEXT|TCIF_IMAGE;
67
ti.header.pszText = (LPTSTR)(LPCTSTR)str;
68
if (pszTitle)
69
{
70
ti.view.pszTitle = new TCHAR[_tcslen(pszTitle)+1];
71
if (NULL==ti.view.pszTitle)
72
return FALSE;
73
_tcscpy(ti.view.pszTitle,pszTitle);
74
}
75
else
76
{
77
ti.view.pszTitle = NULL;
78
}
79
ti.header.iImage = iImage;
80
ti.view.pWnd = pWnd;
81
ti.view.pData = pData;
82
if (-1==GetTabCtrl().InsertItem(iIndex,ti))
83
{
84
if (pszTitle) delete []ti.view.pszTitle;
85
return FALSE;
86
}
87
pWnd->SetParent(this);
88
if (bActivate)
89
{
90
SetActiveViewIndex(iIndex);
91
OnViewActivated(iIndex);
92
}
93
return TRUE;
94
}
95
96
void CTabView::RemoveView(CWnd* pWnd,BOOL bDestroy)
97
{
98
RemoveView(GetIndex(pWnd),bDestroy);
99
}
100
101
void CTabView::RemoveView(int iIndex,BOOL bDestroy)
102
{
103
ASSERT(::IsWindow(CCtrlView::m_hWnd));
104
ASSERT(IsValidViewIndex(iIndex));
105
106
CWnd* pWnd = GetView(iIndex);
107
ASSERT(pWnd);
108
109
BOOL bInner;
110
if (IsInnerView(iIndex,bInner) && bInner)
111
m_UniqueIDs.Add(pWnd->GetDlgCtrlID());
112
bDestroy ? pWnd->DestroyWindow() : pWnd->ShowWindow(SW_HIDE);
113
114
LPTSTR pszTitle;
115
if (GetViewTitle(iIndex,pszTitle))
116
delete []pszTitle;
117
118
ATLVERIFY(GetTabCtrl().DeleteItem(iIndex));
119
if(m_iActiveView == iIndex)
120
{
121
m_iActiveView = -1;
122
if(iIndex > 0)
123
{
124
SetActiveViewIndex(iIndex-1);
125
}
126
else if(GetViewCount() > 0)
127
{
128
SetActiveViewIndex(iIndex);
129
}
130
else
131
{
132
SetRedraw(TRUE);
133
Invalidate();
134
UpdateWindow();
135
}
136
}
137
else
138
{
139
iIndex = (iIndex < m_iActiveView) ? (m_iActiveView - 1) : m_iActiveView;
140
m_iActiveView = -1;
141
SetActiveViewIndex(iIndex);
142
}
143
if (-1!=m_iActiveView)
144
{
145
OnViewActivated(m_iActiveView);
146
}
147
}
148
149
void CTabView::RemoveAllView()
150
{
151
LPTSTR pszTitle;
152
for (int iIndex=0;iIndex<GetViewCount();++iIndex)
153
{
154
GetView(iIndex)->DestroyWindow();
155
if (GetViewTitle(iIndex,pszTitle))
156
delete []pszTitle;
157
}
158
GetTabCtrl().DeleteAllItems();
159
}
160
161
int CTabView::GetViewCount() const
162
{
163
ASSERT(::IsWindow(CCtrlView::m_hWnd));
164
return GetTabCtrl().GetItemCount();
165
}
166
167
CWnd* CTabView::GetView(int iIndex) const
168
{
169
ASSERT(::IsWindow(CCtrlView::m_hWnd));
170
ASSERT(IsValidViewIndex(iIndex));
171
172
TC_EXTRA_ITEM ti;
173
ti.header.mask = TCIF_PARAM;
174
if (!GetTabCtrl().GetItem(iIndex,ti))
175
return NULL;
176
return ti.view.pWnd;
177
}
178
179
int CTabView::GetIndex(const CWnd* pWnd) const
180
{
181
ASSERT(::IsWindow(CCtrlView::m_hWnd));
182
183
int count = GetTabCtrl().GetItemCount();
184
for (int i=0;i<count;++i)
185
{
186
if (GetView(i)==pWnd)
187
return i;
188
}
189
return -1;
190
}
191
192
CWnd* CTabView::GetActiveView() const
193
{
194
ASSERT(::IsWindow(CCtrlView::m_hWnd));
195
return (-1==m_iActiveView) ? NULL : GetView(m_iActiveView);
196
}
197
198
int CTabView::GetActiveViewIndex() const
199
{
200
return m_iActiveView;
201
}
202
203
void CTabView::SetActiveView(const CWnd* pWnd)
204
{
205
SetActiveViewIndex(GetIndex(pWnd));
206
}
207
208
void CTabView::SetActiveViewIndex(int iIndex)
209
{
210
ASSERT(::IsWindow(CCtrlView::m_hWnd));
211
ASSERT(IsValidViewIndex(iIndex));
212
213
if (iIndex==m_iActiveView)
214
return;
215
216
// SetRedraw(FALSE);
217
if (-1!=m_iActiveView)
218
{
219
GetView(m_iActiveView)->ShowWindow(SW_HIDE);
220
}
221
GetTabCtrl().SetCurSel(iIndex);
222
m_iActiveView = iIndex;
223
GetView(m_iActiveView)->ShowWindow(SW_SHOWNORMAL);
224
225
UpdateLayout();
226
227
//SetRedraw(TRUE);
228
//RedrawWindow(NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
229
230
if (GetFocus()!=this)
231
{
232
GetView(iIndex)->SetFocus();
233
}
234
}
235
236
BOOL CTabView::SetViewTitle(const CWnd* pWnd,LPCTSTR pszTitle)
237
{
238
return SetViewTitle(GetIndex(pWnd),pszTitle);
239
}
240
241
BOOL CTabView::SetViewTitle(int iIndex,LPCTSTR pszTitle)
242
{
243
ASSERT(::IsWindow(CCtrlView::m_hWnd));
244
ASSERT(IsValidViewIndex(iIndex));
245
246
TC_EXTRA_ITEM ti;
247
ti.header.mask = TCIF_PARAM;
248
if (!GetTabCtrl().GetItem(iIndex,ti))
249
return FALSE;
250
delete []ti.view.pszTitle;
251
252
CString str;
253
ShortenTitle(pszTitle,str);
254
255
ti.header.mask = TCIF_TEXT|TCIF_PARAM;
256
ti.header.pszText = (LPTSTR)(LPCTSTR)str;
257
if (pszTitle)
258
{
259
ti.view.pszTitle = new TCHAR[_tcslen(pszTitle)+1];
260
if (NULL==ti.view.pszTitle)
261
return FALSE;
262
_tcscpy(ti.view.pszTitle,pszTitle);
263
}
264
if (!GetTabCtrl().SetItem(iIndex,ti))
265
{
266
if (pszTitle) delete []ti.view.pszTitle;
267
return FALSE;
268
}
269
return TRUE;
270
}
271
272
BOOL CTabView::GetViewTitle(const CWnd* pWnd,LPTSTR& pszTitle) const
273
{
274
return GetViewTitle(GetIndex(pWnd),pszTitle);
275
}
276
277
BOOL CTabView::GetViewTitle(int iIndex,LPTSTR& pszTitle) const
278
{
279
ASSERT(IsValidViewIndex(iIndex));
280
281
TC_EXTRA_ITEM ti;
282
ti.header.mask = TCIF_PARAM;
283
if (!GetTabCtrl().GetItem(iIndex,ti))
284
return FALSE;
285
pszTitle = ti.view.pszTitle;
286
return TRUE;
287
}
288
289
CImageList* CTabView::SetImageList(CImageList* pImageList)
290
{
291
ASSERT(CCtrlView::m_hWnd);
292
return GetTabCtrl().SetImageList(pImageList);
293
}
294
295
CImageList* CTabView::GetImageList() const
296
{
297
ASSERT(CCtrlView::m_hWnd);
298
return GetTabCtrl().GetImageList();
299
}
300
301
BOOL CTabView::SetViewImage(const CWnd* pWnd,int iImage)
302
{
303
return SetViewImage(GetIndex(pWnd),iImage);
304
}
305
306
BOOL CTabView::SetViewImage(int iIndex,int iImage)
307
{
308
ASSERT(IsValidViewIndex(iIndex));
309
310
TC_EXTRA_ITEM ti;
311
ti.header.mask = TCIF_IMAGE;
312
ti.header.iImage = iImage;
313
return GetTabCtrl().SetItem(iIndex,ti);
314
}
315
316
BOOL CTabView::GetViewImage(const CWnd* pWnd,int& iImage) const
317
{
318
return GetViewImage(GetIndex(pWnd),iImage);
319
}
320
321
BOOL CTabView::GetViewImage(int iIndex,int& iImage) const
322
{
323
ASSERT(IsValidViewIndex(iIndex));
324
325
TC_EXTRA_ITEM ti;
326
ti.header.mask = TCIF_IMAGE;
327
if (!GetTabCtrl().GetItem(iIndex,ti))
328
return FALSE;
329
iImage = ti.header.iImage;
330
return TRUE;
331
}
332
333
BOOL CTabView::SetViewData(const CWnd* pWnd,LPVOID pData)
334
{
335
return SetViewData(GetIndex(pWnd),pData);
336
}
337
338
BOOL CTabView::SetViewData(int iIndex,LPVOID pData)
339
{
340
ASSERT(IsValidViewIndex(iIndex));
341
342
TC_EXTRA_ITEM ti;
343
ti.header.mask = TCIF_PARAM;
344
if (!GetTabCtrl().GetItem(iIndex,ti))
345
return FALSE;
346
ti.header.mask = TCIF_PARAM;
347
ti.view.pData = pData;
348
return GetTabCtrl().SetItem(iIndex,ti);
349
}
350
351
BOOL CTabView::GetViewData(const CWnd* pWnd,LPVOID& pData) const
352
{
353
return GetViewData(GetIndex(pWnd),pData);
354
}
355
356
BOOL CTabView::GetViewData(int iIndex,LPVOID& pData) const
357
{
358
TC_EXTRA_ITEM ti;
359
ti.header.mask = TCIF_PARAM;
360
if (!GetTabCtrl().GetItem(iIndex,ti))
361
return FALSE;
362
pData = ti.view.pData;
363
return TRUE;
364
}
365
366
BOOL CTabView::IsInnerView(const CWnd* pWnd,BOOL& bInner) const
367
{
368
return IsInnerView(GetIndex(pWnd),bInner);
369
}
370
371
BOOL CTabView::IsInnerView(int iIndex,BOOL& bInner) const
372
{
373
ASSERT(IsValidViewIndex(iIndex));
374
375
TC_EXTRA_ITEM ti;
376
ti.header.mask = TCIF_PARAM;
377
if (!GetTabCtrl().GetItem(iIndex,ti))
378
return FALSE;
379
bInner = ti.view.bInner;
380
return TRUE;
381
}
CTabCtrl& CTabView::GetTabCtrl() const2
{3
return *(CTabCtrl*)this;4
}5

6
CWnd* CTabView::AddView(CRuntimeClass* pClass,CCreateContext* pContext,LPCTSTR pszTitle,7
int iImage,LPVOID pData,BOOL bActivate)8
{9
return InsertView(GetViewCount(),pClass,pContext,pszTitle,iImage,pData,bActivate);10
}11

12
BOOL CTabView::AddView(CWnd* pWnd,LPCTSTR pszText,int iImage,LPVOID pData,BOOL bActivate)13
{14
return InsertView(GetViewCount(),pWnd,pszText,iImage,pData,bActivate);15
}16

17
CWnd* CTabView::InsertView(int iIndex,CRuntimeClass* pClass,CCreateContext* pContext,18
LPCTSTR pszTitle,int iImage,LPVOID pData,BOOL bActivate)19
{20
ASSERT(::IsWindow(CCtrlView::m_hWnd));21
ASSERT(pClass!=NULL);22
ASSERT(pClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)));23
ASSERT(AfxIsValidAddress(pClass,sizeof(CRuntimeClass),FALSE));24

25
CWnd* pWnd = (CWnd*)pClass->CreateObject();26
if (NULL==pWnd) return NULL;27
ASSERT(pWnd->IsKindOf(RUNTIME_CLASS(CWnd)));28

29
CCreateContext context;30
if(pContext==NULL)31
{32
CView* pOldView=(CView*)GetActiveView();33
if(pOldView!=NULL && pOldView->IsKindOf(RUNTIME_CLASS(CView)))34
{35
ASSERT(context.m_pCurrentFrame==NULL);36
context.m_pLastView=pOldView;37
context.m_pCurrentDoc=pOldView->GetDocument();38
if(context.m_pCurrentDoc!=NULL)39
{40
context.m_pNewDocTemplate=context.m_pCurrentDoc->GetDocTemplate();41
}42
}43
pContext=&context;44
}45
if (!pWnd->Create(NULL,NULL,WS_CHILD,CRect(0,0,0,0),this,GetUniqueId(),pContext))46
{47
delete pWnd; return NULL;48
}49
if (!InsertView(iIndex,pWnd,pszTitle,iImage,pData,bActivate))50
{51
pWnd->DestroyWindow(); return NULL;52
}53
SetViewInner(iIndex,TRUE);54
return pWnd;55
}56

57
BOOL CTabView::InsertView(int iIndex,CWnd* pWnd,LPCTSTR pszTitle,int iImage,LPVOID pData,BOOL bActivate)58
{59
ASSERT(::IsWindow(CCtrlView::m_hWnd));60
ASSERT(pWnd&&::IsWindow(pWnd->m_hWnd));61

62
CString str;63
ShortenTitle(pszTitle,str);64

65
TC_EXTRA_ITEM ti;66
ti.header.mask = TCIF_PARAM|TCIF_TEXT|TCIF_IMAGE;67
ti.header.pszText = (LPTSTR)(LPCTSTR)str;68
if (pszTitle) 69
{70
ti.view.pszTitle = new TCHAR[_tcslen(pszTitle)+1];71
if (NULL==ti.view.pszTitle)72
return FALSE;73
_tcscpy(ti.view.pszTitle,pszTitle);74
}75
else76
{77
ti.view.pszTitle = NULL;78
}79
ti.header.iImage = iImage;80
ti.view.pWnd = pWnd;81
ti.view.pData = pData;82
if (-1==GetTabCtrl().InsertItem(iIndex,ti))83
{84
if (pszTitle) delete []ti.view.pszTitle; 85
return FALSE;86
}87
pWnd->SetParent(this);88
if (bActivate)89
{90
SetActiveViewIndex(iIndex);91
OnViewActivated(iIndex);92
}93
return TRUE;94
}95

96
void CTabView::RemoveView(CWnd* pWnd,BOOL bDestroy)97
{98
RemoveView(GetIndex(pWnd),bDestroy);99
}100

101
void CTabView::RemoveView(int iIndex,BOOL bDestroy)102
{103
ASSERT(::IsWindow(CCtrlView::m_hWnd));104
ASSERT(IsValidViewIndex(iIndex));105

106
CWnd* pWnd = GetView(iIndex);107
ASSERT(pWnd);108

109
BOOL bInner;110
if (IsInnerView(iIndex,bInner) && bInner)111
m_UniqueIDs.Add(pWnd->GetDlgCtrlID());112
bDestroy ? pWnd->DestroyWindow() : pWnd->ShowWindow(SW_HIDE);113
114
LPTSTR pszTitle;115
if (GetViewTitle(iIndex,pszTitle)) 116
delete []pszTitle;117
118
ATLVERIFY(GetTabCtrl().DeleteItem(iIndex));119
if(m_iActiveView == iIndex)120
{121
m_iActiveView = -1;122
if(iIndex > 0)123
{124
SetActiveViewIndex(iIndex-1);125
}126
else if(GetViewCount() > 0)127
{128
SetActiveViewIndex(iIndex);129
}130
else131
{132
SetRedraw(TRUE);133
Invalidate();134
UpdateWindow();135
}136
}137
else138
{139
iIndex = (iIndex < m_iActiveView) ? (m_iActiveView - 1) : m_iActiveView;140
m_iActiveView = -1;141
SetActiveViewIndex(iIndex);142
}143
if (-1!=m_iActiveView)144
{145
OnViewActivated(m_iActiveView);146
}147
}148

149
void CTabView::RemoveAllView()150
{151
LPTSTR pszTitle;152
for (int iIndex=0;iIndex<GetViewCount();++iIndex)153
{154
GetView(iIndex)->DestroyWindow();155
if (GetViewTitle(iIndex,pszTitle))156
delete []pszTitle;157
}158
GetTabCtrl().DeleteAllItems();159
}160

161
int CTabView::GetViewCount() const162
{163
ASSERT(::IsWindow(CCtrlView::m_hWnd));164
return GetTabCtrl().GetItemCount();165
}166

167
CWnd* CTabView::GetView(int iIndex) const168
{169
ASSERT(::IsWindow(CCtrlView::m_hWnd));170
ASSERT(IsValidViewIndex(iIndex));171

172
TC_EXTRA_ITEM ti;173
ti.header.mask = TCIF_PARAM;174
if (!GetTabCtrl().GetItem(iIndex,ti))175
return NULL;176
return ti.view.pWnd;177
}178

179
int CTabView::GetIndex(const CWnd* pWnd) const180
{181
ASSERT(::IsWindow(CCtrlView::m_hWnd));182

183
int count = GetTabCtrl().GetItemCount();184
for (int i=0;i<count;++i)185
{186
if (GetView(i)==pWnd)187
return i;188
}189
return -1;190
}191

192
CWnd* CTabView::GetActiveView() const193
{194
ASSERT(::IsWindow(CCtrlView::m_hWnd));195
return (-1==m_iActiveView) ? NULL : GetView(m_iActiveView);196
}197

198
int CTabView::GetActiveViewIndex() const199
{200
return m_iActiveView;201
}202

203
void CTabView::SetActiveView(const CWnd* pWnd)204
{205
SetActiveViewIndex(GetIndex(pWnd));206
}207

208
void CTabView::SetActiveViewIndex(int iIndex)209
{210
ASSERT(::IsWindow(CCtrlView::m_hWnd));211
ASSERT(IsValidViewIndex(iIndex));212

213
if (iIndex==m_iActiveView)214
return;215

216
// SetRedraw(FALSE);217
if (-1!=m_iActiveView)218
{219
GetView(m_iActiveView)->ShowWindow(SW_HIDE);220
}221
GetTabCtrl().SetCurSel(iIndex);222
m_iActiveView = iIndex;223
GetView(m_iActiveView)->ShowWindow(SW_SHOWNORMAL);224

225
UpdateLayout();226
227
//SetRedraw(TRUE);228
//RedrawWindow(NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);229

230
if (GetFocus()!=this)231
{232
GetView(iIndex)->SetFocus();233
} 234
}235

236
BOOL CTabView::SetViewTitle(const CWnd* pWnd,LPCTSTR pszTitle)237
{238
return SetViewTitle(GetIndex(pWnd),pszTitle);239
}240

241
BOOL CTabView::SetViewTitle(int iIndex,LPCTSTR pszTitle)242
{243
ASSERT(::IsWindow(CCtrlView::m_hWnd));244
ASSERT(IsValidViewIndex(iIndex));245

246
TC_EXTRA_ITEM ti;247
ti.header.mask = TCIF_PARAM;248
if (!GetTabCtrl().GetItem(iIndex,ti))249
return FALSE;250
delete []ti.view.pszTitle;251

252
CString str;253
ShortenTitle(pszTitle,str);254

255
ti.header.mask = TCIF_TEXT|TCIF_PARAM;256
ti.header.pszText = (LPTSTR)(LPCTSTR)str;257
if (pszTitle)258
{259
ti.view.pszTitle = new TCHAR[_tcslen(pszTitle)+1];260
if (NULL==ti.view.pszTitle) 261
return FALSE;262
_tcscpy(ti.view.pszTitle,pszTitle);263
}264
if (!GetTabCtrl().SetItem(iIndex,ti))265
{266
if (pszTitle) delete []ti.view.pszTitle;267
return FALSE;268
}269
return TRUE;270
}271

272
BOOL CTabView::GetViewTitle(const CWnd* pWnd,LPTSTR& pszTitle) const273
{274
return GetViewTitle(GetIndex(pWnd),pszTitle);275
}276

277
BOOL CTabView::GetViewTitle(int iIndex,LPTSTR& pszTitle) const278
{279
ASSERT(IsValidViewIndex(iIndex));280

281
TC_EXTRA_ITEM ti;282
ti.header.mask = TCIF_PARAM;283
if (!GetTabCtrl().GetItem(iIndex,ti))284
return FALSE;285
pszTitle = ti.view.pszTitle;286
return TRUE;287
}288

289
CImageList* CTabView::SetImageList(CImageList* pImageList)290
{291
ASSERT(CCtrlView::m_hWnd);292
return GetTabCtrl().SetImageList(pImageList);293
}294

295
CImageList* CTabView::GetImageList() const296
{297
ASSERT(CCtrlView::m_hWnd);298
return GetTabCtrl().GetImageList();299
}300

301
BOOL CTabView::SetViewImage(const CWnd* pWnd,int iImage) 302
{303
return SetViewImage(GetIndex(pWnd),iImage);304
}305

306
BOOL CTabView::SetViewImage(int iIndex,int iImage)307
{308
ASSERT(IsValidViewIndex(iIndex));309

310
TC_EXTRA_ITEM ti;311
ti.header.mask = TCIF_IMAGE;312
ti.header.iImage = iImage;313
return GetTabCtrl().SetItem(iIndex,ti);314
}315

316
BOOL CTabView::GetViewImage(const CWnd* pWnd,int& iImage) const317
{318
return GetViewImage(GetIndex(pWnd),iImage);319
}320

321
BOOL CTabView::GetViewImage(int iIndex,int& iImage) const322
{323
ASSERT(IsValidViewIndex(iIndex));324

325
TC_EXTRA_ITEM ti;326
ti.header.mask = TCIF_IMAGE;327
if (!GetTabCtrl().GetItem(iIndex,ti))328
return FALSE;329
iImage = ti.header.iImage;330
return TRUE;331
}332

333
BOOL CTabView::SetViewData(const CWnd* pWnd,LPVOID pData)334
{335
return SetViewData(GetIndex(pWnd),pData);336
}337

338
BOOL CTabView::SetViewData(int iIndex,LPVOID pData)339
{340
ASSERT(IsValidViewIndex(iIndex));341

342
TC_EXTRA_ITEM ti;343
ti.header.mask = TCIF_PARAM;344
if (!GetTabCtrl().GetItem(iIndex,ti))345
return FALSE;346
ti.header.mask = TCIF_PARAM;347
ti.view.pData = pData;348
return GetTabCtrl().SetItem(iIndex,ti);349
}350

351
BOOL CTabView::GetViewData(const CWnd* pWnd,LPVOID& pData) const352
{353
return GetViewData(GetIndex(pWnd),pData);354
}355

356
BOOL CTabView::GetViewData(int iIndex,LPVOID& pData) const357
{358
TC_EXTRA_ITEM ti;359
ti.header.mask = TCIF_PARAM;360
if (!GetTabCtrl().GetItem(iIndex,ti))361
return FALSE;362
pData = ti.view.pData;363
return TRUE;364
}365

366
BOOL CTabView::IsInnerView(const CWnd* pWnd,BOOL& bInner) const367
{368
return IsInnerView(GetIndex(pWnd),bInner);369
}370

371
BOOL CTabView::IsInnerView(int iIndex,BOOL& bInner) const372
{373
ASSERT(IsValidViewIndex(iIndex));374

375
TC_EXTRA_ITEM ti;376
ti.header.mask = TCIF_PARAM;377
if (!GetTabCtrl().GetItem(iIndex,ti))378
return FALSE;379
bInner = ti.view.bInner;380
return TRUE;381
}



