多标签视图类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
36public:
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
109protected:
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
116protected:
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
124protected:
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
134public:
135 virtual void OnInitialUpdate();
136
137private:
138 CArray<UINT,UINT> m_UniqueIDs;
139 int m_iActiveView;
140 int m_cyTabHeight;
141 size_t m_nMaxTabTextLen;
142} ;
143
144 #endif
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
36public:
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
109protected:
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
116protected:
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
124protected:
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
134public:
135 virtual void OnInitialUpdate();
136
137private:
138 CArray<UINT,UINT> m_UniqueIDs;
139 int m_iActiveView;
140 int m_cyTabHeight;
141 size_t m_nMaxTabTextLen;
142} ;
143
144 #endif
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 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}