在对话框中加入属性页

在对话框中加入属性页
作者:黄晨量

下载本文全部源代码

当一个基于对话框的程序中有相当多的控件时,你一定会想到使用属性页来将这些控件分类放置。本文针对这种方法来讨论几种可能实现的方案。

方案一

本方案的例子请见源代码打包文件中的Property1部分

在对话框上放置一个Tab Control的控件,再在对话框上放置所需的控件(本例放置了2个按钮,试图在每个标签中显示一个)。然后利用Class Wizard来为Tab Control控件创建一个控件变量,该变量是CTabCtrl类的,再为其他控件也创建相应的控件类。 在主对话框的初始函数中CProperty1Dlg::OnInitDialog()加入如下代码:
//本例插入两个标签,实际运用中可通过循环插入所需个数的标签,运行后默认第一个标签被选中
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;
}
这样做以后就可以使界面上的控件在不同的标签中显示了,但是这个方案也有很多弊病。

所有的控件仍然在一个对话框内,在使用对话框编辑器进行编辑时,操作很不方便。
为了能分类显示控件,必须用ClassWizard为每一个控件创建一个控件变量,以便利用各控件变量的CWnd基类的ShowWindow函数来显示和隐藏。有时为了使用DDX和DDV机制来进行数据交换,还要创建一些存放值的变量,这样就使得整个对话框类变得相当庞大难以操作。
当然你也可以使用数组来存放那些控件变量或值变量,但是这样并不是最好,有时一些不相关的控件变量放入一个数组中,通过没有实际意义的数组索引号来访问控件,对程序的编写会造成麻烦。 最好能将所有控件进行分类,放入不通对话框类中,这些对话框作为子对话框出现在主对话框中。可以。现在看看方案二。

方案二

本方案的例子请见源代码打包文件中的Property2部分
这个方案中,我将使用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类继承自己的类啊!下面来看看方案三的做法。

方案三

本方案的例子请见源代码打包文件中的Property3部分

首先还是要创建那些要在属性页中的显示的子对话框类,创建步骤和方案二一样,都是从CPropertyPage继承。

这次我们将从CPropertySheet类继承自己的类(假设类名为CMySheet)。我们要在这里放上一个button控件。那么现在先在CMySheet中加入一个CButton类的成员变量m_button。

在CMySheet类中的OnInitDialog()函数里,这样写:

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;
效果如下:

使用方案三虽然能在主对话框中加入控件,但是也比较麻烦,首先所加的控件只能在属性页的右边或下边。并且用程序来产生控件比较烦琐,位置与大小不易控制。那么还有其他方法,既能在对话框中加入属性页,又能在主对话框随意添加控件?还是有的,看看方案四。

方案四

本方案的例子请见源代码打包文件中的Property4部分

这次我们不从CPropertySheet继承自己的类,还是直接使用它。各属性页的子对话框类还是需要的,创建方法和上述两个方案相同。

首先我们新建一个基于对话框的工程。在编辑已有的一个主对话框中可以自由加一些所需的控件,但是得留出一定的空间用于放置属性页。

在主对话框类里加入一个CPropertySheet类的一个成员变量(m_sheet)代表整个属性页。再加入一些各子对话框类的实例作为成员变量(m_page1、m_page2……)。

在主对话框类的OnInitDialog()函数中加入:

//加入标签,标签名由各个子对话框的标题栏决定
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);

效果如下:

这个方案可以自由在主对话框中加一些必要的控件,而且属性页中的控件也都分散在了各个子对话框类中,使用非常方便。

但是这样也有一些缺陷:主对话框不能处理属性页上标签的消息,即点击标签时无法通知主对话框。(可能笔者水平有限,理论上应该可以,但笔者尚未解决这个问题)

方案五

本方案的例子请见源代码打包文件中的Property5部分

这次我们仍然要使用Tab Control,并且从CTabCtrl控件类继承自己的类(CTabSheet)来处理。(此方法来自CodeGuru的一篇文章,本人稍做修改使其使用更简便)

