摘 要:本文介绍VC++实现Tab View的多种方法,简要地分析了各种方法的实现细节和过程。
关键词:标签 文档 视图
一、引言
标签控件(Tab Control)是VC++编程中经常使用的控件之一,它允许在单个对话框或窗口中设置多个页面,每个页面代表一组控件。当某个页面的标签被选中时,该页面内的控件就会被显示出来。标签控件使得在有限的窗口空间内可以显示更多的信息,而且分类清晰。同时,VC++提供了以文档/视图(Document/View)结构方式开发应用程序的简单方法,在文档中保存数据,在视图中显示数据。无论是在SDI还是MDI的程序中,每个文档可以对应一个或多个是视图,但常常在显示数据时,需要将同一组数据用不同的视图显示,如列表视图、树型视图等,或者用一个视图显示一部分数据,用另一个视图显示另一部分数据,并且希望能在同一个显示区显示,在需要时进行切换。将标签控制运用到多视图的切换中,就形成了Tab View。
通过上面的分析,我们不难发现,实现一个Tab View主要要完成以下两方面的工作:
· 实现一个标签窗口。它要具有绘制窗口、响应用户选择、判断处理用户选择等功能。本文对Tab View 实现方法的分类就是根据标签窗口不同划分的。
· 多个视图之间的切换。根据标签窗口判断用户选择的结果,从多个视图中选择一个,在显示区中显示。
本文分析和总结了三种Tab View的实现方法:
1)利用CTabCtrl控件实现Tab View.
2)利用CSheetCtrl标签选择窗口实现Tab View.
3)利用静态分割窗口实现Tab View.
二、CTabCtrl控件实现Tab View
CTabCtrl是MFC类库中定义的标准控件类,通过对消息TCN-SELCHANGE的处理以及运用函数GetCurSel()、SetCurSel()等,可以很好地完成响应、判断和设置标签控制的工作,因此利用CTabCtrl控件实现Tab View是较容易的方法,如图1所示。
图1 CTabCtrl实现的Tab View
1.实现的主要类
//要切换显示的视窗口类
class CMyView1 : public CListView
class CMyView2 : public CView
//派生的标签控件类
class CViewTabCtrl : public CTabCtrl
//定义了Tab view的主窗口
class CTabCtrlView : public CWnd
{
protected:
CViewTabCtrl m_TabCtl;
…
}
class CMainFrame : public CFrameWnd
{
CTabCtrlView m_TabView;
…
}
2.窗口之间的父子关系以及位置关系
图2 中给出了窗口之间的父子关系。下述代码确定各窗口之间的位置关系。
void CTabCtrlView::RecalcLayout()
{ …
CRect rect;
// CTabCtrlView窗口的客户区大小
GetClientRect(&rect);
m_TabCtl.RecalcLayout(rect, pWnd);
…
}
void CViewTabCtrl::RecalcLayout(CRect & rect, CWnd * wnd)
{
//标签控件占据CTabCtrlView窗口的客户区
SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, SWP_NOZORDER);
//调整要显示的视窗口位置,使其占据标签控件的显示区
AdjustRect(FALSE, &rect);
wnd->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left,
rect.bottom - rect.top, SWP_NOZORDER);
}
3.多个视之间切换的实现
对于图1 所示的一个SDI的程序,视的切换主要完成下面的工作:
// 步骤1:设置当前活动的子窗口的ID
CView* pOldActiveView = GetActiveView();
::SetWindowLong(pOldActiveView->m_hWnd, GWL_ID, m_nCurrentExample);
// 步骤2:生成一个新的与所选择的视窗口对应的运行时类
CRuntimeClass* pNewViewClass;
switch (nViewID)// nViewID各个视图的标识
{
case ID_MYVIEW1:
pNewViewClass = RUNTIME_CLASS(CMyView1);
break;
case ID_MYVIEW2:
pNewViewClass = RUNTIME_CLASS(CMyView2);
break;
default:
ASSERT(0);
return;
}
// 步骤3:准备新视图类的相关上下文,创建新的视
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:关闭旧的视图
pOldActiveView->DestroyWindow();
}
在视图切换过程中,都需要重新生成新视图,关闭旧的视图。但在某些情况下,希望多个视图窗口能够同时存在,在某时刻只显示一个,而隐藏其它的窗口。可以通过定义下面的数据结构和变量,将每次加入的新视图的窗口信息保存。
typedef struct
{
CWnd *pWnd; //窗口指针
char szLabel[32]; //标签窗口对应该视图的字符串
}TCB_ITEM;
//将每次如入的视图信息保存到列表中
CList <TCB_ITEM *,TCB_ITEM *> m_Views;
在切换时,通过函数SetWindowPos()中设置参数SWP_SHOWWINDOW或SWP_HIDEWINDOW来显示选中的新视图,或隐藏旧视图。采用这种方法,使对视图操作更加灵活,可以很方便在Tab View中添加和删除不同视图。
三、CSheetCtrl标签选择窗口实现Tab View
图3 CSheetCtrl实现的高级标签窗口
CSheetCtrl不是MFC类库中的类,它实现了图3中所示的高级标签窗口,用它来实现Tab View的方法和上一个方法基本相同。在程序员大本营网站的VC编程源代码集的[其它控制]分类中,” A Tab-like Sheet Ctrl”程序含有该类源代码,但在使用时要将窗口的切换改为视图切换。
1.标签窗口的创建
CSheetCtrl实现的Attach( )函数,是它与外部的接口。在CTabSheetCtrl 中定义CSheetsWnd m_Sheet ,初始化过程中,通过调用m_Sheet.Attach(this)将CSheetCtrl创建为CTabSheetCtrl窗口的子窗口。
BOOL CSheetsWnd::Attach(CWnd * pWndParent, COLORREF rgbBackground)
{
//确定了标签窗口的大小和位置
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实现了类似于CTabCtrl的功能,如绘制标签窗口、判断用户的选择等。它本身并没有保存任何有关视图的信息,在视图切换时,它通过其父窗口来查找用户所选的视图窗口。
//得到父窗口的第一个的视图子窗口指针函数
CWnd* CSheetsWnd::GetFirstView()
{
m_pViewFind = GetParent()->GetWindow(GW_CHILD);
// m_hWnd存放的是CSheetCtrl标签窗口
//排除CSheetCtrl标签窗口
while (m_pViewFind && m_pViewFind->m_hWnd == m_hWnd)
m_pViewFind = m_pViewFind->GetWindow(GW_HWNDNEXT);
return m_pViewFind;
}
//得到下一个视图窗口指针函数
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)指针后,根据每个子窗口的标题所占空间位置,来确定所选择的视图窗口。
//获得第一个视图窗口指针
CWnd* pChild = GetFirstView();
while (pChild)
{
CRect rect(cx,0,0,0);
//rect返回绘制该窗口的标题所需的矩形大小
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鼠标位置的横坐标
break;//找到所选视图
//获得下一个视图窗口的指针
pChild = GetNextView();
int next = rect.Width() + 6 + LRB;
cx += next;
}
四、静态分割窗口实现Tab View
用静态分割窗口CSplitterWnd实现Tab View,其主要的设计思想是通过分割窗口,使用splitter窗口的Pane(0,0)作为切换视的显示区,Pane(0,1)显示类似图3的高级标签窗口CWndTab。CSplitterWnd窗口完成了上面两种方法中CTabCtrlView和CTabSheetView的工作,作为视的窗口和标签窗口的容器。此方法的源代码,在程序员大本营网站也有。
五、结束语
笔者通过分析了多个相关程序的源代码,并且在实际编程过程中,根据需要实现了自己的Tab View。在此简要地总结了三种实现Tab View 的方法,希望对读者的编程能有所帮助。
|
相关推荐
《HAHA数据库查询软件:基于ODBC的SAP HANA系统高效查询实践》 在信息技术领域,数据管理是至关重要的环节,而高效的数据查询则是数据管理的核心任务之一。"HAHA数据库查询软件"是一款专为SAP系统设计的基于ODBC...
本软件适合各种需要换IE...本软件由Haha111.com网自主研发的系列免费软件之一,为绿色安全软件,下载解压即可使用,更重要的是使用它不需要你付任何费用,并且有问题会及时升级,请放心使用,也欢迎推荐给你的朋友。
5. **使用HAHA分析**:将hprof文件导入HAHA,通过其可视化界面查看对象关系,定位问题根源。 6. **修复问题**:根据LeakCanary的报告和HAHA的分析结果,修改代码,消除内存泄漏。 7. **重复检测**:修复后再次运行...
根据提供的文件信息,本文将对《haha手册》中关于ActiveMQ的相关知识点进行详细解析,内容涵盖ActiveMQ的基础介绍、组件、连接器、通配符、客户端与代理配置、网络结构等多个方面。 ### 1. ActiveMQ简介 #### 1.1 ...
HAHA CHAT Java仿QQ聊天程序源代码,使用了比较多的图片资源 ,因此程序比较大,初步完成的效果,文件夹结构还有些乱。这个聊天程序有着QQ一样的隐藏窗体,程序有服务端和QQ登录端,同时还有一些设置程序,虽然窗口...
基于java的开发源码-HAHA CHAT Java仿QQ聊天程序源代码.zip 基于java的开发源码-HAHA CHAT Java仿QQ聊天程序源代码.zip 基于java的开发源码-HAHA CHAT Java仿QQ聊天程序源代码.zip 基于java的开发源码-HAHA CHAT ...
标题中的“spring demo document”表明这是一个关于Spring框架的示例文档,而“haha”可能是创建者添加的个性化标签或无特定含义。由于没有提供具体的压缩包内容,我将基于Spring框架的一般知识来展开讨论。 Spring...
标题中的“Miracle Falcon Driver ALL Windows Driver_HAHA_mfastboot_steamr78”指出这是一个关于Miracle Falcon驱动程序的集合,适用于所有Windows操作系统。关键词“mfastboot”表明这个驱动程序可能与设备的快速...
[图片动画]怀旧动画全站_haha.zip源码ASP.NET网站源码打包下载[图片动画]怀旧动画全站_haha.zip源码ASP.NET网站源码打包下载[图片动画]怀旧动画全站_haha.zip源码ASP.NET网站源码打包下载[图片动画]怀旧动画全站_...
【Haha .NET Web服务器】是一款基于.NET框架的轻量级Web服务器软件,它具有绿色小巧的特点,无需安装即可直接使用。用户可以通过鼠标右键菜单快速启动,方便快捷。这款Web服务器是从Visual Studio 2010开发环境中的...
### SAP HANA In-Memory Data Management:企业应用的转折点 #### 核心知识点解析 在探讨SAP HANA的最新内存技术方向之前,我们首先需要理解几个关键概念和技术背景。 **1.... 内存计算是一种数据处理方式,它将数据...
"前端葵花宝典资料haha"这个标题暗示我们这里将探讨的是一份包含丰富前端学习资源的集合,特别是与CSS相关的知识点。这份资料可能涵盖了从基础到高级的各种主题,帮助开发者掌握前端布局技巧。 1. **CSS基础知识**...
"基于Java的HAHA CHAT Java仿QQ聊天程序源代码.zip" 这个标题揭示了我们正在处理一个使用Java编程语言开发的聊天应用程序,名为HAHA CHAT。这个程序的设计灵感来自于知名的即时通讯软件QQ,旨在提供类似的功能和用户...
标题“jnjd_haha_ok”似乎是一个简略的标识或者编码,没有直接提供明确的IT知识点。描述同样简洁,只包含“jnjd_haha_ok”,这看起来像是某种内部项目或文件命名规范的一部分,但没有足够的上下文来深入解读。标签为...
该压缩包文件“基于Java的实例开发源码-HAHA CHAT Java仿QQ聊天程序源代码.zip”包含了一个使用Java编程语言开发的聊天程序实例,名为"HAHA CHAT",其设计灵感来源于著名的即时通讯软件QQ。这个项目旨在帮助学习者...
《基于Java的源码-HAHA CHAT Java仿QQ聊天程序源代码》 在这个项目中,我们探讨的是一个名为“HAHA CHAT”的Java聊天程序,它是一个模仿QQ聊天功能的实现。通过分析这个源代码,我们可以深入理解Java在开发实时通信...
【标题】"怀旧动画全站_haha.zip"是一个压缩包文件,可能包含了与怀旧动画相关的网站或应用的源代码。"haha"可能是该项目的代号或者主题标识,暗示了这个项目可能以轻松、幽默的风格为主。从描述中的“源码参考”...
【HAHA CHAT Java仿QQ聊天程序源代码.zip】是一个包含Java编程语言实现的聊天程序,旨在模仿QQ的用户界面和基本功能。这个项目对于学习Java编程、网络通信以及GUI设计的学生和开发者来说是一个很好的实践案例。以下...
【标题】"HAHA CHAT Java仿QQ聊天程序源代码.7z" 是一个压缩包文件,其中包含了一个Java编程语言实现的聊天程序,模仿了QQ的聊天功能。这个项目可能是一个教学示例或者个人实践作品,目的是为了帮助学习者理解和掌握...
该压缩包文件“基于Java的实例源码-HAHA CHAT Java仿QQ聊天程序源代码.zip”提供了一个名为“HAHA CHAT”的Java聊天程序的完整源代码,它旨在模仿QQ聊天软件的功能和用户体验。这个项目对于学习Java编程、网络通信、...