Date: | January 21, 2011 / year-entry #15 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20110121-00/?p=11703 |
Comments: | 22 |
Summary: | Here's a question that came from a customer. You can answer it yourself based on what you know about modal UI. (If you're kind of rusty on the topic, you can catch up here.) I've left in some irrelevant details just to make things interesting. Our program launches a helper program to display an Aero... |
Here's a question that came from a customer. You can answer it yourself based on what you know about modal UI. (If you're kind of rusty on the topic, you can catch up here.) I've left in some irrelevant details just to make things interesting.
Although it's not common, it is legal to have a window's parent or owner belongs to another thread or process. But it definitely makes things a bit more tricky to manage because it attaches the input queues of the two threads, and you now have two threads coöperating to manage a single window hierarchy. Is the cross-process window hierarchy a contributing factor to the problem, or is it just a red herring? |
Comments (22)
Comments are closed. |
Why TaskDialogIndirect? And also where is the hInst for the TASKDIALOGCONFIG…
From what I understand of the description of the problem, I think the TaskDialog should have used the Aero Wizard as its parent. This is assuming the cancel handling is done in the Wizard, prior to closing it. (The description of the workflow strongly implies that the confirmation is done before closing the wizard.)
I don't understand why MessageBox() works properly. Maybe it automatically detects that the parent is disabled and search for its active child?
I'm assuming that the call to the wizard's DoModal() with hwndMainFrame as a parameter is setting hwndMainFrame as the owner of the modal wizard (if that's not the case, then never mind this whole thing). The TaskDialog is setting hwndMainFrame as its parent. This means that there's two different dialogs that have the same owner, unless I'm getting myself confused by the differences between parent and owner. When the TaskDialog closes, it may re-enable and switch back to its owner, which is supposed to still be disabled and waiting on the wizard. That seems like it's guaranteed to lead to strange behavior.
I have done cross-process owner/owned windows. It does work from native code, but managed code seemt to not like it.
I'm guessing that corss-process is a red herring here.
I, too, would like clarification on whether the task dialog is shown prior to dismissing the wizard. If so, then the task dialog's parent should be the wizard, not the original program. Then the task dialog should return activation to the wizard which would in turn return it to the main window.
But I'm not sure why the message box works when the task dialog doesn't.
What's with the umlaut on the second 'o' in 'cooperating' (last sentence of second-to-last paragraph)? Is that a hint of some sort? :-)
@SMW
Raymond is just trying to set a new trend, that's second time he writes cooperates this way this week…
Well of course if this entry is several years old as many are, then it's just a coincidence both mistakes happen the same week!
Or maybe Raymond is using his psychic powers to also write his comments several years before the story is published.
Or maybe we are ignorant youngins and Raymond is fan of this blog: http://thedutras.blogspot.com/
Well… Raymond has answered in the time it took me to write the post, that's what I get for being slow :)
Now I'm slow AND an ignorant youngin…
The Wikipedia entry also states that its use is uncommon in English, stating that it is optional. I also don't read The New Yorker or the MIT Technology Review. And since I have a German background and took German language classes way back in high school I naturally think it's an umlaut. But then in English that would have been written differently.
FTFY ;-)
Regarding the actual question, in my own code, it would most likely be that I forgot to pass
config
along to code that was expecting it, and MessageBox would work because it didn't need the config.Raymond may be channeling the New Yorker magazine which sticks to the diaresis on cooperate and coordinate, even though most magazines and newspapers have dropped the use. I didn't think the English language had more than twenty-six letters, with no diacritical marks or accents — that's what I learned in elementary school. But there's amoeba, and diarrhoea, where oe is combined into one letter in older writings.
Another process has the active Window and wants to give it away to another window?
I think calling AllowSetForegroundWindow should do the trick.
Maybe MessageBox handles this case to be backwards compatible to applications that don't know about the above.
Mmmm. I'm reading this in a tabbed IE frame. There are three tabs and four IE processes running, making me wonder if this is a case of a window's parent or owner belonging to another process.
The correct modal UI is none.
Totally unrelated, but I just went to a search engine to try to find one of your articles for a co-worker. I didn't narrow to search to "blogs.msdn.com", however. The first hit in the results was an article on my *own* web site that happens to mention *another* article of yours. I think I'm going to mention you in all of my articles now. ;)
@Paul M. Parks: What post?
My guess: The TaskDialog is trying to set an owner window which is still disabled by the wizard. Maybe TaskDialog skips the EnableWindow/SetFocus calls for such a window while MessageBox doesn't.
Please can we learn to co-operate with Raymond? Thanks.
I remember a bug in Windows 3.1 where the last active popup didn't get updated for a background window with a nested dialog. In particular we used an app framework whose default print preview was in a popup and you could trigger the bug by switching away from the app while the print progress dialog (which closed automatically when it had finished printing) was active. In Windows 95 the bug was alleviated by setting the last active popup to NULL, and the bug was completely fixed in at least Windows 2000 (it may have been fixed in prior Windows NT versions but I didn't test it there.)
Cross-process is a red herring; the wrong parent was used.
DerekYu: while I agree in principle, how would you have solved the problem at hand without a modal confirmation message?
As presented, this problem makes no sense. MessageBox and TaskDialog both implement a a modal popup. With the same parent window being specified, and with both being called from the PSM_QUERYCANCEL message the behavior of the application should be the same. Unless TaskDialog and MessageBox have internal differences in how they implement their modality. Cross process is also a red herring as, again, both examples are doing the same cross process things the same way. Which means there is some undisclosed piece of information that makes one of the scenarios not modal, or it was actually the Butler, in the pantry, with the serving fork.
Yeah, I think the "irrelevant details" only wound up making the whole exercise more confusing, maybe that's the point since this is a real world situation? It seems the obvious correct answer is that the incorrect window is specified for hwndParent, as many have pointed out; however, that simple answer is now completely overshadowed by the "irrelevant details" on why there's a difference between TaskDialog and MessageBox (I'm leaning towards Pierre's theory), and how the use of incorrect hwndParent ultimately leads to the wrong window becoming active (perhaps a surface symptom of a more serious issue triggered by hwndMainFrame being re-enabled prematurely?)
And it's amusing that the whole *topic* itself was for a short time sidetracked by the irrelevant topic of diaeresis. Yeah, this blog entry has become more interesting all right, for better or for worse. :p
Raymond seems to answer this in his linked series (#5):
blogs.msdn.com/…/379635.aspx
"If you are displaying a modal dialog from another modal dialog, it is important to pass the correct window as the owner for the second dialog."