首先我先介绍一下如何使用CTabSheet。

先要制作子对话框类,这次的子对话框类不要从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消息来对切换了标签时进行一些动作。

本文共使用了5种方法在对话框中加属性页,当然应该还有其他方法,当本人水平有限,如果各位读者有更好的方法,可不要忘了告诉我。

作者信箱:hcl-hcl@21cn.com




最新评论 [发表评论] [文章投稿] 查看所有评论 推荐给好友 打印

作者大哥你好:
我用的方案五,在主对话框中按照您的方法加入了3个属性页对话框,属性页显示响应消息都没有问题,还有我加入属性页的主对话框只是一个按钮的弹出对话框,但是关闭主对话框时程序会报错,无法退回到上一级对话框了,不知道什么问题,想请大哥指点,谢谢!! ( havocbs 发表于 2011-4-26 9:07:00)
 
前两个试了一下
后三个都没试出来
( sheldon 发表于 2010-8-11 13:49:00)
 
在VC208中CPropertySheet直接添加继承于CPropertyPage的类的实例会出现错误,不知道该怎么转换。 ( flyfunyz 发表于 2010-5-10 7:59:00)
 
请问方案五中“利用ClassWizard来处理WM_LBUTTONDOWN消息。”是怎么操作的?
我双击tab control 的标签 就出来OnTcnSelchangeTab事件了 没有WM_LBUTTONDOWN事件啊? ( xuwuhua 发表于 2009-7-23 17:52:00)
 
whitecream:我与taro_yu一样的问题,怎么为Tab Control创建一个CTabSheet的控件变量,只有CTabCtrl?
(发表于2009-3-28 17:10:00)

主要是有些文件没有更新造成的。

这种问题一般删除clw和ncb文件就可以解决了。再次打开vc时会重新生成,clw文件是在打开class wizard时创建,编译时创建ncb文件。 ( baiduwen3 发表于 2009-4-8 14:33:00)
 
不好意思,打错了几个字。 ( baiduwen3 发表于 2009-4-8 10:15:00)
 
我用的是方案5,一开始没有问题,后来在移植整理项目的时候,程序可以允许,但在推出时出现了内容不可written的问题,现在初步确定是因为直接引用先前生成的tabsheet类而导致的。以后移植到其他项目时,尽量重新生成tabsheet类。 ( baiduwen3 发表于 2009-4-8 10:14:00)
 
我与taro_yu一样的问题,怎么为Tab Control创建一个CTabSheet的控件变量,只有CTabCtrl? ( whitecream 发表于 2009-3-28 17:10:00)
 
太好了!正是我需要的,谢谢! ( yaruolin 发表于 2009-3-27 12:43:00)
 
请教一下,我用方法五,不能为Tab Control创建一个CTabSheet的控件变量,只有CTabCtrl,为什么?这样就不能调用AddPage()了。还有,我通过按钮响应打开属性页,这样就没有OnInitDialog()函数,我应该在哪里加入隐藏OK和Cancel按钮的语句呢? ( taro_yu 发表于 2009-3-17 22:09:00)
 
VC70新手:不错
(发表于2002-7-23 23:36:00)

smiler:还可以啦,值得一看!
(发表于2002-7-25 16:25:00)

king_koo:good!原来还有这么多方案。
(发表于2002-7-28 19:12:00)

cqy:程序有点小问题:目前属性列表被广泛应用,当方案五创建的属性页中加入属性列表时,属性列表不能正常操作,希望作者能够解决这个问题。
(发表于2002-7-30 19:47:00)

jb:很不错!
(发表于2002-8-12 22:17:00)

horin153:Very Good!请问能否在属性页中显示文字和图形?
(发表于2002-9-18 21:10:00)

loveKiller:方案5中只能加入一个对话框,两个以后就不行,不知是那里出错了?

(发表于2002-11-17 16:31:00)

