首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于对话框的应用程序标题栏突出显示Windows10上的可视工件(即CDialogEx中的错误)

问基于对话框的应用程序标题栏突出显示Windows10上的可视工件(即CDialogEx中的错误)
EN

Stack Overflow用户
提问于 2018-12-14 03:16:17
回答 3查看 834关注 0票数 4

我不确定为什么我会得到这个视觉神器?

下面是重现的方法:

我正在使用Visual Studio 2017社区。创建新的C++ -> MFC项目:

​

​

然后指定“基于对话”:

​

​

然后构建为“调试”x86应用程序并运行它。

所以我在Windows10上运行它。

当这个基于对话框的过程具有焦点时,它看起来就像我所期望的那样:

​

​

但是,如果我将键盘焦点切换到其他应用程序(通过单击它),这个基于对话框的过程仍然保留其标题栏颜色:

​

​

我不确定这只是一个视觉问题,还是在窗口消息处理方面有更深层次的混乱。我怎么纠正它呢?(对于较旧的MFC项目,这不是问题。)

EN

回答 3

Stack Overflow用户

发布于 2018-12-14 03:34:38

我设法复制了您的问题,并找到了一个快速解决方案。您需要将WM_ACTIVATE消息处理程序添加到主对话框中,注释掉基类OnActivate,然后像这样修改它:

代码语言:javascript
复制
void CMFCApplication1Dlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    //CDialogEx::OnActivate(nState, pWndOther, bMinimized);

    // TODO: Add your message handler code here
    this->Default();
}

CWnd::Default调用需要保持默认按钮的活动/非活动可视化。

票数 6
EN

Stack Overflow用户

发布于 2018-12-15 17:49:30

好吧,虽然我非常欣赏@VuVirt的解决方案,但它并没有完全消除VS2017中默认的基于对话框的解决方案中的所有错误。它解决了标题栏焦点问题,但在继续开发我的项目时,我遇到了另一个bug。所以我从我的评论中复制并粘贴到他的回答中:

这里还是有些混乱。我不确定它是否与这个修复有关。例如:如果你创建了一个按钮,然后在它的处理程序中尝试这样做: CFileDialog d(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_EXPLORER,NULL,this);d.DoModal();打开一个文件选择器对话框。当文件选取器打开时,将其关闭并查看父MFC对话框窗口的标题栏是否恢复活动。在我的例子中,它保持非活动状态,直到我单击Windows任务栏,然后返回到MFC应用程序。

在试着把头撞到墙上看看发生了什么之后,我决定尝试@zett42在对我最初的问题的评论中提出的更早的解决方案(即用CDialog替换CDialogEx ),它起作用了!所有的虫子都不见了!

所以我的结论是:CDialogEx是有buggy的。

解决方法非常简单:当您创建一个新的基于对话框的项目时,使用项目范围内的查找和替换(在“编辑”菜单中),并将所有出现的CDialogEx替换为CDialog。就是这样。(我试着使用VS2017的重构工具来解决这个问题,但是它把它搞乱了,并没有完全取代它。因此,简单的搜索和替换就可以完成这项工作。)

如果你认为没有CDialogEx你会错过一些功能,那么你就不会错过,它所做的(除了引入bug之外)就是在对话框中添加背景图片和颜色。

因此,在微软修复其模板中的那些明显的错误之前,我坚持使用这种方法。

票数 2
EN

Stack Overflow用户

发布于 2018-12-16 04:26:26

这似乎是CDialogImpl::OnActivate和CDialogImpl::OnNcActivate中的一个错误

void CDialogImpl::OnNcActivate(BOOL& bActive) { if (m_Dlg.m_nFlags & WF_STAYACTIVE) bActive = TRUE;if (!m_Dlg.IsWindowEnabled()) bActive = FALSE;} void CDialogImpl::OnActivate(UINT nState,CWnd* pWndOther) { m_Dlg.m_nFlags &= ~WF_STAYACTIVE;CWnd* pWndActive = (nState == WA_INACTIVE)?pWndOther:&m_Dlg;if (pWndActive != NULL) { BOOL bStayActive = (pWndActive->GetSafeHwnd() == m_Dlg.GetSafeHwnd() || pWndActive->SendMessage(WM_FLOATSTATUS,FS_SYNCACTIVE));if (bStayActive) m_Dlg.m_nFlags |= WF_STAYACTIVE;} else { m_Dlg.SendMessage(WM_NCPAINT,1);}}

这意味着当显示CMFCPopupMenu时,CDialogEx能够保持活动状态。

但m_Dlg.SendMessage(WM_NCPAINT, 1)是个可疑电话。用法与WM_NCPAINT的文档不匹配

参数

wParam窗口更新区域的句柄。将更新区域裁剪到窗口框架。

lParam

不使用此参数。

此外,OnNcActivate还具有基于IsWindowEnabled()的覆盖。这似乎是修复OnActivate中早期问题的补丁。但它会在其他地方引发问题,例如在CDialogEx中使用CFileDialog时

建议的解决方案:

修改CDialogEx::OnActivate,使其运行默认过程。或者,将其更改为强制重新绘制。

代码语言:javascript
复制
BOOL CDialogEx::OnNcActivate(BOOL active)
{
    if(m_nFlags & WF_STAYACTIVE)
        active = TRUE;
    return(BOOL)DefWindowProc(WM_NCACTIVATE, active, 0L);
}

void CDialogEx::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    Default();
}

或

代码语言:javascript
复制
void CDialogEx::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
    Default();

    //save the previous flag
    UINT previous_flag = m_nFlags;
    m_nFlags &= ~WF_STAYACTIVE;

    // Determine if this window should be active or not:
    CWnd* pWndActive = (nState == WA_INACTIVE) ? pWndOther : this;
    if(pWndActive != NULL)
    {
        BOOL bStayActive = pWndActive->GetSafeHwnd() == GetSafeHwnd() ||
            pWndActive->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE);
        if(bStayActive)
            m_nFlags |= WF_STAYACTIVE;
    }

    if(previous_flag != m_nFlags && previous_flag & WF_STAYACTIVE)
    {
        //if the flag is changed, 
        //and if WF_STAYACTIVE was previously set, 
        //then OnNcActivate had handled it wrongly, do it again
        SendMessage(WM_NCACTIVATE, FALSE); //<- less wrong!
    }
}

例如,这应该适用于CMFCPopupMenu。MFC菜单将打开,但不会停用该对话框。

我不确定SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE)是用来做什么的,我还没能测试它……如果有必要,似乎可以将代码添加到OnNcActivate上,然后OnActivate就不用管了。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53768653

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档