多标签视图类CTabView的设计实现
在MFC9(在vc2008和vc2010中,已经有了CTabView的现成类)以前的版本中,有CListView,CTreeView,CEditView,CRichEditView等控件视图类,但就是没有类似的CTabView类,因工作需要,最近在做一个简单的多标签IE浏览器,开发环境是vs2005,基本框架是sdi + chtmlview + ctabview,因此自行封装实现了CTabView,并把它作为一个重要的基础类来维护使用。先来说下我这个CTabView类的特点及功能:
1)CTabView本质上就是一种窗口容器,基于CCtrlView实现,能够容纳类型为CWnd的所有窗口,并作为它的子窗口(为描述方便,在这特称为视图页面),每个标签对应一个视图页面。
2)扩展了标准的标签项数据结构TC_ITEM,即自定义了一个TC_EXTRA_ITEM扩展数据结构,该结构除包含标准的数据结构(第1个成员)外,还包括视图页面对象、内部标志、视图页面标题、视图页面关联数据4种类型数据,扩展数据大小需要在创建后插入标签前调用SetItemExtra设定。
3)支持容纳外部窗口和创建内部窗口,前者是指容纳外面已经创建好的窗口;后者是根据窗口类型信息,由CTabView自己来管理创建视图页面。
4)对于内部窗口的管理,为方便区分并有利于消息映射处理,因此窗口ID是唯一的,即在创建时分派一个新的不同的ID,销毁时回收到ID数组中。而外部窗口ID则由外部管理。
5)提供激活视图页面后的自定义处理,表现为OnViewActivated虚函数。
6)提供右键单击Tab标签后的自定义处理,表现为OnTabContextMenu虚函数。
7)提供Tab标签提示信息的自定义处理,表现为UpdateTooltipText虚函数。
8)提供CTabView视图类的自绘处理(须设定TCS_OWNERDRAWFIXED样式),表现为DrawItem虚函数。
9)Tab标签的文本默认是简写的,即当长度超过最大值时,多余部分用省略号...代替,同时也支持自定义处理,表现为ShortenTitle虚函数。
10)对上述特点7,为了能支持派生类自定义处理,由于提示文本消息的发送者是CToolTipCtrl窗口,而不是CTabView本身,所以不能像TCN_SELCHANGE,NM_RCLICK等通知消息可以使用反射宏来实现,因此使用了窗口子类化来捕获父窗口的TTN_GETDISPINFO通知消息实现的。这一行为也可以通过UpdateTooltipText来定制,当其返回值是TRUE时,表示允许消息默认被父窗口接收处理,否则,反之。
11)对上述特点8,本可以重载OnChildNotify来实现WM_DRAWITEM消息的回调,但为了简洁,如同TTN_GETDISPINFO通知消息,也是使用窗口子类化来捕获实现的。
12)对上述10和11的消息捕获处理,使用了CBasicSubClassWnd类来实现,表现为重写其SubWindowProc虚函数。
接下来看看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; // 视图页面是否内部创建
24
LPTSTR pszTitle; // 视图页面标题
25
LPVOID pData; // 视图页面数据
26
};
27![]()
28
//扩展TC_ITEM数据,第一个成员必须为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
//设置活动视图页面
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
//获取视图页面数量
71
int GetViewCount() const;
72
73
//设置视图页面的标题
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
//设置图像列表
81
CImageList* SetImageList(CImageList* pImageList);
82
//获取图像列表
83
CImageList* GetImageList() const;
84
//设置视图页面的图像
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
//设置视图页面的数据
92
BOOL SetViewData(int iIndex,LPVOID pData);
93
BOOL SetViewData(const CWnd* pWnd,LPVOID pData);
94
//获取视图页面的数据
95
BOOL GetViewData(int iIndex,LPVOID& pData) const;
96
BOOL GetViewData(const CWnd* pWnd,LPVOID& pData) const;
97![]()
98
//是否为内部创建的视图页面
99
BOOL IsInnerView(const CWnd* pWnd,BOOL& bInner) const;
100
BOOL IsInnerView(int iIndex,BOOL& bInner) const;
101![]()
102
//设置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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21

