8

我正在开发一个应用程序,它恰好是我也在开发的安装程序的引导程序。该应用程序进行了几次 MSI 调用以获取我需要的信息,以便将作为我的应用程序主窗口的向导组合在一起,这会导致在收集信息时打开一个进度窗口,然后在完成后消失。然后设置并启动向导。我的问题是向导(从 CPropertySheet 派生)不想在我不添加一些调用的情况下出现在最前面并成为活动应用程序。

我已经在我的 OnInitDialog() 方法中使用以下代码解决了将其置于最前面的问题:

SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // force window to top
SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // lose the topmost status that the previous line gave us

我的问题是我还没有弄清楚如何让窗口自动激活(即,让自己成为焦点)。SetFocus() 在这种情况下不起作用。我需要一些东西来强制窗口到 Z 顺序的顶部并激活它,最好是在尽可能少的调用中。

我的猜测是 MSI 调用在开始时打开的进度窗口导致主窗口出错,但我无法阻止该窗口出现。此外,隐藏它是没有意义的,因为它让用户在主窗口到达之前知道发生了什么。

4

5 回答 5

11

安德鲁并不完全正确。Windows 确实非常努力地阻止您窃取焦点,但可以使用以下方法。

  1. 附加到当前具有焦点的窗口的线程。
  2. 使您的窗口成为焦点。
  3. 从线程中分离。

其代码将如下所示:

DWORD dwCurrentThread = GetCurrentThreadId();
DWORD dwFGThread      = GetWindowThreadProcessId(GetForegroundWindow(), NULL);


AttachThreadInput(dwCurrentThread, dwFGThread, TRUE);

// Possible actions you may wan to bring the window into focus.
SetForegroundWindow(hwnd);
SetCapture(hwnd);
SetFocus(hwnd);
SetActiveWindow(hwnd);
EnableWindow(hwnd, TRUE);

AttachThreadInput(dwCurrentThread, dwFGThread, FALSE);

您可能需要也可能不需要以管理权限运行您的程序才能使其正常工作,但我已经亲自使用过这段代码,它已经完成了工作。

于 2013-12-19T21:15:43.013 回答
7

你不能偷走焦点。时期。

请参阅这篇旧新事物文章:

https://blogs.msdn.microsoft.com/oldnewthing/20090220-00/?p=19083

于 2009-03-27T03:17:19.977 回答
0

ShowWindow(youwindow,SW_SHOWNORMAL) 不工作吗?-大学教师

于 2009-03-27T02:50:39.777 回答
0

您会发现,BringWindowToTop 或 SetForegroundWindow 具有必须满足的要求,才能将窗口实际强制置于所有其他窗口(应用程序)的前面。如果不满足这些条件,Windows 只会在任务栏中闪烁应用程序的图标。本文介绍了一种解决方法,但正如 1800 INFORMATION 指出的那样,不建议这样做。我想你只需要接受它。

于 2009-03-27T03:05:49.973 回答
0

应用程序“窃取”焦点是有充分理由的。我的应用程序是一个加载许多驱动程序 DLL 的服务器。另一个连接到服务器的应用程序有一个按钮,该按钮向服务器发送消息以显示其中一个 DLL(由服务器拥有,而不是客户端应用程序拥有)中的详细信息,以方便使用。不幸的是,这个弹出的打开窗口通常隐藏在多个窗口下。

于 2021-02-19T14:22:14.773 回答