我如何强制我的应用程序出现在前面并集中注意力?

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

I'm working on an application that happens to be the bootstrap for an installer that I'm also working on. The application makes a few MSI calls to get information that I need for putting together the wizard that is my application's main window, which causes a progress window to open while the info is being gathered and then go away once that's done. Then the wizard is set up and launched. My problem is that the wizard (derived from CPropertySheet) does not want to come to the front and be the active application without me adding in some calls to do so.

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

I've solved the problem of bringing it to the front with the following code in my OnInitDialog() method:

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 顺序的顶部并激活它,最好是在尽可能少的调用中.

My problem is that I still haven't figured out how to make the window self-activate (i.e., make itself be the one that has the focus). SetFocus() won't work in this context. I need something that will force the window to the top of the Z-order and activate it, preferably in as few calls as possible.

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

My guess is that the progress window opened at the beginning by the MSI calls is causing the main window to screw up, but I have no way to prevent that window from appearing. Also, it wouldn't make sense to hide it, because it lets the user know what's going on before the main window arrives.

推荐答案

Andrew 并不完全正确.Windows 确实会尽力阻止您窃取焦点,但可以使用以下方法.

Andrew isn't completely correct. Windows does try really hard to stop you from stealing focus, but it is possible using the folowing method.

  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);

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

You may or may not need to have to run your program with administrative privileges for this to work, but I've used this code personally and it has go the job done.

相关文章