方案一
在对话框上放置一个Tab Control的控件,再在对话框上放置所需的控件(本例放置了2个按钮,试图在每个标签中显示一个)。然后利用Class Wizard来为Tab Control控件创建一个控件变量,该变量是CTabCtrl类的,再为其他控件也创建相应的控件类。 在主对话框的初始函数中CProperty1Dlg::On<wbr>InitDialog()加入如下代码:</wbr>
//本例插入两个标签,实际运用中可通过循环插入所需个数的标签,运行后默认第一个标签被选中 m_tab.InsertItem( 0, _T("Tab1") ); m_tab.InsertItem( 1, _T("Tab2") ); //将不是第一个标签的控件隐藏掉,只留下你要的控件 m_button2.ShowWindow( SW_HIDE ); 再利用ClassWizard处理Tab Control的 TCN_SELCHANGE 的消息。在消息处理函数中,利用CWnd::ShowWindow来使相应的控件显示和隐藏。 void CProperty1Dlg::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) { //GetCurSel返回当前被选中的标签的索引号(以0为基础算起) int sel = m_tab.GetCurSel(); switch(sel) { case 0: m_button1.ShowWindow( SW_SHOW ); m_button2.ShowWindow( SW_HIDE ); break; case 1: m_button2.ShowWindow( SW_SHOW ); m_button1.ShowWindow( SW_HIDE ); break; } *pResult = 0; }
方案二
本这个方案中,我将使用MFC中现成的CPropertySheet和CPropertyPage类来完成将控件分散到各个对话框类中。
首先加入两个(或数个)对话框资源。修改各对话框资源的属性,将对话框的Caption属性改为你要在标签上所显示的文字。将对话框的Style属性改为:Child, Border属性改为:Thin, 只选中Title Bar复选框,去掉其他复选框。然后你可以在这些对话框中加入要分开显示的各个控件。
为上述对话框资源分别制作一个对话框类,该对话框类是从CPropertyPage继承。这样一来各子对话框类就好了,主对话框类可以直接使用CPropertySheet类。使用如下代码即可:
CPropertySheet sheet("属性页对话框"); CPage1 page1; CPage2 page2; //加入子对话框作为一个属性页 sheet.AddPage(&page1); sheet.AddPage(&page2); //产生一个模态对话框,也可以使用Create方法来产生一个非模态对话框(具体参见MSDN) sheet.DoModal();
如何在主对话框中放置其他控件呢?如果直接使用CPropertySheet的话,是不可以的,但是别忘了我们可以从CPropertySheet类继承自己的类啊!
方案三
首先还是要创建那些要在属性页中的显示的子对话框类,创建步骤和方案二一样,都是从CPropertyPage继承。
这次我们将从CPropertySheet类继承自己的类(假设类名为CMySheet)。我们要在这里放上一个button控件。那么现在先在CMySheet中加入一个CButton类的成员变量m_button。
在CMySheet类中的On<wbr>InitDialog()函数里,这样写:</wbr>
BOOL bResult = CPropertySheet::OnInitDialog(); //取得属性页的大小 CRect rectWnd; GetWindowRect(rectWnd); //调整对话框的宽度 SetWindowPos(NULL, 0, 0,rectWnd.Width() + 100,rectWnd.Height(),SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); CRect rectButton(rectWnd.Width() + 25, 25,rectWnd.Width()+75, 75); //用程序创建一个按钮 m_button.Create("Button", BS_PUSHBUTTON, CRect(rectWnd.Width(), 25,rectWnd.Width()+75, 50) , this, 1); //显示这个按钮 m_button.ShowWindow( SW_SHOW ); CenterWindow(); return bResult;
使用方案三虽然能在主对话框中加入控件,但是也比较麻烦,首先所加的控件只能在属性页的右边或下边。并且用程序来产生控件比较烦琐,位置与大小不易控制。那么还有其他方法,既能在对话框中加入属性页,又能在主对话框随意添加控件?
方案四
不从CPropertySheet继承自己的类,还是直接使用它。各属性页的子对话框类还是需要的,创建方法和上述两个方案相同。
首先我们新建一个基于对话框的工程。在编辑已有的一个主对话框中可以自由加一些所需的控件,但是得留出一定的空间用于放置属性页。
在主对话框类里加入一个CPropertySheet类的一个成员变量(m_sheet)代表整个属性页。再加入一些各子对话框类的实例作为成员变量(m_page1、m_page2……)。
在主对话框类的On<wbr>InitDialog()函数中加入:</wbr>
//加入标签,标签名由各个子对话框的标题栏决定 m_sheet.AddPage(&m_page1); m_sheet.AddPage(&m_page2); //用Create来创建一个属性页 m_sheet.Create(this, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT); RECT rect; m_sheet.GetWindowRect(&rect); int width = rect.right - rect.left; int height = rect.bottom - rect.top; //调整属性页的大小和位置 m_sheet.SetWindowPos(NULL, 20, 50, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
这个方案可以自由在主对话框中加一些必要的控件,而且属性页中的控件也都分散在了各个子对话框类中,使用非常方便。
方案五
使用Tab Control,并且从CTabCtrl控件类继承自己的类(CTabSheet)来处理。
首先我先介绍一下如何使用CTabSheet。
先要制作子对话框类,这次的子对话框类不要从CPropertyPage继承,而是直接从CDialog继承。并且各个子对话框资源的属性应设置为:Style为Child, Border为None。
在主对话框资源中,加入一个Tab Control,并且适当调整位置和大小。利用ClassWizard来为这个Tab Control创建一个CTabSheet的控件变量。
在主对话框的On<wbr>InitDialog()加入:</wbr>
m_sheet.AddPage("tab1", &m_page1, IDD_DIALOG1);
m_sheet.AddPage("tab2", &m_page2, IDD_DIALOG2);
m_sheet.Show();
就这样就可以在对话框上制作出一个完美的属性页了。效果和上图完全一样。
下面我就来讲讲CTabSheet类的细节内容。
CTabSheet是从CTabCtrl继承来的,用于Tab Control的控件类。在类中有一个成员变量用来记录各子对话框的指针CDialog* m_pPages[MAXPAGE]; MAXPAGE是该类所能加载的标签的最大值。
类中有一个AddPage方法,用于记录子对话框的指针和所使用对话框资源的ID号。
BOOL CTabSheet::AddPage(LPCTSTR title, CDialog *pDialog,UINT ID) { if( MAXPAGE == m_nNumOfPages ) return FALSE; //保存目前总的子对话框数 m_nNumOfPages++; //记录子对话框的指针、资源ID、要在标签上显示的文字 m_pPages[m_nNumOfPages-1] = pDialog; m_IDD[m_nNumOfPages-1] = ID; m_Title[m_nNumOfPages-1] = title; return TRUE; } 在使用AddPage加入了若干子对话框后,必须调用CTabSheet的Show方法来真正生成标签和子对话框。 void CTabSheet::Show() { //利用CDialog::Create来创建子对话框,并且使用CTabCtrl::InsertItem来加上相应的标签 for( int i=0; i < m_nNumOfPages; i++ ) { m_pPages[i]->Create( m_IDD[i], this ); InsertItem( i, m_Title[i] ); } //由于对话框显示时默认的是第一个标签被选中,所以应该让第一个子对话框显示,其他子对话框隐藏 m_pPages[0]->ShowWindow(SW_SHOW); for( i=1; i < m_nNumOfPages; i++) m_pPages[i]->ShowWindow(SW_HIDE); SetRect(); }
生成好标签和子对话框后,调用CTabSheet::SetRect来计算并调整属性页的大小。
void CTabSheet::SetRect() { CRect tabRect, itemRect; int nX, nY, nXc, nYc; //得到Tab Control的大小 GetClientRect(&tabRect); GetItemRect(0, &itemRect); //计算出各子对话框的相对于Tab Control的位置和大小 nX=itemRect.left; nY=itemRect.bottom+1; nXc=tabRect.right-itemRect.left-2; nYc=tabRect.bottom-nY-2; //利用计算出的数据对各子对话框进行调整 m_pPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW); for( int nCount=1; nCount < m_nNumOfPages; nCount++ ) m_pPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW); }
在单击标签栏后,应该是相应的子对话框显示,正在显示的子对话框应该隐藏。因此利用ClassWizard来处理WM_LBUTTONDOWN消息。
void CTabSheet::OnLButtonDown(UINT nFlags, CPoint point) { CTabCtrl::OnLButtonDown(nFlags, point); //判断是否单击了其他标签 if(m_nCurrentPage != GetCurFocus()) { //将原先的子对话框隐藏 m_pPages[m_nCurrentPage]->ShowWindow(SW_HIDE); m_nCurrentPage=GetCurFocus(); //显示当前标签所对应的子对话框 m_pPages[m_nCurrentPage]->ShowWindow(SW_SHOW); } }
这样利用CTabSheet这个类就可以轻松地在对话框上放置自己的属性页了,并且控件都分散在各子对话框类中,符合对象封装的思想。而且用这个方法来制作属性页就可以利用ClassWizard来轻松地生成消息映射处理Tab Control的消息了。例如:可以处理TCN_SELCHANGE消息来对切换了标签时进行一些动作。
方案五另一写法
思路:当我们调用InsertItem()这个函数的时候,选项卡控件将会添加一个标签页,这个时候,我们将自己的对话框的窗体的指针与此标签页关联起来,当用户进行标签页的切换的时候,我们根据当前是哪个标签页,显示哪个对话框,不是与当前标签页关联的对话框,我们将其隐藏即可.这样我们便可以实现选项卡控件.
第一步:新建一个自己的类CTabSheet继承CTabCtrl.
第二步:定义有用的成员变量
CDialog* m_dlgWnd[MAXTABPAGE]; //这个是存放对话框指针的指针数组
int m_curTabNumber; //记录当前用户添加了几个标签页
int m_selTabID; //当前用户点击的标签页的ID
第三步:添加成员函数
//通过这个函数,可以将一个对话框指针与添加的标签页关联起来,insWnd是创建的非模式对话框的指针,wndID是对话框的ID,pageText是标签页的标题
void CreateTabPage(CWnd *insWnd, int wndID,CString pageText)
//添加控件的点击事件的处理,当点击后得到当前点击的标签页的ID,然后将与此标签页相关的对话框显示,其它的隐藏即可
void On<wbr>LButtonDown(UINT nFlags, CPoint point) <br> 通过添加以上的成员变量及成员函数即可实现一个简单的选项卡控件的用法<br> 下面我将这两个成员函数的代码贴出来,并详细讲解<br></wbr>
//创建并且增加一个标签页 //创建并且增加一个标签页 void CTabSheet::CreateTabPage(CWnd *insWnd, int wndID,CString pageText) { if (m_curTabNumber >= MAXTABPAGE) { MessageBox("标签页己经达到最大!","创建出错!",MB_OK); return; } //首先new一个对话框的指针,但是不要调用create函数,再将些指针当成参数传进来即可,创建己由此函数做完 if (NULL == insWnd) { MessageBox("标签页为空","创建出错",MB_OK); return; } //创建对话框,并且增加标签页 CDialog* curDlg = (CDialog*)insWnd; curDlg->Create(wndID,this); int suc = InsertItem(m_curTabNumber,pageText); if (-1 == suc) { MessageBox("插入标签页失败","失败",MB_OK); return; } curDlg->ShowWindow(SW_SHOW); //将这个对应的窗体指针存放起来 m_dlgWnd[m_curTabNumber] = curDlg; //此时选择当前页面 SetCurSel(m_curTabNumber); m_selTabID = m_curTabNumber; m_curTabNumber ++; } //点击左键事件,处理 void CTabSheet::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CTabCtrl::OnLButtonDown(nFlags, point); //得到当前用户点击的标签页的ID int curSelect = GetCurSel(); //得到当前标签页的位置以便设置对话框显示的位置 CRect curRect; GetClientRect(curRect); if (-1 == curSelect) { return; } //查找标签页,将与当前用户点击的标签页相关的对话框显示出来,其它的对话框隐藏 for (int i = 0; i < m_curTabNumber; i ++) { if (i == curSelect) { m_dlgWnd[i]->SetWindowPos(NULL,0,20,curRect.Width(),curRect.bottom,SWP_SHOWWINDOW); } else { m_dlgWnd[i]->SetWindowPos(NULL,0,20,curRect.Width(),curRect.bottom,SWP_HIDEWINDOW); } } m_selTabID = curSelect; Invalidate(); //CTabCtrl::OnLButtonDown(nFlags, point); }
以上为关键的两个函数,下面介绍调用的方法
创建非模式的对话框
CTabSheet m_tabSheet;
CMyDlg* m_dlg = new CMyDlg;
m_tabSheet.CreateTabPage(m_dlg ,IDD_DLG_ID,"第一个标签页");
这样就可以产生一个标签页了,当然还可以继续调用此函数添加标签页
相关推荐
总结来说,MFC选项卡功能通过CTabCtrl类实现,涉及创建控件、添加选项卡、处理选项卡切换事件等步骤。理解并熟练运用这些知识,可以帮助开发者构建用户友好的Windows应用程序。在实际项目中,可以根据需求进一步定制...
在MFC中实现选项卡界面,可以使用CTabCtrl类,它提供了创建和管理选项卡的功能。通过这个类,开发者可以轻松地在选项卡之间切换,为用户提供分隔不同功能或信息区域的界面。在航空订票系统中,这些选项卡可能分别...
### MFC之选项卡事件详解 #### 一、概述 在MFC框架中,`CPropertySheet` 类及其派生类常用于创建包含多个页面(选项卡)的对话框,这些页面通常用来组织相关的设置或配置选项。通过这种方式,用户可以在不同的页面...
MFC 中使用 Tab 控件实现选项卡,外加图像控件显示图像 在 MFC 中使用 Tab 控件可以实现选项卡的功能,从而提高用户体验。本文将详细介绍如何在 MFC 中使用 Tab 控件实现选项卡,并在子对话框中使用图像控件显示...
本文将深入讨论如何在VC环境下重绘`TabCtrl`以及实现关闭选项卡的功能。 首先,`360TabCtrl.cpp`和`360TabCtrl.h`可能包含了自定义的`C360TabCtrl`类,这个类是对标准`CTabCtrl`类的扩展,增加了360浏览器样式的...
在MFC(Microsoft Foundation Classes)框架中,标准的CTabCtrl控件通常显示为横向排列的选项卡,但有时开发者可能需要实现自定义布局,比如竖直排列的选项卡。本教程将详细介绍如何利用MFC自绘控件来实现竖排的TAB ...
电话簿管理、复杂计算器、综合选项卡、文本输出、某天是当年的第几天、键盘输入计算器、简单通讯录等 是大二上学期“VC++程序设计”课程的平时练习程序,都是较为基础的知识。 - 开发环境:Visual C++ 6.0 - 开发...
在VC++2005开发环境中,实现选项卡功能通常涉及到使用MFC(Microsoft Foundation Classes)库中的CTabCtrl类。CTabCtrl是Windows API中Tab控件的封装,允许开发者在应用程序中创建和管理选项卡。下面我们将深入探讨...
在本文中,我们将深入探讨MFC(Microsoft Foundation Classes)中的MDI(Multiple Document Interface)以及如何在C++环境中实现带有选项卡的MDI应用程序。标题所提到的"一个mfc mdi tab的源代码"是一个使用C++编程...
在MFC(Microsoft Foundation Class)库中,TabControl控件是一个常用的功能组件,它允许用户通过不同的选项卡来组织和切换界面内容。这个控件在Windows应用程序设计中非常常见,例如在设置面板、软件多面板视图等...
总结,这个基于MFC的银行ATM存取款机系统展示了如何运用面向对象编程技术和MFC框架来实现复杂的功能。通过这个项目,开发者不仅可以深入理解MFC的使用,还能了解到银行系统的一般设计原则和安全要求。对于学习...
总结起来,"MFC中用CEF实现c++与js交互"涉及了MFC应用程序设计、CEF的集成、多选项卡管理、以及C++与JavaScript的双向通信。这个Demon示例将帮助开发者理解如何在传统的桌面应用中嵌入现代Web技术,增强用户界面的...
"mfc tab control 标签切换 页面改变"这个主题涉及了如何在MFC应用中实现和处理TabControl的标签切换事件,并在不同页面之间动态更新显示的数据。 首先,我们需要理解MFC中的TabControl是如何工作的。TabControl...
在这个项目中,我们将利用MFC的控件,如列表框和复选框,来实现这一功能。 1. **MFC框架介绍** MFC是基于C++的,它封装了Windows API,提供了一种面向对象的方式来处理Windows编程。它包含了类库、宏库以及运行时...
在Microsoft Foundation Class (MFC)库中,"MFC当窗口多标签实现"是指使用MFC框架来创建具有多个选项卡的窗口界面。MFC是微软为Windows平台提供的一种C++类库,它封装了Windows API,使得开发Windows应用程序变得...
在MFC(Microsoft Foundation Classes)框架中,TabCtrl控件是一种常见的用户界面元素,用于创建具有多个选项卡的界面,每个选项卡代表一个独立的视图或功能区域。默认情况下,MFC TabCtrl控件的标签是纯文本的,但...
本资源“VC 窗体选项卡TAB的实现源码.rar”提供了实现这一功能的具体源代码,包括两种不同的选项卡切换效果:普通点击切换和动画过渡切换。 首先,我们要理解窗体选项卡的基本原理。在Windows API或MFC(Microsoft ...
在Windows编程中,这种控件通常被称为CTabCtrl,它是由MFC(Microsoft Foundation Classes)库提供的,用于创建具有多个选项卡的用户界面。每个选项卡都可以承载一个单独的对话框或控件集,模拟成书本中的章节,用户...
CTable和Dialog是MFC中的两个重要组件,而CTableSheet类则是将两者巧妙结合的一个实例,尤其适用于需要在多个选项卡界面中展示不同对话框布局的场景。在本文中,我们将深入探讨如何在VC++6.0环境下实现基于MFC的...