多标签视图类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
16class 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 BOOL SetViewImage(const CWnd* pWnd,int iImage);
82 BOOL SetViewImage(int iIndex,int iImage);
83 //获取视图页面的图像
84 BOOL GetViewImage(const CWnd* pWnd,int& iImage) const;
85 BOOL GetViewImage(int iIndex,int& iImage) const;
86
87 //设置视图页面的数据
88 BOOL SetViewData(int iIndex,LPVOID pData);
89 BOOL SetViewData(const CWnd* pWnd,LPVOID pData);
90 //获取视图页面的数据
91 BOOL GetViewData(int iIndex,LPVOID& pData) const;
92 BOOL GetViewData(const CWnd* pWnd,LPVOID& pData) const;
93
94&
补充:软件开发 , C语言 ,