yuanl:黄晨量,你好:

    我按你的“在对话框中加入属性页”中方案五,
     加入两个属性页时,成功;
     加入三个属性页,提示错误,跟踪调试时,发现出错是在
     标 *************的地方
     请教为什么?



在主对话框的OnInitDialog()加入:
m_sheet.AddPage("tab1", &m_page1, IDD_DIALOG1);
m_sheet.AddPage("tab2", &m_page2, IDD_DIALOG2);
m_sheet.AddPage("tab3", &m_page3, IDD_DIALOG3);
m_sheet.Show();


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();

}

(发表于2003-7-1 14:56:00)

lckboy:很好
(发表于2003-11-30 4:27:00)

hummingbird:不错,方法五也很成功,但是有一个小问题在方法五中,如果是在主对话框中,那么可以,但如果是由主对话框创建出来的子对话框(不论用是模态还是非模态),属性页就显示不出来,我百思不得其解
(发表于2004-2-27 15:00:00)

ikohl:蛮好的,感谢作者
(发表于2004-9-1 15:35:00)

Dinah:不错不错
(发表于2004-9-9 14:48:00)

babam:写得挺好的
方案4里面
主窗口里面还是能够得到属性页里面的事件的.
直接取父窗口的父窗口不就行了.

(发表于2004-12-14 17:25:00)

peter_wu:我用第五种方法很有问题,当我在对话的menu里使用它的时候,第一次可以正常显示,但在退出来后,第二次再调用它的时候,当执行到m_sheet.Show()的时候,整个程序就出错了,提示你是否按"中断","重试","忽略",然后整个程序就退出了.

是不是哪里没清除掉一些东西,程序没有完全退出呢?
(发表于2005-1-6 16:15:00)

冰河时代2:我写了一个属性页中加入LISTCTRL的代码,用的是:
主对话框类从CPropertySheet派生;然后加入两个对话框类cDlg1和cDlg2作为成员。
在:
BOOL cDlg1::OnInitDialog()
{

CDialog::OnInitDialog();
//clc.InsertColumn(0,"Col 1",LVCFMT_LEFT,300,0);//出错!
return TRUE;
}

请问这是为什么啊?
(发表于2005-1-27 12:13:00)

hexiyajin:很好,很好,已经加入收藏夹!
(发表于2005-1-31 14:22:00)

hunter0075846:请问怎么样给OK,CANCEL,APPLAY三个按钮添加代码
(发表于2005-3-31 9:48:00)

daemon2005:请问一下
我把属性页置于顶端,里面的控件正确显示
置于底端,却都显示不了,不知那里需要修改?
(发表于2005-3-31 17:25:00)

weiliu112:第五种方法有问题,你在Cpage1下定义一个CMainDlg *p_dlg的全局对象,就是会报错。我改了很久也不知道错在那


(发表于2005-7-29 15:21:00)

黄真康:这篇文章写得很好,我很喜欢这样的文章。
但我不认为方案五是一个好方法。我认为方案四是一个好方法,毕竟我们自己管理page总没有CPropertySheet管理得好,自己管理page如果考
虑不周的话会有这样或那样意想不到的问题。
那怎样才能解决方案四中笔者提到的问题呢?
有两个办法:
 1、简单方法:重载PreTranslateMessage,拦截WM_LBUTTONDOWN 

BOOL CTaskSheet::PreTranslateMessage(MSG* pMsg)
{
if(pMsg!=NULL && pMsg->message==WM_LBUTTONDOWN )
{
CWnd *pWnd=(CWnd *)CPropertySheet::GetTabControl();
if(pWnd!=NULL && pWnd->GetSafeHwnd()==pMsg->hwnd)
{
::SendMessage(pMsg->hwnd,pMsg->message,pMsg->wParam,pMsg->lParam);

if(GetActiveIndex()==0)
{
//...;
}else{
//...;
}
return TRUE;
}
}

return CPropertySheet::PreTranslateMessage(pMsg);
}

