MFC的基于对话框的应用程序标题栏突出显示Windows 10上的视觉伪像(即CDialogEx中的错误)

时间:2018-12-13 19:16:17

标签: c++ user-interface mfc visual-studio-2017 windows-10

我不确定为什么会得到这个视觉伪像?

此处是复制方法:

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

enter image description here

然后指定“基于对话框”:

enter image description here

然后以“调试” x86应用程序的形式构建并运行它。

所以我正在Windows 10上运行它。

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

enter image description here

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

enter image description here

我不确定这仅仅是视觉故障还是窗口消息处理有更深层的混乱。我该如何纠正? (这与较早的MFC项目无关。)

3 个答案:

答案 0 :(得分:5)

我设法复制了您的问题,并找到了快速解决方案。 您需要将WM_ACTIVATE消息处理程序添加到主对话框,注释掉基类OnActivate并按如下所示对其进行修改:

class MainApp(App):

    def build(self):
        self.title = "Shantazam"
        Window.bind(on_dropfile=self._on_file_drop)
        Window.size = (400,700)
        self.mainLayout = MainLayout()
        return self.mainLayout

    def _on_file_drop(self, window, file_path):
        self.mainLayout.artistName = 'Three Day Grace'

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

答案 1 :(得分:2)

好吧,就我对@VuVirt的解决方案的赞赏而言,它并没有完全消除VS2017中基于对话框的默认解决方案中提供的所有错误。它解决了标题栏焦点问题,但是在继续开发我的项目时,我遇到了另一个错误。因此,我将其复制并粘贴到他对他的回答的评论中:

  

那里仍然有一些问题。我不确定它是否与此修复程序有关。例如:如果创建一个按钮,然后在其处理程序中尝试执行以下操作:CFileDialog d(TRUE,NULL,NULL,OFN_HIDEREADONLY | OFN_EXPLORER,NULL,this); d.DoModal();打开文件选择器对话框。当文件选择器打开时,将其关闭,然后查看父MFC对话框窗口的标题栏是否恢复为活动状态。就我而言,它一直保持不活动状态,直到我单击Windows任务栏,然后再回到该MFC应用程序。

将我的头撞在墙上试图看看那里发生了什么之后,我决定尝试使用@ zett42在我的原始问题的注释中提出的较早解决方案(即用CDialog替换CDialogEx),并且有效!所有的错误都消失了!

这是我的判断:CDialogEx是越野车。

解决方案非常简单::创建新的基于对话框的项目时,请在项目范围内使用查找和替换(在“编辑”菜单中)并替换所有出现的CDialogExCDialog。就是这样。 (我曾尝试使用VS2017的重构工具,但它搞砸了它并没有全部替换。所以简单的搜索和替换就可以完成这项工作。)

如果您认为如果没有CDialogEx,将会缺少某些功能,那么您将不会。它所做的一切(除了引入错误之外)是为对话框添加背景图像和颜色。

因此,在MS修复其模板中那些明显的错误之前,我一直坚持这种方法。

答案 2 :(得分:2)

这似乎是<api batchcomplete=""> <query> <pages> <page _idx="25039021" pageid="25039021" ns="0" title="Go (programming language)"> <extract xml:space="preserve"> stuff about golang </extract> </page> </pages> </query> </api> type Page struct { PageID string `xml:"pageid,attr"` } type Extract struct { Text string `xml:"query>pages>page>extract"` Page Page `xml:"query>pages>page"` } 中的错误:

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); } } 时。

但是CDialogEx是个可疑电话。用法与WM_NCPAINT的文档不匹配:

  

参数

     

CMFCPopupMenu      窗口更新区域的句柄。更新区域被裁剪到窗口框架。

     

m_Dlg.SendMessage(WM_NCPAINT, 1)

     

不使用此参数。

此外,wParam具有一个基于lParam的覆盖。这似乎是一个补丁,用于解决OnNcActivate中的早期问题。但这会在其他地方引起问题,例如在IsWindowEnabled()

中使用OnActivate

建议的解决方案:

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

CDialogEx

CDialogEx::OnActivate

例如,这应该与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(); } 一起使用。 MFC菜单将打开而不会禁用该对话框。

我不确定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上添加代码,然后再添加{{ 1}}独自一人。