c++ - 如果我切换到另一个应用程序,我的MFC应用程序将卡住

标签 c++ visual-studio visual-studio-2008 visual-c++ mfc

开始这个问题的V 2.0版本。

我的VC++ MFC应用程序可以编译并正常运行。也就是说,直到我切换到另一个窗口。一旦我的程序失去焦点,它就会冻结。我无法切换回它,并且如果移动它前面的窗口,则我的应用程序窗口在另一个窗口覆盖的空间中显示为白色。

自从我第一次发布此问题以来,我已经能够查明程序的哪一部分导致了此行为,但是我仍然不知道哪些代码行是错误的或为什么。

我的MFC应用程序的主对话框包含一个名为m_MainTabControl的CTabCtrl。该主选项卡控件包含两个标记为“基本设计”和“高级设计”的选项卡,每个选项卡均与各自的对话框相关。这两个对话框都包含带有多个选项卡的CTabCtrl。因此,我的问题诞生了。

当我第一次创建此选项卡内部选项卡结构时,当我尝试在内部选项卡之间切换时,程序冻结了问题。不用说,我对此感到困惑,直到我注意到,如果我首先单击一个内部选项卡上的控件,那么我就可以切换选项卡了。因此,在没有完全理解问题是什么的情况下,我将焦点设置为程序启动时第一个内部选项卡的第一个内部选项卡。问题解决了一半。运行程序时,我可以在第一组内部选项卡上单击一下;如果我切换到第二个外部选项卡并尝试单击其内部选项卡而不先单击对话框控件,则它将再次冻结。因此,我做了一个Focus函数来聚焦当前选中的外部标签的当前选中的内部标签,并在我的标签更改事件(单击另一个标签时熄灭的事件)中调用了该功能。

这就是我最初问这个问题时的意思。我以为我的程序运行良好,直到我玩了更多,然后发现当我在另一个窗口或程序之间来回切换时,它的播放效果不佳。更具体地说,一旦我的程序失去焦点,就会有一些进程陷入困境,并占用整个CPU的处理能力。

现在,我之所以如此详细地解释我的小标签结构和重点问题的原因是:经过大量的实验,我发现如果注释掉外部标签结构上的第二个标签(即“高级设计”对话框及其所有 child 子选项卡)程序的其余部分运行良好,我可以切换到另一个窗口,而无需打斗就可以返回。我想:“太好了,这只是我程序的大约90%,为了使它正常工作,我已经将其注释掉了。让我们尝试进一步削减它。”我放回“高级设计”选项卡式对话框,但注释掉了“高级设计”中由选项卡控件创建的选项卡式对话框,一切仍然正常。我一步一步地放回属于“高级设计”选项卡控件的选项卡式对话框,并且每次我重新引入“错误”时,无论我未评论哪个选项卡。我还应该指出,我尝试放回的第一个标签页(当然是单独的)是“页边距”标签,这是MarginDlg类,我也可以在“基本设计”选项卡下使用它而没有麻烦。这使我相信,在选项卡式对话框中创建选项卡式对话框时,我没有做过的事情或我做不正确或做得不正确的事情,就像我必须首先集中精力使其工作一样。

我非常感谢能说明这种情况的一切。我包括了我认为是相关的代码片段;与往常一样,让我知道是否需要更多。

主对话框的.h文件中的变量声明:

//tab stuff
CTabCtrl m_MainTabControl;
vector<CDialog*> m_tabPages;
SimpDesDlg* simpDesDlg;
AdvDesDlg* advDesDlg;

当我的应用程序启动时,它将创建我的主对话框,并调用OnInitDialog():
(TODO上方的所有内容:注释是默认VS处理愚蠢的about对话框的内容)
BOOL CspAceDlg::OnInitDialog()
{
    CDialog::OnInitDialog();


    // Add "About..." menu item to system menu.

    // IDM_ABOUTBOX must be in the system command range.
    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);
        }
    }

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);         // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon

    // TODO: Add extra initialization here
    ///////////////////////////////////////

    DrawResultsArea();
    DrawTabs();
    theApp.Calculate();
    Focus();
    //simpDesDlg->Focus();
    //DrawToolbar();

    return FALSE;  // return TRUE  unless you set the focus to a control
}

