急急急!MFC对话框tab control切换页面时出现卡顿!

时间:2022-05-03 23:49:12
事情是这样的:我用VS建了一个MFC对话框项目,在生成的主对话框中放置了一个tab control,一个Button,点击Button可以弹出一个子窗口,子窗口也有一个tab control,两个窗口的tab control都设置了四个页面。并分别在主窗口和子窗口的oninitdialog()函数中实现了初始化。但是在程序运行起来之后,在主对话框中,标签页的切换是正常的,很流畅,但是是在弹出来的子对话框中的标签页切换就会出现明显的卡顿,在VS2010下有时还可以切换,在VS2008中就直接卡死了,点切换根本就没反应。郁闷了一天了,都不知道问题出在哪里,不知道有没有人遇到过这种情况,希望有大神能帮助解决。PS:我是在新建的子对话框中重写的oninitdialog()实现的子对话框中tab control的初始化。 急急急!MFC对话框tab control切换页面时出现卡顿!在线等高手解答,十万火急呀! 急急急!MFC对话框tab control切换页面时出现卡顿!

8 个解决方案

#1


资源泄漏?死循环?消息阻塞?得看代码。

#2


引用 1 楼 Mackz 的回复:
资源泄漏?死循环?消息阻塞?得看代码。


//主对话框
BOOL CJMDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// 将“关于...”菜单项添加到系统菜单中。

// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标

ShowWindow(SW_MINIMIZE);

// TODO: 在此添加额外的初始化代码

m_tabThree.InsertItem(0, "正常加工");
m_tabThree.InsertItem(1, "采样测量");
m_tabThree.InsertItem(2, "机器调整");
m_tabThree.InsertItem(3, "I/O检测");

m_three1.Create(IDD_TABTHREE1, GetDlgItem(IDC_TABTHREE));
m_three2.Create(IDD_TABTHREE2, GetDlgItem(IDC_TABTHREE));
m_three3.Create(IDD_TABTHREE3, GetDlgItem(IDC_TABTHREE));
m_three4.Create(IDD_TABTHREE4, GetDlgItem(IDC_TABTHREE));

CRect rsTabThree;
m_tabThree.GetClientRect(&rsTabThree);

rsTabThree.top += 25;
rsTabThree.left += 2;
rsTabThree.right -= 10;
rsTabThree.bottom -= 5;

m_three1.MoveWindow(&rsTabThree);
m_three2.MoveWindow(&rsTabThree);
m_three3.MoveWindow(&rsTabThree);
m_three4.MoveWindow(&rsTabThree);