22
23
24
25
26
27
28
29
30

31
32
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
1)增加视图页面:AddIView,有2个重载形式,其中带CRuntimeClass和CCreateConext类型参数的用于创建内部窗口,成功返回对应的窗口,否则为NULL;带CWnd参数的用于容纳外部窗口,成功返回TRUE,否则返回FALSE。
2)插入视图页面:InsertView,有2个重载形式,其中带CRuntimeClass和CCreateConext类型参数的用于创建内部窗口,成功返回对应的窗口,否则为NULL;带CWnd参数的用于容纳外部窗口,成功返回TRUE,否则返回FALSE。
3)移除某个视图页面:RemoveView,有2个重载形式,其中int类型参数的用于按索引移除,CWnd类型的用于按窗口对象移除。
4)移除所有视图页面:RemoveAllView。5)获取活动视图页面:有2个方法,GetActiveView如果无活动视图页面,则返回NULL,否则返回对应的窗口;GetActiveViewIndex如果无活动视图页面,则返回-1,否则返回>=0的索引值。
5)设置活动视图页面:有2个方法:SetActiveView按窗口来设置,SetActiveViewIndex按索引来设置。
6)视图页面窗口与索引的相互转换:GetView由窗口得到其索引,操作失败返回-1,否则返回>=0的索引值。GetIndex由索引得到窗口,失败返回NULL,否则返回对应的窗口。
7)获取视图页面的数量:GetViewCount。
8)设置视图页面的标题:SetViewTitle,有2个重载形式,int类型参数的按索引设置,CWnd类型参数的按窗口设置,成功返回TRUE,否则返回FALSE。
9)获取视图页面的标题:GetViewTitle,有2个重载形式,int类型参数的按索引获取,CWnd类型参数的按窗口获取,成功返回TRUE,否则返回FALSE。
10)设置图像列表:SetImageList。
11)获取图像列表:GetImageList。
12)设置视图页面的图像:有2个重载形式,int类型参数的按索引设置,CWnd类型参数的按窗口设置,成功返回TRUE,否则返回FALSE。
13)获取视图页面的图像:有2个重载形式,int类型参数的按索引获取,CWnd类型参数的按窗口获取,成功返回TRUE,否则返回FALSE。
14)设置视图页面的数据:有2个重载形式,int类型参数的按索引设置,CWnd类型参数的按窗口设置,成功返回TRUE,否则返回FALSE。
15)获取视图页面的数据:有2个重载形式,int类型参数的按索引获取,CWnd类型参数的按窗口获取,成功返回TRUE,否则返回FALSE。
16)视图页面内部标志查询:有2个重载形式,int类型参数的按索引查询,CWnd类型参数的按窗口查询,成功返回TRUE,否则返回FALSE,当操作成功时,参数bInner为TRUE表示为CTabView内部创建的窗口,否则表示外部窗口。
最后列出主要部分的实现代码,如下所示
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
}
2

3
4
5
6
7
8

9
10
11
12
13

14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
30
31

32
33
34

35
36
37
38
39

40
41
42
43
44
45
46

47
48
49
50

51
52
53
54
55
56
57
58

59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76

77
78
79
80
81
82
83

84
85
86
87
88
89

90
91
92
93
94
95
96
97

98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123

124
125
126
127

128
129
130
131

132
133
134
135
136
137
138

139
140
141
142
143
144

145
146
147
148
149
150

151
152
153

154
155
156
157
158
159
160
161
162

163
164
165
166
167
168

169
170
171
172
173
174
175
176
177
178
179
180

181
182
183
184
185

186
187
188
189
190
191
192
193

194
195
196
197
198
199

200
201
202
203
204

205
206
207
208
209

210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237

238
239
240
241
242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265

266
267
268
269
270
271
272
273

274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290

291
292
293
294
295
296

297
298
299
300
301
302

303
304
305
306
307

308
309
310
311
312
313
314
315
316
317

318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339

340
341
342
343
344
345
346
347
348
349
350
351
352

353
354
355
356
357

358
359
360
361
362
363
364
365
366
367

368
369
370
371
372

373
374
375
376
377
378
379
380
381