DrawTabs()是我为外部标签控件创建标签的地方:
void CspAceDlg::DrawTabs()
{
    simpDesDlg = new SimpDesDlg;
    m_tabPages.push_back(simpDesDlg);
    advDesDlg = new AdvDesDlg;
    m_tabPages.push_back(advDesDlg);

    // create a tcItem to hold the name of each tab during creation
    // and then get inserted, and arrays holding the tab names and IDs of
    // the dialogs they refer to
    TC_ITEM tcItem;
    PSTR pszTabNames[] = {"Basic Design", "Advanced Design"};
    UINT pszTabItems[] = {IDD_SIMPLEDESIGNTAB, IDD_ADVANCEDDESIGNTAB};

    //every member of m_tabPages[] will become a tab
    for (int i = 0; i < int(m_tabPages.size()); i++)
    {
        //set up the tab name
        tcItem.mask = TCIF_TEXT;
        tcItem.pszText = pszTabNames[i];
        tcItem.cchTextMax = int(strlen(pszTabNames[i]));
        //insert the new tab into the tab control and create the dialog window
        m_MainTabControl.InsertItem(i, &tcItem);
        m_tabPages[i]->Create(pszTabItems[i], &m_MainTabControl);
    }

    //redraw so that the dialogs don't appear in upper left corner and cover the tabs
    CRect tabRect, itemRect;
    int nX, nY, nXc, nYc;

    m_MainTabControl.GetClientRect(&tabRect);
    m_MainTabControl.GetItemRect(0, &itemRect);

    nX=itemRect.left;
    nY=itemRect.bottom+1;
    nXc=tabRect.right-itemRect.left-1;
    nYc=tabRect.bottom-nY-1;

    m_tabPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW);
    for(int nCount=1; nCount < int(m_tabPages.size()); nCount++){
        m_tabPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW);
    }
}

主对话框的Focus()方法:
void CspAceDlg::Focus()
{
    int curSel = m_MainTabControl.GetCurSel();
    m_tabPages[curSel]->SetFocus();

    //if it's the basic design, we need to focus its first tab
    if (curSel == 0)
    {
        simpDesDlg->Focus();
    }
    //if it's the advanced design, we need to focus its first tab
    else if (curSel == 1)
    {
        advDesDlg->Focus();
    }
}

m_MainTabControl的标签选择更改事件的代码:
void CspAceDlg::OnTcnSelchangeBuildtabs(NMHDR *pNMHDR, LRESULT *pResult)
{
    for (int i = 0; i < int(m_tabPages.size()); i++)
    {
        m_tabPages[i]->ShowWindow(m_MainTabControl.GetCurSel() == i ? SW_SHOW :
                                                   SW_HIDE);
    }

    Focus();

    *pResult = 0;
}

SimpDesDlg和AdvDesDlg的标签使用相同的代码,除了标签初始化外(只是为每个标签创建不同的标签),因此这是AdvDesDlg的代码:

OnInitDialog():
BOOL AdvDesDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    DrawTabs();

    return false;
}