2、复杂方法:钩CPropertySheet中控件CTabCtrl 的WindowProc函数,从而达到获得CTabCtrl消息的目的
 大概步骤如下:

1)钩WindowProc函数
SetWindowLong(CPropertySheet::GetTabControl()->GetSafeHwnd(), GWL_WNDPROC, (LONG)MyTabCtrlWindowProc);
        2)定义自己的WindowProc函数

MyTabCtrlWindowProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{}

(发表于2005-8-5 23:22:00)

xiangshifu:他的这个类有bug, 修改如下:

BOOL CTabSheet::AddPage(LPCTSTR title, CDialog *pDialog,UINT ID)
{
if( MAXPAGE == m_nNumOfPages )
return FALSE;

m_IDD[m_nNumOfPages] = ID;
m_Title[m_nNumOfPages] = title;

m_pPages[m_nNumOfPages] = new CDialog();
m_pPages[m_nNumOfPages]->Create( m_IDD[m_nNumOfPages], this );
InsertItem( m_nNumOfPages, m_Title[m_nNumOfPages] );


m_nNumOfPages++;

return TRUE;
}


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();

}
(发表于2005-9-7 0:32:00)

xiangshifu:呵呵, 刚才发的有一点问题, 再次修改的代码:

BOOL CTabSheet::AddPage(LPCTSTR title, CDialog *pDialog,UINT ID)
{
if( MAXPAGE == m_nNumOfPages )
return FALSE;

m_IDD[m_nNumOfPages] = ID;
m_Title[m_nNumOfPages] = title;

pDialog->DestroyWindow();
pDialog->Create( m_IDD[m_nNumOfPages], this );

m_pPages[m_nNumOfPages] = pDialog;


InsertItem( m_nNumOfPages, m_Title[m_nNumOfPages] );


m_nNumOfPages++;

return TRUE;
}
(发表于2005-9-7 0:51:00)

ahxh2000:谢谢作者的好文章呀,给我很大的帮助!
(发表于2006-6-14 15:24:00)

bsnail:采用方案五 
在属性页设置 listctrl 如何能让listctrl 支持拖拽 接收到 WM_DROPFILES 消息
谢谢!
(发表于2006-10-12 15:20:00)

lanhai:第四中方法 我的解决方法是在 每个子dialog里响应onshow消息,如果是显示那就是这个子窗口被显示了,就可以通过n中方法告诉主对话框了
(发表于2006-10-12 17:40:00)

bsnail:采用方案四,对第二个子窗口的列表控件无法进行处理。
当我在主对话框中的OnInitDialog() 对 第二个列表控件进行 m_page2.m_List2.InsertColumn(0, _T("文件路径"), LVCFMT_LEFT, nCol1Width);
处理的时候报错:
Debug Assertion Failed!
……
如何解决啊,谢谢!
(发表于2006-10-13 10:16:00)

bsnail:方案4:可以接收消息,可是无法初始化第二个窗口
m_sheet.AddPage(&m_page1);
m_sheet.AddPage(&m_page2);
m_sheet.Create(this, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT);
m_page2 加不进去,它的窗口句柄 hWnd 为空。

方案五:可以初始化,但是无法接收消息。郁闷!!
哪位大哥大姐帮帮忙,解决一下啊
(发表于2006-10-13 11:36:00)

kingbluesea:那位大哥大姐帮个忙!我是刚开始学习VC!我的属性页一闪而过!(非模态)什么原因!十分感谢!
(发表于2006-11-16 19:13:00)

pixelor:我想问一下 怎么才能使方案四支持上下文的帮助呢?
(发表于2007-1-12 9:50:00)

shellhy:这样的不爽,个人还是喜欢用按钮响应自定义消息,把多个对话框放到Static或者Group控件上面这样构成那样的效果,
(发表于2007-2-3 16:18:00)

