How do I force my app to come to the front and take focus?

ⅰ亾dé卋堺 提交于 2019-11-28 07:37:26

问题


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.

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

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.

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.


回答1:


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. Attach to the thread of the window that currently has focus.
  2. Bring your window into focus.
  3. Detach from the thread.

And the code for that would go something like this:

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.




回答2:


You can't steal focus. Period.

See this Old New Thing article:

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




回答3:


doesn't ShowWindow(youwindow,SW_SHOWNORMAL) work? -don




回答4:


You will find that BringWindowToTop or SetForegroundWindow have requirements that must be met before the window will actually be forced to the front over all other windows (applications). If these aren't met, Windows will only flash the application's icon in the taskbar. This article presents a way around that but as 1800 INFORMATION points out, it is not recommended. I guess you'll just have to accept it.



来源:https://stackoverflow.com/questions/688337/how-do-i-force-my-app-to-come-to-the-front-and-take-focus

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!