如何实现标签页式的切换窗口?急! 我想做一个在窗口有两个象标签式的按钮,然后有两个窗口可以通过他控制,并且两个窗口中显示的内容是动态的! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 就是TabView嘛,CodeProject和CodeGuru里面肯定有你适合使用的类的。==========================================================百尺竿头,卧薪尝胆 CPropertySheet加CPropertyPage也可實現Tab的功能.如我們建立DataLink的對話框就是屬於這种.不知你要的是哪种實現. 用TabView比较简单,每个标签页面中都有各自的初始化代码,可以实现动态显示。 给你我改的一个类,你自己用用: #pragma once //如果VC版本不支持此命令,改成if !defined...define...endif形式// TabSheet.h : header file// /////////////////////////////////////////////////////////////////////////////// CTabSheet window#define MAXPAGE 16 //最大显示16Tab页 class CTabSheet : public CTabCtrl{// Constructionpublic: CTabSheet(); // Attributespublic: // Operationspublic: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CTabSheet) //}}AFX_VIRTUAL // Implementationpublic: int GetCurSel(); int SetCurSel(int nItem); void Show(); void SetRect(); BOOL AddPage(LPCTSTR title, CDialog *pDialog, UINT ID); virtual ~CTabSheet(); // Generated message map functionsprotected: LPCTSTR m_Title[MAXPAGE]; UINT m_IDD[MAXPAGE]; CDialog* m_pPages[MAXPAGE]; int m_nNumOfPages; int m_nCurrentPage; //{{AFX_MSG(CTabSheet) afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //}}AFX_MSG DECLARE_MESSAGE_MAP()}; //Tabsheet.cpp文件#include "stdafx.h"#include "Property5.h" // !!!这边改成你所用的工程文档名#include "TabSheet.h" #ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif /////////////////////////////////////////////////////////////////////////////// CTabSheet CTabSheet::CTabSheet(){ m_nNumOfPages = 0; m_nCurrentPage = 0;} CTabSheet::~CTabSheet(){} BEGIN_MESSAGE_MAP(CTabSheet, CTabCtrl) //{{AFX_MSG_MAP(CTabSheet) ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAPEND_MESSAGE_MAP() /////////////////////////////////////////////////////////////////////////////// CTabSheet message handlers BOOL CTabSheet::AddPage(LPCTSTR title, CDialog *pDialog,UINT ID){ if( MAXPAGE == m_nNumOfPages ) return FALSE; m_nNumOfPages++; m_pPages[m_nNumOfPages-1] = pDialog; m_IDD[m_nNumOfPages-1] = ID; m_Title[m_nNumOfPages-1] = title; return TRUE;} void CTabSheet::SetRect(){ CRect tabRect, itemRect; int nX, nY, nXc, nYc; GetClientRect(&tabRect); GetItemRect(0, &itemRect); 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); } void CTabSheet::Show(){ 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(); } 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);// m_pPages[m_nCurrentPage]->SetFocus(); }} int CTabSheet::SetCurSel(int nItem){ if( nItem < 0 || nItem >= m_nNumOfPages) return -1; int ret = m_nCurrentPage; if(m_nCurrentPage != nItem ) { m_pPages[m_nCurrentPage]->ShowWindow(SW_HIDE); m_nCurrentPage = nItem; m_pPages[m_nCurrentPage]->ShowWindow(SW_SHOW);// m_pPages[m_nCurrentPage]->SetFocus(); CTabCtrl::SetCurSel(nItem); } return ret;} int CTabSheet::GetCurSel(){ return CTabCtrl::GetCurSel();} 先要制作子对话框类,这次的子对话框类不要从CPropertyPage继承,而是直接从CDialog继承。并且各个子对话框资源的属性应设置为:Style为Child, Border为None。 在主对话框资源中,加入一个Tab Control,并且适当调整位置和大小。利用ClassWizard来为这个Tab Control创建一个CTabSheet的控件变量。 在主对话框的OnInitDialog()加入: 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消息来对切换了标签时进行一些动作。 看这个:http://www.vckbase.com/document/viewdoc.asp?id=398 //m_configTab是一个TabCtrl m_configTab.InsertItem(0,"System",0); m_configTab.InsertItem(1,"Color",1); m_configTab.InsertItem(2,"Others",2);// IMPORTANT: Tab pages should be created,IDD_SYSCONFIG is Dialog//m_dlgSysConfig,m_dlgColorConfig,m_dlgOtherConfig 是三个对话框窗口类,注意窗口应为Child类型。 m_dlgSysConfig.Create(IDD_SYSCONFIG, &m_configTab); m_dlgColorConfig.Create(IDD_COLORCONFIG, &m_configTab); m_dlgOtherConfig.Create(IDD_OTHERCONFIG, &m_configTab); m_dlgSysConfig.ShowWindow(SW_SHOW); m_dlgColorConfig.ShowWindow(SW_HIDE); m_dlgOtherConfig.ShowWindow(SW_HIDE); m_configTab.GetClientRect(&tabRect); m_configTab.GetItemRect(0, &itemRect); nX=itemRect.left; nY=itemRect.bottom+1; nXc=tabRect.right; nYc=tabRect.bottom-nY-1; CRect rc(nX,nY,nXc,nYc); m_dlgSysConfig.MoveWindow(rc);m_dlgColorConfig.MoveWindow(rc);m_dlgOtherConfig.MoveWindow(rc);然后将三个对话框移动到tab内的位置 CClassView 窗口消息响应问题 【请教】FOR循环创建多线程,创建完一条新线程就报错 关于ListControl控件的使用问题? 请教关于列表控件! vc++如何入门? 怎么进入csdn首页的广告换了? ::::如何在SDK中加载ToolBar和StatusBar? 怎样条件编译 资源文件(.rc) 关于edit组件的两个问题。(在线等待,马上给分) 线程函数!! 请问.ISO为扩展名的文件如展开! 怎样在MDI的一个视中显示两个不同的位图?急!高分求救 简单问题请教!
百尺竿头,卧薪尝胆
如我們建立DataLink的對話框就是屬於這种.不知你要的是哪种實現.
#pragma once //如果VC版本不支持此命令,改成if !defined...define...endif形式// TabSheet.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CTabSheet window
#define MAXPAGE 16 //最大显示16Tab页
class CTabSheet : public CTabCtrl
{
// Construction
public:
CTabSheet();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTabSheet)
//}}AFX_VIRTUAL
// Implementation
public:
int GetCurSel();
int SetCurSel(int nItem);
void Show();
void SetRect();
BOOL AddPage(LPCTSTR title, CDialog *pDialog, UINT ID);
virtual ~CTabSheet();
// Generated message map functions
protected:
LPCTSTR m_Title[MAXPAGE];
UINT m_IDD[MAXPAGE];
CDialog* m_pPages[MAXPAGE];
int m_nNumOfPages;
int m_nCurrentPage;
//{{AFX_MSG(CTabSheet)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#include "stdafx.h"
#include "Property5.h" // !!!这边改成你所用的工程文档名
#include "TabSheet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTabSheet
CTabSheet::CTabSheet()
{
m_nNumOfPages = 0;
m_nCurrentPage = 0;
}
CTabSheet::~CTabSheet()
{
}
BEGIN_MESSAGE_MAP(CTabSheet, CTabCtrl)
//{{AFX_MSG_MAP(CTabSheet)
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTabSheet message handlers
BOOL CTabSheet::AddPage(LPCTSTR title, CDialog *pDialog,UINT ID)
{
if( MAXPAGE == m_nNumOfPages )
return FALSE;
m_nNumOfPages++;
m_pPages[m_nNumOfPages-1] = pDialog;
m_IDD[m_nNumOfPages-1] = ID;
m_Title[m_nNumOfPages-1] = title;
return TRUE;
}
void CTabSheet::SetRect()
{
CRect tabRect, itemRect;
int nX, nY, nXc, nYc;
GetClientRect(&tabRect);
GetItemRect(0, &itemRect);
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);
}
void CTabSheet::Show()
{
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();
}
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);
// m_pPages[m_nCurrentPage]->SetFocus();
}
}
int CTabSheet::SetCurSel(int nItem)
{
if( nItem < 0 || nItem >= m_nNumOfPages)
return -1;
int ret = m_nCurrentPage;
if(m_nCurrentPage != nItem )
{
m_pPages[m_nCurrentPage]->ShowWindow(SW_HIDE);
m_nCurrentPage = nItem;
m_pPages[m_nCurrentPage]->ShowWindow(SW_SHOW);
// m_pPages[m_nCurrentPage]->SetFocus();
CTabCtrl::SetCurSel(nItem);
}
return ret;
}
int CTabSheet::GetCurSel()
{
return CTabCtrl::GetCurSel();
}
在主对话框资源中,加入一个Tab Control,并且适当调整位置和大小。利用ClassWizard来为这个Tab Control创建一个CTabSheet的控件变量。
在主对话框的OnInitDialog()加入:
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消息来对切换了标签时进行一些动作。
http://www.vckbase.com/document/viewdoc.asp?id=398
m_configTab.InsertItem(0,"System",0);
m_configTab.InsertItem(1,"Color",1);
m_configTab.InsertItem(2,"Others",2);// IMPORTANT: Tab pages should be created,IDD_SYSCONFIG is Dialog
//m_dlgSysConfig,m_dlgColorConfig,m_dlgOtherConfig 是三个对话框窗口类,注意窗口应为Child类型。
m_dlgSysConfig.Create(IDD_SYSCONFIG, &m_configTab); m_dlgColorConfig.Create(IDD_COLORCONFIG, &m_configTab);
m_dlgOtherConfig.Create(IDD_OTHERCONFIG, &m_configTab);
m_dlgSysConfig.ShowWindow(SW_SHOW);
m_dlgColorConfig.ShowWindow(SW_HIDE);
m_dlgOtherConfig.ShowWindow(SW_HIDE);
m_configTab.GetItemRect(0, &itemRect); nX=itemRect.left;
nY=itemRect.bottom+1;
nXc=tabRect.right;
nYc=tabRect.bottom-nY-1;
CRect rc(nX,nY,nXc,nYc);
m_dlgSysConfig.MoveWindow(rc);
m_dlgColorConfig.MoveWindow(rc);
m_dlgOtherConfig.MoveWindow(rc);然后将三个对话框移动到tab内的位置