我不确定为什么会得到这个视觉伪像?
此处是复制方法:
我正在使用Visual Studio 2017社区。创建一个新的C ++-> MFC项目:
然后指定“基于对话框”:
然后以“调试” x86应用程序的形式构建并运行它。
所以我正在Windows 10上运行它。
当这个基于对话框的过程具有焦点时,它看起来就像我期望的那样:
但是,如果我将键盘焦点切换到其他应用程序(通过单击它),则此基于对话框的过程仍然保留其标题栏颜色:
我不确定这仅仅是视觉故障还是窗口消息处理有更深层的混乱。我该如何纠正? (这与较早的MFC项目无关。)
答案 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
是越野车。
解决方案非常简单::创建新的基于对话框的项目时,请在项目范围内使用查找和替换(在“编辑”菜单中)并替换所有出现的CDialogEx
与CDialog
。就是这样。 (我曾尝试使用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}}独自一人。