Skip to main content
GameDev.net gamedev.net
🔒 Locked

Win32 API, XP - DialogBox doesn't come to top [A solution found]

Started by Buckeye Jul 16, 2010 at 5:29 PM 6 replies 3.1k views
Original Post
Buckeye
Buckeye
I have 2 dialog box classes, both modal, initiated with DialogBox(...). Dialog1 can call Dialog2 by new'ing an instance of Dialog2 and calling Dialog2's DoModal() function (which just calls DialogBox(..) ). (I delete the Dialog2 instance after it returns)

Dialog2 allows selection of a file using the common controls GetOpenFileName.

When I select a file in Dialog2 (using GetOpenFileName) and close Dialog2, it returns to Dialog1 okay. However, the 2nd time I call Dialog2, the Dialog2 window does not come to the top of the z-order. Dialog2's OnInitDialog get called but WM_NCPAINT isn't called until I can click on the Windows taskbar for the main app and then Dialog2 will appear.

The "hidden" behavior of Dialog2 occurs only if GetOpenFileName is called from Dialog2. But then it occurs every time Dialog2 is invoked after that (unless I close and reopen Dialog1).

It appears that invoking GetOpenFileName, for some reason, affects the focus of Dialog2 the next time it's instantiated and run. I've tried setting the owner of the GetOpenFileName window to both the dialog and NULL.

Anyone know why this occurs?

EDIT: apologies - posted to wrong forum - moderator notified.

[Edited by - Buckeye on July 17, 2010 6:47:40 AM]
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
Buckeye
Buckeye
Gave it a try, both in OnInitDialog and immediately after the return from GetOpenFileName. Didn't work, unfortunately. Thanks for the suggestion. Hadn't heard of BringWindowToTop, actually.
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
Erik Rufelt
Erik Rufelt
Is your other program window still active?
When using BringWindowToTop, the app must already be active, or it won't have permission to use BringWindowToTop, unless attaching to the thread of the foreground window (or something like that, there are docs about it on MSDN, but I couldn't find it now...).
If that happens to be your problem, it can be solved like this:
HWND hFGWnd = GetForegroundWindow();DWORD dwFGId = GetWindowThreadProcessId(hFGWnd, NULL);DWORD dwCId = GetCurrentThreadId();AttachThreadInput(dwCId, dwFGId, TRUE);BringWindowToTop(...);AttachThreadInput(dwCId, dwFGId, FALSE);
Buckeye
Buckeye
Gave that a try, but it didn't work either. It apparently does have something to do with threading as GetOpenFileName does work in another thread.

Also, the following sequence "avoids" the problem:

Open Dialog1
Open Dialog2 from Dialog1
Invoke GetOpenFileName from Dialog2
Close Dialog2
-->> Drag Dialog1 window to a new position
Open Dialog2 - appears correctly.

Also tried SetWindowPos(..,HWND_TOP,..) in OnInitDialog. No help.

Dragging Dialog1 must set the foreground window/thread somehow.

Think I'll look into setting foreground window to main app window, Dialog1 or Dialog2. At this point it's strictly hacking.

EDIT: None of that worked. Trying to determine what aspect of moving Dialog1 does the trick.

EDIT2: Did some playing around and it's seems that XP doesn't know how to handle 2 modal dialogs open by the same app after a GetOpenFileName thread has been invoked. Even with Dialog2 owned by Dialog1, and GetOpenFileName owned by Dialog2, XP (for whatever reason) hasn't a clue what to do when Dialog2 is opened a second time.

Thanks all for the input. I'll have to hack something.

[Edited by - Buckeye on July 16, 2010 9:42:28 PM]
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
Endurion
Endurion
That's weird. Can you post a toned down small example that exhibits the behaviour?

Messing with BringWindowToTop and similar NEVER solves a problem, it only creates a host of new ones.

Which API are you using? Win32 directly or MFC?
Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
Buckeye
Buckeye
This is a Win32 project (uses DirectX in the main frame client). Just occurred to me that, for some reason DirectX may be involved [embarrass]. Let me cobble together a very small project without DX and see what happens. If the behavior is the same (or maybe if it's not!), I'll post the code.

AHA! From your suggestion to put together simplified code - A clue! - I created a basic Win32 windows app without DirectX that launches a dialog that launches a dialog that launches GetOpenFileName. It does not exhibit the behavior noted above.

With that hint, back to the first app that exhibits the behavior described above:
1. Open dlg1
2. Move dlg1 from over the DirectX window!
3. From dlg1, launch dlg2
4. From dlg2, launch GetOpenFileName
5. From dlg1, launch dlg2 again
No problem!

So, it may have something to do with trying to update the Dx window, though I haven't any idea why launching GetOpenFileName or not launching it would make a difference. But it does. As hinted above, it may be a thread issue that doesn't arise until GetOpenFileName launches a thread for itself. It appears that as long as the dialog threads are associated with the main window, there's no problem.

I'll play around a bit and open a topic in the DirectX forum if I can't figure it out.

EDIT:
Solution (I think) - I have a "paused" flag for the application that allows me to "freeze" the DirectX rendering. In the WndProc, for WM_PAINT, I call for rendering only if the app is not paused. However, if paused, BeginPaint/Endpaint was not called. So, the update region was never validated. I moved the "paused" check inside the BeginPaint/Endpaint pair and it appears to be functioning as it should.

Not validating the update region (whether I redraw or not) is probably bad practice (duh). But apparently it's important only if another thread is launched by the app (e.g., GetOpenFileName). In any case, the WndProc is "proper" now.

Thanks to all for making me think of things to look at.

EDIT2:
I can't keep from messing with it. Because this particular app is an editor, rather than an app that needs to be paused, I eliminated the "pause" feature altogether. Now it works as-advertised. [sigh]

As Ron White (comedian) says: "You can't fix stupid."


[Edited by - Buckeye on July 17, 2010 6:11:50 AM]
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
Zahlman
Zahlman
Moved to General Programming per OP request.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.