Jump to content
  • Advertisement
Sign in to follow this  
Buckeye

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

This topic is 3038 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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]

Share this post


Link to post
Share on other sites
Advertisement
Don't know why you're seeing this behavior, but did you try sticking a call to BringWindowToTop() in Dialog2's WM_INITDIALOG handler?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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);

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!