views:

682

answers:

4

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.

A: 

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

Don Dickinson
Haven't tried it, but I'm guessing that it's no more effective than BringWindowToTop(). (See my comment on Mitch Wheat's reply.)
RobH
A: 

BringWindowToTop

Mitch Wheat
Tried it. Doesn't work.
RobH
A: 

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.

Arnold Spence
Don't do this. Raymond Chen explains why this often causes your app to hang: http://blogs.msdn.com/oldnewthing/archive/2008/08/01/8795860.aspx
1800 INFORMATION
Thanks. I've edited my answer.
Arnold Spence
+4  A: 

You can't steal focus. Period.

See this Old New Thing article:

http://blogs.msdn.com/oldnewthing/archive/2009/02/20/9435239.aspx

Andrew Medico
Thank you, I was looking for this article as the answer to this question. Please everyone that reads this, internalise it and fix the virus meme that tries to steal foreground activation. But my app is special! Your app is user hostile. Don't do it!
1800 INFORMATION
I agree and although in all likely hood this applies to the author, he (or somebody else) may have a good reason to need this functionality (closed system, private or home computer only). Make a recommendation on usage but don't hide the information.
Arnold Spence
I hope that Microsoft will - some day - finally fix all focus-stealing once and for all. Programmers doing focus-stealing should be sent to Siberia. Naked.
snemarch
My reason for stealing focus is that the user just launched the application, it launches a window that does get focus, that window goes away, and the app launches another window, which doesn't get focus. That leaves the user scratching his head if I don't fix that.
RobH
That article is of no use to me, because I'm not running a second instance of the same application. My application (or, rather, the MSI calls that my application is calling) is launching a window and then closing it, and my app then launches its main window. It's not taking focus, but it should.
RobH
It sounds like it applies *exactly* to your situation. You have process A launching process B and you want process B to get focus. The solution, as the article explains, is that process A must *give* process B focus - process B can't take focus by itself.
Andrew Medico
No, my program calls MSI functions that end up opening a progress window (which gets focus). The last MSI function call closes the window, and my app then opens its main window (which doesn't get focus). It's all happening in the same process.
RobH