在选项卡式对话框中添加:
void AdvDesDlg::DrawTabs()
{
    //Make the dialogs for the tabs
    antennaDlg = new AntennaDlg;
    commSEDlg = new CommSEDlg;
    encryptorDlg = new EncryptorDlg;
    marginDlg = new MarginDlg;
    miscDlg = new MiscDlg;
    transRecDlg = new TransRecDlg;

    //add them all to the tabPages vector
    m_tabPages.push_back(antennaDlg);
    m_tabPages.push_back(commSEDlg);
    m_tabPages.push_back(encryptorDlg);
    m_tabPages.push_back(marginDlg);
    m_tabPages.push_back(miscDlg);
    m_tabPages.push_back(transRecDlg);

    //m_tabPages[0] = new AntennaDlg;
    //m_tabPages[1] = new CommSEDlg;
    //m_tabPages[2] = new EncryptorDlg;
    //m_tabPages[3] = new MarginDlg;
    //m_tabPages[4] = new MiscDlg;
    //m_tabPages[5] = new TransRecDlg;

    //antennaDlg = (AntennaDlg*) m_tabPages[0];
    //commSEDlg = (CommSEDlg*) m_tabPages[1];
    //encryptorDlg = (EncryptorDlg*) m_tabPages[2];
    //marginDlg = (MarginDlg*) m_tabPages[3];
    //miscDlg = (MiscDlg*) m_tabPages[4];
    //transRecDlg = (TransRecDlg*) m_tabPages[5];

    // create a tcItem to hold the name of each tab during creation
    // and then get inserted, and arrays holding the tab names and IDs of
    // the dialogs they refer to
    TC_ITEM tcItem;
    PSTR pszTabNames[] = {"Antenna", "Comm Support", "Encryptor", "Margins", "Misc", "Trasmitter/Receiver"};
    UINT pszTabItems[] = {IDD_ANTENNATAB, IDD_COMMSETAB, IDD_ENCRYPTORTAB, IDD_MARGINTAB, IDD_MISCTAB, IDD_TRANSRECTAB};

    //every member of m_tabPages[] will become a tab
    for (int i = 0; i < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; i++)
    {
        //set up the tab name
        tcItem.mask = TCIF_TEXT;
        tcItem.pszText = pszTabNames[i];
        tcItem.cchTextMax = int(strlen(pszTabNames[i]));
        //insert the new tab into the tab control and create the dialog window
        advTab.InsertItem(i, &tcItem);
        m_tabPages[i]->Create(pszTabItems[i], &advTab);
    }

    //redraw so that the dialogs don't appear in upper left corner and cover the tabs
    CRect tabRect, itemRect;
    int nX, nY, nXc, nYc;

    advTab.GetClientRect(&tabRect);
    advTab.GetItemRect(0, &itemRect);

    nX=itemRect.left;
    nY=itemRect.bottom+1;
    nXc=tabRect.right-itemRect.left-1;
    nYc=tabRect.bottom-nY-1;

    //m_tabPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW);
    for(int nCount=/*1*/0; nCount < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; nCount++){
        m_tabPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW);
    }
}

然后Focus()和tab更改:
void AdvDesDlg::Focus()
{
    this->SetFocus();
    for (int i = 0; i < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; i++)
    {
        m_tabPages[i]->ShowWindow(advTab.GetCurSel() == i ? SW_SHOW :
                                                   SW_HIDE);
    }

    int curSel = advTab.GetCurSel();
    m_tabPages[curSel]->SetFocus();
}

void AdvDesDlg::OnTcnSelchangeAdvDesign(NMHDR *pNMHDR, LRESULT *pResult)
{
    for (int i = 0; i < int(m_tabPages.size())/*(sizeof(m_tabPages)/sizeof(m_tabPages[0]))*/; i++)
    {
        m_tabPages[i]->ShowWindow(advTab.GetCurSel() == i ? SW_SHOW :
                                                   SW_HIDE);
    }

    int curSel = advTab.GetCurSel();
    m_tabPages[curSel]->SetFocus();

    *pResult = 0;
}

最佳答案

调试您的应用,使其进入此状态,然后转到“调试/全部中断”。在“线程”窗口中找到主线程,然后查看调用堆栈。调用堆栈中的某处将是导致挂起的代码。

请注意,为了获得合理的调用堆栈,您需要将Visual Studio指向Microsoft的符号服务器。见http://msdn.microsoft.com/en-us/library/b8ttk8zy.aspx

关于c++ - 如果我切换到另一个应用程序,我的MFC应用程序将卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1027503/

相关文章:

visual-studio-2008 - 如何阻止 VS2008 错误列表中出现 CSS 验证错误

c# - Visual Studio 2008 无法识别 Lambda 表达式语法

c++ - Klocwork(或其他工具)能否识别类型、typedef 和#define 指令?

c++ - 使用 try/catch 处理字符串流错误

visual-studio - CMAKE 避免在 Visual Studio 上编译 HLSL 着色器文件

c++ - 从类/结构的开头查找所有类/结构的所有成员 N 字节偏移量?

c++ - 在 Visual Studio 2005 中创建 DLL

visual-studio - 为什么 Visual Studio 的 Windows 窗体设计器停止工作?

C++ 中止重写

c++ - 当鼠标离开 QListView 时,ListViewItem 停留在鼠标悬停状态