我正在调查与失去焦点和更改窗口激活相关的问题。我发现如果我创建一个不可见的属性表,活动/前景窗口会改变,焦点窗口也会改变。以下是一些示例MFC代码:
// ignore CAutoDeleter, just a template that calls "delete this " in PostNcDestroy()
CPropertySheet* pSheet = new CAutoDeleter<CPropertySheet>(_T("Test Sheet"));
CTestPage* pPage = new CAutoDeleter<CTestPage>();
pSheet->AddPage(pPage);
DWORD style = WS_SYSMENU | WS_POPUP | WS_CAPTION | DS_MODALFRAME | DS_CONTEXTHELP;
// style |= WS_DISABLED; //does nothing to help
DWORD exStyle = 0;
//exStyle = WS_EX_NOPARENTNOTIFY|WS_EX_NOACTIVATE; // does nothing to help
pSheet->Create(AfxGetMainWnd(), style, exStyle); // adding
调用pSheet-&gt; Create()后,活动/前景/焦点窗口已更改,应用程序窗口位于顶部。如果我使用Spy ++并查看创建的窗口,则会发现属性表是DIALOG窗口类。我假设它有一个不同的WNDPROC,当然。有趣的是,如果我使用创建一个不可见的无模式对话框,它就不会出现问题。如果我创建了不可见的无模式对话框,则活动/前景/焦点窗口保持不变。
我尝试在代码片段中设置各种标记,但是它们没有任何可辨别的效果 - 我仍然没有闪烁和激活。
我可以通过在pSheet->Create()
之前和之后设置和清除挂钩(WH_CBT)来获得一些改进 - 然后吃掉激活消息。当我这样做时,我没有可怕的闪烁,我的应用程序窗口没有出现在顶部。但是,焦点(以及具有插入符号的窗口的插入符号)确实远离Create()之前的任何窗口。
有没有人知道在创建隐藏属性表时保持焦点和激活不变的方法? (在某些时候,属性表可能会或可能不会被设置为可见。并且,如果属性表在被销毁时不可见,它也会导致闪烁和激活更改。)
我尝试使用GetUIThreadInfo()中返回的值来尝试在调用Create()之后恢复内容,但它也会导致一些闪烁。
我只想知道如何创建一个不会导致活动,前景和焦点窗口发生变化的不可见属性表。
答案 0 :(得分:2)
不幸的是,底层API函数PropertySheet
在创建后在主属性表对话框中调用SetForegroundWindow
。没有简单的方法 - 使用WH_CBT
钩子的你的kludge可能是你最好的选择。
修改:正如@stephen在this duplicate question的评论中所建议的那样,您可以使用LockSetForegroundWindow
阻止激活/焦点更改。
答案 1 :(得分:2)
我几周来一直在努力解决同样的问题,有一个类似的项目,我的主应用程序启动一个辅助EXE进程,充当音频应用程序中的服务器(这需要一个单独的进程来屏蔽应用程序插件故障,因此它可以是实时音频处理的高优先级。)
我的辅助EXE是一个无模式CPropertySheet
,用于状态和诊断显示,但是打算隐藏在后台启动。然而,无论我尝试了哪些变通方法(例如覆盖OnWindowPosChanging
),它总是在启动时从主应用程序中窃取激活(
我以为我会发疯,所以我很高兴找到这个问题。 WH_CBT技巧很有用,但我发现虽然它阻止了激活辅助EXE,但它并没有阻止主应用程序的停用。
但后来我在LockSetForegroundWindow
API(自Win2K以来可用)中发现了一个出色的解决方案,这是我以前从未听说过的。看起来它正是为了这个目的,禁用前台激活的更改并防止对等进程窃取它。
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633532(v=vs.85).aspx
它可以很好地消除在属性表公共控件深处发生的对SetForegroundWindow
的内部调用,并且无论是在CreateProcess
之前的主应用程序中还是在辅助EXE中使用,都可以正常工作。我选择后一种情况来包装属性表创建:
LockSetForegroundWindow(LSFW_LOCK);
pSheet->Create(NULL, dwStyle, dwExStyle);
LockSetForegroundWindow(LSFW_UNLOCK);
这最大限度地减少了干预的范围,并将修复本地化为作为问题根源的流程。我希望这可以挽救其他人在这个繁琐的问题上浪费尽可能多的时间。