m_three1.ShowWindow(TRUE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(FALSE);

m_tabThree.SetCurSel(0);

return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CJMDlg::OnTcnSelchangeTabthree(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    
    int nCursel = m_tabThree.GetCurSel();

    switch(nCursel)
    {
    case 0:
m_three1.ShowWindow(TRUE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(FALSE);
break;
    case 1:
m_three1.ShowWindow(FALSE);
m_three2.ShowWindow(TRUE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(FALSE);
break;
    case 2:
m_three1.ShowWindow(FALSE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(TRUE);
m_three4.ShowWindow(FALSE);
break;
    case 3:
m_three1.ShowWindow(FALSE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(TRUE);
break;
    default:
break;
    }

    *pResult = 0;
}


//子窗口
BOOL CShapeChange::OnInitDialog()
{
    CDialog::OnInitDialog();

    m_TabChild.InsertItem(0, "试折操作");
    m_TabChild.InsertItem(1, "半框选择");
    m_TabChild.InsertItem(2, "图样调整");
    m_TabChild.InsertItem(3, "备份存储");

    m_tabChild1.Create(IDD_TABCHILD1, GetDlgItem(IDC_TABCHILD));
    m_tabChild2.Create(IDD_TABCHILD2, GetDlgItem(IDC_TABCHILD));
    m_tabChild3.Create(IDD_TABCHILD3, GetDlgItem(IDC_TABCHILD));
    m_tabChild4.Create(IDD_TABCHILD4, GetDlgItem(IDC_TABCHILD));

    CRect rsTabChild;

    m_TabChild.GetClientRect(&rsTabChild);

    m_tabChild1.MoveWindow(&rsTabChild);
    m_tabChild2.MoveWindow(&rsTabChild);
    m_tabChild3.MoveWindow(&rsTabChild);
    m_tabChild4.MoveWindow(&rsTabChild);

    m_tabChild1.ShowWindow(TRUE);
    m_tabChild2.ShowWindow(FALSE);
    m_tabChild3.ShowWindow(FALSE);
    m_tabChild4.ShowWindow(FALSE);

    m_TabChild.SetCurSel(0);

    m_childList.ModifyStyle(0L, LVS_SHOWSELALWAYS);
    DWORD dwStyle = m_childList.GetExtendedStyle();
    dwStyle |= LVS_EX_FULLROWSELECT;
    dwStyle |= LVS_EX_GRIDLINES;
    m_childList.SetExtendedStyle(dwStyle);

    m_childList.InsertColumn(0, _T("序号"));
    m_childList.InsertColumn(1, _T("成型"));
    m_childList.InsertColumn(2, _T("弯度"));

    CRect rsTemp;
    m_childList.GetClientRect(rsTemp);
    m_childList.SetColumnWidth(0, rsTemp.Width()/3);
    m_childList.SetColumnWidth(1, rsTemp.Width()/3);
    m_childList.SetColumnWidth(2, rsTemp.Width()/3);

    // TODO:  在此添加额外的初始化

    return TRUE;  // return TRUE unless you set the focus to a control
    // 异常: OCX 属性页应返回 FALSE
}


void CShapeChange::OnTcnSelchangeTabchild(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码

    int nChildCursel = m_TabChild.GetCurSel();

    switch(nChildCursel)
    {
    case 0:
m_tabChild1.ShowWindow(TRUE);
m_tabChild2.ShowWindow(FALSE);
m_tabChild3.ShowWindow(FALSE);
m_tabChild4.ShowWindow(FALSE);
break;
    case 1:
m_tabChild1.ShowWindow(FALSE);
m_tabChild2.ShowWindow(TRUE);
m_tabChild3.ShowWindow(FALSE);
m_tabChild4.ShowWindow(FALSE);
break;
    case 2:
m_tabChild1.ShowWindow(FALSE);
m_tabChild2.ShowWindow(FALSE);
m_tabChild3.ShowWindow(TRUE);
m_tabChild4.ShowWindow(FALSE);
break;
    case 3:
m_tabChild1.ShowWindow(FALSE);
m_tabChild2.ShowWindow(FALSE);
m_tabChild3.ShowWindow(FALSE);
m_tabChild4.ShowWindow(TRUE);
break;
    default:
break;
    }

    *pResult = 0;
}


代码呈上:
在主对话框和子对话框中,我对tab control采用了一样的实现,都是分别实现对话框的oninitdialog()函数,然后响应对应的事件,但是结果是主对话框切换正常,子对话框出现明显卡顿。 急急急!MFC对话框tab control切换页面时出现卡顿!
一直没想通是怎么回事。

#3


我看你的子对话框多了一个m_childList,不知道在Tab切换的时候是否有影响,先把这个变量注释掉看看。

另外你的情况似乎用CPropertySheet/CPropertyPage更方便。

#4


引用 3 楼 Mackz 的回复:
我看你的子对话框多了一个m_childList,不知道在Tab切换的时候是否有影响,先把这个变量注释掉看看。

另外你的情况似乎用CPropertySheet/CPropertyPage更方便。

很感谢您这么耐心地看我的帖子,m_childList是子对话框上list control控件的对应变量,我试过,在这里是没有影响的。在网上找了好久,都只是看到一些tab control控件的使用方法,我很奇怪在这之前,就没有人遇到过和我一样的问题么?还是说Tab control就只能用在主对话框上(我觉得不可能会是这样)。还是,用到子对话框上和用在主对话框上是两种情况,处理的方法不同。反正,我就是没想通怎么会这样,在VS2008和VS2010下我都试过,都会卡。

#5


主对话框、子对话框什么的肯定是没有关系的,要不你把两个对话框换个位置试试看。我觉得还是你的Tab页关联的子窗口问题。一般我要用TabCtrl的话,子窗口用BringWindowToTop就可以了,不用Show/Hide那么麻烦。

#6


您好,在您的指点下,我又作了一个小实验。这一次,我在主对话框中,只放置了一个button,用来点击显示子对话框,而在子对话框中放置了一个tab control用来实验。这一次,只有子对话框有标签控件,点击之后标签的切换没有出现卡死顿的情况。面且,在子对话框和主对话框都有Tab control的情况下,如果在只给子对话框的标签控件设置标题名称,而不让它显示标签页的内容,这样做,子对话框标签的页面切换也是正常的,无卡顿。但是一旦要其显示其中的内容,不管是显示几个,都会有卡顿。我在想,是不是因为子对话框的oninitdialog()和主对话框有冲突,或者是两个Tab control控件的响应事件有冲突造成的。

#7


引用 6 楼 qq77821542 的回复:
您好,在您的指点下,我又作了一个小实验。这一次,我在主对话框中,只放置了一个button,用来点击显示子对话框,而在子对话框中放置了一个tab control用来实验。这一次,只有子对话框有标签控件,点击之后标签的切换没有出现卡死顿的情况。面且,在子对话框和主对话框都有Tab control的情况下,如果在只给子对话框的标签控件设置标题名称,而不让它显示标签页的内容,这样……
不会,每个窗口自己的消息循环是分开的。

#8


你好,我的问题解决了。 急急急!MFC对话框tab control切换页面时出现卡顿!
在我的火眼金睛的观察下,我发现了一个不为人知的秘密。
问题在于,我对标签页在控件中的显示位置没有把握好。
第一次在VS2010下面做的时候,标签页显示的位置刚好覆盖到了控件标题大概一半的位置,所以点击切换的时候有时候能点到标题,有时候则只能点到标签页,而这两种情况的效果刚好就是有时能切换,有时不能,给我一种卡顿的错觉。
第二次在VS2008下做的时候,标签页基本覆盖了控件标题,所以,不管我怎么点击,都不能切换,而我误以为这是控件卡死了。
急急急!MFC对话框tab control切换页面时出现卡顿!这就个问题纠结了这么久,我是有多喜欢给自己找事做呀,给我一块豆腐撞了吧! 急急急!MFC对话框tab control切换页面时出现卡顿!
再次谢谢您的帮助!分都是你的,嘿嘿...

#1


资源泄漏?死循环?消息阻塞?得看代码。

#2


引用 1 楼 Mackz 的回复:
资源泄漏?死循环?消息阻塞?得看代码。


//主对话框
BOOL CJMDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// 将“关于...”菜单项添加到系统菜单中。

// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标

ShowWindow(SW_MINIMIZE);

// TODO: 在此添加额外的初始化代码

m_tabThree.InsertItem(0, "正常加工");
m_tabThree.InsertItem(1, "采样测量");
m_tabThree.InsertItem(2, "机器调整");
m_tabThree.InsertItem(3, "I/O检测");

m_three1.Create(IDD_TABTHREE1, GetDlgItem(IDC_TABTHREE));
m_three2.Create(IDD_TABTHREE2, GetDlgItem(IDC_TABTHREE));
m_three3.Create(IDD_TABTHREE3, GetDlgItem(IDC_TABTHREE));
m_three4.Create(IDD_TABTHREE4, GetDlgItem(IDC_TABTHREE));

CRect rsTabThree;
m_tabThree.GetClientRect(&rsTabThree);

rsTabThree.top += 25;
rsTabThree.left += 2;
rsTabThree.right -= 10;
rsTabThree.bottom -= 5;

m_three1.MoveWindow(&rsTabThree);
m_three2.MoveWindow(&rsTabThree);
m_three3.MoveWindow(&rsTabThree);
m_three4.MoveWindow(&rsTabThree);

m_three1.ShowWindow(TRUE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(FALSE);

m_tabThree.SetCurSel(0);

return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CJMDlg::OnTcnSelchangeTabthree(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码
    
    int nCursel = m_tabThree.GetCurSel();

    switch(nCursel)
    {
    case 0:
m_three1.ShowWindow(TRUE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(FALSE);
break;
    case 1:
m_three1.ShowWindow(FALSE);
m_three2.ShowWindow(TRUE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(FALSE);
break;
    case 2:
m_three1.ShowWindow(FALSE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(TRUE);
m_three4.ShowWindow(FALSE);
break;
    case 3:
m_three1.ShowWindow(FALSE);
m_three2.ShowWindow(FALSE);
m_three3.ShowWindow(FALSE);
m_three4.ShowWindow(TRUE);
break;
    default:
break;
    }

    *pResult = 0;
}


//子窗口
BOOL CShapeChange::OnInitDialog()
{
    CDialog::OnInitDialog();

    m_TabChild.InsertItem(0, "试折操作");
    m_TabChild.InsertItem(1, "半框选择");
    m_TabChild.InsertItem(2, "图样调整");
    m_TabChild.InsertItem(3, "备份存储");

    m_tabChild1.Create(IDD_TABCHILD1, GetDlgItem(IDC_TABCHILD));
    m_tabChild2.Create(IDD_TABCHILD2, GetDlgItem(IDC_TABCHILD));
    m_tabChild3.Create(IDD_TABCHILD3, GetDlgItem(IDC_TABCHILD));
    m_tabChild4.Create(IDD_TABCHILD4, GetDlgItem(IDC_TABCHILD));

    CRect rsTabChild;

    m_TabChild.GetClientRect(&rsTabChild);

    m_tabChild1.MoveWindow(&rsTabChild);
    m_tabChild2.MoveWindow(&rsTabChild);
    m_tabChild3.MoveWindow(&rsTabChild);
    m_tabChild4.MoveWindow(&rsTabChild);

    m_tabChild1.ShowWindow(TRUE);
    m_tabChild2.ShowWindow(FALSE);
    m_tabChild3.ShowWindow(FALSE);
    m_tabChild4.ShowWindow(FALSE);

    m_TabChild.SetCurSel(0);

    m_childList.ModifyStyle(0L, LVS_SHOWSELALWAYS);
    DWORD dwStyle = m_childList.GetExtendedStyle();
    dwStyle |= LVS_EX_FULLROWSELECT;
    dwStyle |= LVS_EX_GRIDLINES;
    m_childList.SetExtendedStyle(dwStyle);

    m_childList.InsertColumn(0, _T("序号"));
    m_childList.InsertColumn(1, _T("成型"));
    m_childList.InsertColumn(2, _T("弯度"));

    CRect rsTemp;
    m_childList.GetClientRect(rsTemp);
    m_childList.SetColumnWidth(0, rsTemp.Width()/3);
    m_childList.SetColumnWidth(1, rsTemp.Width()/3);
    m_childList.SetColumnWidth(2, rsTemp.Width()/3);

    // TODO:  在此添加额外的初始化

    return TRUE;  // return TRUE unless you set the focus to a control
    // 异常: OCX 属性页应返回 FALSE
}


void CShapeChange::OnTcnSelchangeTabchild(NMHDR *pNMHDR, LRESULT *pResult)
{
    // TODO: 在此添加控件通知处理程序代码

    int nChildCursel = m_TabChild.GetCurSel();

    switch(nChildCursel)
    {
    case 0:
m_tabChild1.ShowWindow(TRUE);
m_tabChild2.ShowWindow(FALSE);
m_tabChild3.ShowWindow(FALSE);
m_tabChild4.ShowWindow(FALSE);
break;
    case 1:
m_tabChild1.ShowWindow(FALSE);
m_tabChild2.ShowWindow(TRUE);
m_tabChild3.ShowWindow(FALSE);
m_tabChild4.ShowWindow(FALSE);
break;
    case 2:
m_tabChild1.ShowWindow(FALSE);
m_tabChild2.ShowWindow(FALSE);
m_tabChild3.ShowWindow(TRUE);
m_tabChild4.ShowWindow(FALSE);
break;
    case 3:
m_tabChild1.ShowWindow(FALSE);
m_tabChild2.ShowWindow(FALSE);
m_tabChild3.ShowWindow(FALSE);
m_tabChild4.ShowWindow(TRUE);
break;
    default:
break;
    }

    *pResult = 0;
}


代码呈上:
在主对话框和子对话框中,我对tab control采用了一样的实现,都是分别实现对话框的oninitdialog()函数,然后响应对应的事件,但是结果是主对话框切换正常,子对话框出现明显卡顿。 急急急!MFC对话框tab control切换页面时出现卡顿!
一直没想通是怎么回事。

#3


我看你的子对话框多了一个m_childList,不知道在Tab切换的时候是否有影响,先把这个变量注释掉看看。

另外你的情况似乎用CPropertySheet/CPropertyPage更方便。

#4


引用 3 楼 Mackz 的回复:
我看你的子对话框多了一个m_childList,不知道在Tab切换的时候是否有影响,先把这个变量注释掉看看。

另外你的情况似乎用CPropertySheet/CPropertyPage更方便。

很感谢您这么耐心地看我的帖子,m_childList是子对话框上list control控件的对应变量,我试过,在这里是没有影响的。在网上找了好久,都只是看到一些tab control控件的使用方法,我很奇怪在这之前,就没有人遇到过和我一样的问题么?还是说Tab control就只能用在主对话框上(我觉得不可能会是这样)。还是,用到子对话框上和用在主对话框上是两种情况,处理的方法不同。反正,我就是没想通怎么会这样,在VS2008和VS2010下我都试过,都会卡。

#5


主对话框、子对话框什么的肯定是没有关系的,要不你把两个对话框换个位置试试看。我觉得还是你的Tab页关联的子窗口问题。一般我要用TabCtrl的话,子窗口用BringWindowToTop就可以了,不用Show/Hide那么麻烦。

#6


您好,在您的指点下,我又作了一个小实验。这一次,我在主对话框中,只放置了一个button,用来点击显示子对话框,而在子对话框中放置了一个tab control用来实验。这一次,只有子对话框有标签控件,点击之后标签的切换没有出现卡死顿的情况。面且,在子对话框和主对话框都有Tab control的情况下,如果在只给子对话框的标签控件设置标题名称,而不让它显示标签页的内容,这样做,子对话框标签的页面切换也是正常的,无卡顿。但是一旦要其显示其中的内容,不管是显示几个,都会有卡顿。我在想,是不是因为子对话框的oninitdialog()和主对话框有冲突,或者是两个Tab control控件的响应事件有冲突造成的。

#7


引用 6 楼 qq77821542 的回复:
您好,在您的指点下,我又作了一个小实验。这一次,我在主对话框中,只放置了一个button,用来点击显示子对话框,而在子对话框中放置了一个tab control用来实验。这一次,只有子对话框有标签控件,点击之后标签的切换没有出现卡死顿的情况。面且,在子对话框和主对话框都有Tab control的情况下,如果在只给子对话框的标签控件设置标题名称,而不让它显示标签页的内容,这样……
不会,每个窗口自己的消息循环是分开的。

#8


你好,我的问题解决了。 急急急!MFC对话框tab control切换页面时出现卡顿!
在我的火眼金睛的观察下,我发现了一个不为人知的秘密。
问题在于,我对标签页在控件中的显示位置没有把握好。
第一次在VS2010下面做的时候,标签页显示的位置刚好覆盖到了控件标题大概一半的位置,所以点击切换的时候有时候能点到标题,有时候则只能点到标签页,而这两种情况的效果刚好就是有时能切换,有时不能,给我一种卡顿的错觉。
第二次在VS2008下做的时候,标签页基本覆盖了控件标题,所以,不管我怎么点击,都不能切换,而我误以为这是控件卡死了。
急急急!MFC对话框tab control切换页面时出现卡顿!这就个问题纠结了这么久,我是有多喜欢给自己找事做呀,给我一块豆腐撞了吧! 急急急!MFC对话框tab control切换页面时出现卡顿!
再次谢谢您的帮助!分都是你的,嘿嘿...