0

For cross-platform parity reasons, my GetOpenFileName() specifies no owner and I explicitly disable all toplevel windows myself. The problem is re-enabling. In order to re-enable these windows correctly, I need to re-enable them before the dialog closes.

In the case of the user choosing a file, this is no issue: I just check for CDN_FILEOK in the hook procedure. No issues, no messed-up focus.

How can I do the same, but for cancelling the dialog box?

I have tried WM_DESTROY in the hook procedure, but that runs after the dialog box has been hidden (too late). I have tried WM_COMMAND, but that doesn't seem to cover all cases. I'm not sure what other options I have.

I need to target Windows XP and newer for now; that also means no Common Item Dialogs. Thanks!

Alternative: if there was a way to do a callback-based GetOpenFileName() that returned control to my message loop, like on Mac OS X with beginSheetModalForWindow:, I could be able to specify a parent window and avoid this hack.

andlabs
  • 11,290
  • 1
  • 31
  • 52
  • 1
    The obvious mistake you are making is helping too much. The dialog already knows how to be modal without your help. And knows how to do it right. – Hans Passant Aug 25 '14 at 22:21
  • It does, but I cannot choose a /single/ modal owner. I would like it to be modal to all windows of the program, not just one of them. My message loop does a lot of extra stuff; I'd rather not have that stuff being overridden by `GetOpenFileName()`'s. – andlabs Aug 25 '14 at 22:41
  • Clearly the rest of your code has to pretty messed up to break the contract of a dialog. Surely starting from "my message loop does". Nobody can see it. Just stop doing that. – Hans Passant Aug 25 '14 at 22:58
  • Agreed. `GetOpenFileName()` accepts an owner HWND for a reason. You really do need to use it the way it is intended to be used. Your message loop is obviously doing something it should not be doing if you have to circumvent the way the API is designed to be used. – Remy Lebeau Aug 25 '14 at 23:04
  • I have two things: an override for WM_(SYS)KEYDOWN/UP for one of my custom window classes (one that doesn't support TranslateMessage) and one that allows tabbing between tabs and their children. https://github.com/andlabs/ui/blob/master/redo/uitask_windows.c#L11 I don't know what other options I have, apart from only allowing one toplevel window and requiring any others you want to open in this API to be dialog boxes. (Dialog modality is nonportable...) – andlabs Aug 25 '14 at 23:42
  • Actually, now I wonder if what I am doing here could be done without using a custom message loop; the big thing is that I need to inhibit IsDialogMessage() if I handle a keypress in the "area" window class... – andlabs Aug 26 '14 at 00:50
  • (if someone is still interested in answering tha tquesiton,i I moved the IsDialogMessage() to under notkey: in the code listed locally) – andlabs Aug 26 '14 at 02:07
  • HansPassant, RemyLebeau - actually different idea - if I run the GetOpenFileName() in its own thread, with a specified owner window, I could still get events properly in my other windows with my regular message loop, right? – andlabs Aug 26 '14 at 03:51
  • If you decide to build a cross-thread window hierarchy, make sure you understand the implications of calling [`AttachThreadInput`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms681956.aspx). – IInspectable Aug 26 '14 at 08:20
  • I'm aware. The idea here is simple: the new thread just calls GetOpenFileName() and returns; as a result, its parent window will be disabled anyway. Meanwhile, every other window in the system will continue to run with my customized message pump, and when GetOpenFileName() returns and the thread exits, (I hope, anyway, that) all control returns to the main thread. – andlabs Aug 26 '14 at 13:20
  • 1
    Create a dummy hidden owner window and use that as the owner for the dialog. When the dummy owner is enabled, that's your change to enable all the other windows. – Raymond Chen Sep 14 '14 at 16:48
  • It's months late but I can say I'm doing what @RaymondChen suggested now. What I did earlier didn't work, but only now did I get to a point where I could rewrite; thanks again! – andlabs May 22 '15 at 23:16

1 Answers1

0

There is no CDN notification when the dialog is canceled. If the user presses the Cancel button, you could try intercepting the BN_CLICKED notification that it sends to the dialog, or even subclass the button itself. But if the user cancels the dialog through other means (clicking the red X, pressing ESC, etc), you will likely have to catch the WM_CLOSE message instead.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • No luck with either approach. I don't think the hook procedure is getting the BN_CLICKED; in fact, if I understand the documentation correctly, it's not even the dialog procedure for the whole open dialog, but rather for a subdialog... so now I wonder how my original question would even have worked... – andlabs Aug 25 '14 at 23:51
  • 1
    You can subclass the dialog's HWND (or its parent HWND) directly to intercept those kind of messages. – Remy Lebeau Aug 25 '14 at 23:52