Winter_dg:请教楼主一个问题. 
我在工程里运用了最后一种重载TabCtrl的方法,可是出现了一个问题. 
在第一个属性页里(CDialog)包含一个listCtrl控件. 
list数据大于可视范围后没有出现滚动条. 
我在猜想应该是list的父容器出现了问题.就是说最后一种重载TabCtrl的方法出现了问题. 
现在很是困扰我,使我已经想重建工程,丢弃这种方法. 
大家有好的办法,可以找我探讨. 
QQ: 5752108 
eMail: danggang_82@163.com
(发表于2007-5-21 11:14:00)

tuxw:试了下第方案五,效果不错,比用 CPropertyPage 简便多了
但该方案中的代码有些小 BUG,就是在 SetRect() 方法中设置子对话框的位置时没有 TabControl 控件的属性,当标签位置不同时,子对话框显示位置会出错。
解决方法,通过 GetStyle() 获取 TabControl 的风格设置,判断 TCS_VERTICAL、TCS_BOTTOM、TCS_RIGHT 是否置位来分别计算子对话框的位置。
(发表于2007-6-3 1:17:00)

isabc:采用方案四,无法调整属性页大小,导致加载的属性页被缩小的,能有解决的办法吗?高手们,可以加我QQ:77359140,E-Mail:isc_117@163.com

(发表于2007-7-3 14:52:00)

ikohl:very good articles, thanks for share
(发表于2007-9-6 11:05:00)

gaixq:谢谢!!!!!!!!!!!!
(发表于2008-3-12 17:05:00)

luoguizhou:由浅入深
层层推进
非常感谢
(发表于2008-5-25 10:00:00)

taro_yu:请教一下,我用方法五,不能为Tab Control创建一个CTabSheet的控件变量,只有CTabCtrl,为什么?这样就不能调用AddPage()了。还有,我通过按钮响应打开属性页,这样就没有OnInitDialog()函数,我应该在哪里加入隐藏OK和Cancel按钮的语句呢?
(发表于2009-3-17 22:09:00)

yaruolin:太好了!正是我需要的,谢谢!
(发表于2009-3-27 12:43:00)

whitecream:我与taro_yu一样的问题,怎么为Tab Control创建一个CTabSheet的控件变量,只有CTabCtrl?
(发表于2009-3-28 17:10:00)

baiduwen3:我用的是方案5,一开始没有问题,后来在移植整理项目的时候,程序可以允许,但在推出时出现了内容不可written的问题,现在初步确定是因为直接引用先前生成的tabsheet类而导致的。以后移植到其他项目时,尽量重新生成tabsheet类。
(发表于2009-4-8 10:14:00)

baiduwen3:不好意思,打错了几个字。
(发表于2009-4-8 10:15:00)

baiduwen3:whitecream:我与taro_yu一样的问题,怎么为Tab Control创建一个CTabSheet的控件变量,只有CTabCtrl?
(发表于2009-3-28 17:10:00)

主要是有些文件没有更新造成的。

这种问题一般删除clw和ncb文件就可以解决了。再次打开vc时会重新生成,clw文件是在打开class wizard时创建,编译时创建ncb文件。
(发表于2009-4-8 14:33:00)

xuwuhua:请问方案五中“利用ClassWizard来处理WM_LBUTTONDOWN消息。”是怎么操作的?
我双击tab control 的标签 就出来OnTcnSelchangeTab事件了 没有WM_LBUTTONDOWN事件啊?
(发表于2009-7-23 17:52:00)

flyfunyz:在VC208中CPropertySheet直接添加继承于CPropertyPage的类的实例会出现错误,不知道该怎么转换。
(发表于2010-5-10 7:59:00)

sheldon:前两个试了一下
后三个都没试出来

(发表于2010-8-11 13:49:00)

havocbs:作者大哥你好:
我用的方案五,在主对话框中按照您的方法加入了3个属性页对话框,属性页显示响应消息都没有问题,还有我加入属性页的主对话框只是一个按钮的弹出对话框,但是关闭主对话框时程序会报错,无法退回到上一级对话框了,不知道什么问题,想请大哥指点,谢谢!!
(发表于2011-4-26 9:07:00)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值