Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Modeless from Modal wxDialog

76 views
Skip to first unread message

Brian Ray

unread,
Apr 5, 2007, 5:36:42 PM4/5/07
to
Hello:

How do I create a Modeless Dialog attached to a parent Modal Dialog?
When I Show() my Modeless dialog, it appears but can not be clicked
with the mouse or manipulated even if its raised in front of my other
window. I saw that the Find and Replace Dialog does what I want from
the same dialog, but how do I do this for myself?

wxMSW/wxMac 2.6.3


Brian Ray
br...@sent.com
http://kazavoo.com/blog

---------------------------------------------------------------------
To unsubscribe, e-mail: wx-users-u...@lists.wxwidgets.org
For additional commands, e-mail: wx-use...@lists.wxwidgets.org

Vadim Zeitlin

unread,
Apr 6, 2007, 3:28:46 PM4/6/07
to
On Thu, 5 Apr 2007 16:36:42 -0500 Brian Ray <br...@sent.com> wrote:

BR> How do I create a Modeless Dialog attached to a parent Modal Dialog?

This should work just fine under MSW, I'm surprised that you say it
doesn't. But while I don't know about Mac, I do know that this doesn't work
with wxGTK. Unfortunately we don't have any way to fix it: with wxGTK, the
modal dialog grabs all input.

Regards,
VZ

--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/

Brian Ray

unread,
Apr 22, 2007, 6:04:35 PM4/22/07
to

On Apr 6, 2007, at 2:28 PM, Vadim Zeitlin wrote:

> BR> How do I create a Modeless Dialog attached to a parent Modal
> Dialog?
>


> This should work just fine under MSW, I'm surprised that you say it
> doesn't. But while I don't know about Mac, I do know that this
> doesn't work
> with wxGTK. Unfortunately we don't have any way to fix it: with
> wxGTK, the
> modal dialog grabs all input.

OK, this seems to work now on MSW. I had to fully construct the
parent (and show it) before constructing the modal window to get it
to work properly.

Now, on the MAC, the modal window from the modeless window also shows
up and resizes fine; however all the controls appear to be disabled.
Has anybody got this to work on the Mac? I can see its getting some
messages because it appears to resize the controls within the dialog.
I do not have any clue why the controls appear disabled and can not
be clicked. I am sure the concept can work because I am replacing
functionality from PowerPlant. Although, I am unsure about our
program flow in wxMac. Stefan, what is the status of a modeless
dialog parented to a modal?

Does anybody else has a cleaver workaround even if its not cross
platform or pure wx?

This dialog will not go to wxGTK any time soon.

Dan Korn

unread,
Mar 28, 2008, 2:29:14 PM3/28/08
to
Anyone have any more ideas about this? I'm stuck on the same problem in
Mac with wxWidgets 2.8.7. The modeless dialog appears, but it doesn't
seem to handle most events.

Thanks,
Dan

Dan Korn

unread,
Apr 15, 2008, 10:58:39 PM4/15/08
to
Sorry to keep bringing up an old thread, but after much investigation,
I have some more insight into this issue. (I'm using wxWidgets 2.8.7
on Mac (Carbon), in Xcode 2.5, with wxMAC_USE_CORE_GRAPHICS set to 1.)

The issue has to do with the window classes being used to create the
two dialogs in question.

The crux of the problem is that the first dialog isn't actually a
proper OS X modal dialog at all. I'm calling wxDialog::ShowModal(),
and the dialog appears to be in an application-modal state, but if I
look in the Window list for the application from the dock, or use
Exposé (F10), my dialog is shown as a document window.

I traced this down to wxTopLevelWindowMac::DoMacCreateRealWindow(), in
src/mac/carbon/toplevel.cpp. It seems that all windows, except those
with the wxFRAME_TOOL_WINDOW, wxFRAME_DRAWER, or other similar flags,
are being created with kDocumentWindowClass.

This window class would seem to be fine for a monolithic application
in which wxWidgets is being used to create the main document windows
for the application. But I'm using wxWidgets in a plug-in (to a Cocoa
application, although it works mostly the same in a Carbon
application, at least under Leopard/Intel), so I don't want to be
creating more document windows for the application; I want to create
actual modal dialogs, with kMovableModalWindowClass. However,
wxWidgets doesn't seem to take this window class into account.

The one exception to this is in wxDialog::DoShowModal(), where if the
dialog doesn't have a parent window, then this gets called:

SetWindowGroupParent( windowGroup,
GetWindowGroupOfClass( kMovableModalWindowClass ) );

However, this DOES NOT WORK. The code isn't checking the return of
SetWindowGroupParent(); in fact, it's returning paramErr, at least for
me, in my plug-in, under Leopard. Actually, this makes sense from
reading the documentation of the function: specifically, for the first
parameter, inGroup, the Window Manager Reference states, "The
specified window group cannot contain any windows at the time of this
call." Or as the comments in MacWindows.h state,
"SetWindowGroupParent currently requires that the group have no
windows in it." Well, that's obviously not the case, since we're
already created the window and added it to the group, and we're
getting the parameter from a call to GetWindowGroup().

I'm not sure why the call to SetWindowGroupParent() is expected to
change the window class anyway. SetWindowGroup() might do that; I'm
not sure. I'm also not sure why the parentage of the window matters
here; AFAIK, a modal dialog should have kMovableModalWindowClass
regardless of its parent.

In order to actually make my dialog have kMovableModalWindowClass, I
have to call something like this in an override of
wxDialog::ShowModal():

OSStatus err = HIWindowChangeClass((WindowRef)m_macWindow,
kMovableModalWindowClass);

This seems to work, and the dialog doesn't appear as a document.
However, there's still a problem with the wxDialog::DoShowModal() code
if the dialog's parent is NULL. In that case, I've already changed
the window class, and SetWindowGroupParent() hangs, at least on
Leopard/Intel. I think this is also related to the issue of the
window group not being empty; in this case, though, both parameters to
SetWindowGroupParent() are the same, since the dialog is already a
member of that group. Certainly the function shouldn't hang in this
case (maybe that's a post for the Carbon-Dev list), but I'm pretty
sure this is the wrong function to be calling anyway.

Unfortunately, wxDialog::DoShowModal() is not a virtual function, so I
can't override it and change the default behavior without modifying
the wxWidgets source. I suppose I can override wxDialog::Show() and
have it call my own function that's similar to wxDialog::DoShowModal()
without the call to SetWindowGroupParent(). Or, I could create a
"dummy" parent window for the dialog, which has a NULL m_macWindow.
But that seems like a bit of a hack. Other suggestions are welcome.

Anyway, all of that is about the first dialog, the modal one. The
other half of this (welcome to the intermission of this email; go
ahead and get yourself a snack from the lobby) is about the modeless
dialog which I'm attempting to float on top of it.

If the modal dialog has the proper kMovableModalWindowClass, then any
"floating" modeless dialog with the wxFRAME_TOOL_WINDOW flag (such as
a wxFrame) WITHOUT the wxSTAY_ON_TOP flag is created with
kFloatingWindowClass. However, as the comments for this constant in
MacWindows.h specify, "A floating window is layered above all
application windows except for alert and modal windows." So, it's
stuck behind the modal dialog.

The solution here is to add the wxSTAY_ON_TOP flag, which causes the
dialog to be created with kUtilityWindowClass, which makes it show up
on top of my modal dialog. So we're done, right? Well, not quite.
To quote the MacWindows.h comments again, "A utility window is similar
to a floating window, but it floats above the windows of all
applications rather than just above the windows of the application
that creates it." So it stays on top even when I switch to another
application. This is clearly not what I want.

After some ill-fated experimentation with trying to detect when the
application is deactivated to manually hide the window, I found a very
simple way out of this dilemma: set the kWindowHideOnSuspendAttribute
bit. I can call this sometime after the creation of the window:

OSStatus err = ChangeWindowAttributes((WindowRef)m_macWindow,
kWindowHideOnSuspendAttribute, 0);

Voila! Now the windows' relative modalities seem to be as I want
them. The modal dialog is truly modal (and doesn't show up as a
document window), and all the other windows in the application are
disabled, except for my modeless dialog, which floats (ever so
lightly) on top of the modal one, and goes away when I switch to
another application. (There are some other issues with the title bar
and the close, minimize and zoom buttons, but I think those can be
solved with a few more calls to ChangeWindowAttributes().)

This is, of course, how it all works already on Windows without having
to make any of these "#ifdef __WXMAC__" changes.

It seems that the dialog code for wxMac, at least for Carbon, could be
updated to better set up the proper window classes (although I know
how difficult it can be to keep up with Apple's ever-changing
architectures, and I realize that wxMac has evolved over time like
anything else). Ideally, there should at least be an option to create
a window with kMovableModalWindowClass in the call to
CreateNewWindow() in wxTopLevelWindowMac::DoMacCreateRealWindow().
And there should be a way to specify the combination of
kUtilityWindowClass without kWindowHideOnSuspendAttribute. Maybe
wxFRAME_FLOAT_ON_PARENT should do this and wxSTAY_ON_TOP should still
make a "topmost to system" window. Or maybe this could just be
another flag, such as wxHIDE_ON_SUSPEND. It might be a Mac-only
thing, but there are other Mac-specific window styles supported by
wxMac, such as kDrawerWindowClass via wxFRAME_DRAWER.

And if you'll indulge me a bit of an aside (assuming anyone is still
reading), it also seems to me that on both Mac and Windows, the actual
creation of the dialog (with CreateNewWindow() or
CreateDialogIndirect(), respectively) could be deferred until either
Show() or ShowModal() is called. I'm not familiar with other
wxWidgets platforms, so I could be off-base here, but most other APIs
I've dealt with, such as MFC and PowerPlant, work like this. I know,
"Creation Is Resource Allocation," but the exact method of creating of
the WindowRef or HWND is at least somewhat dependent on first knowing
whether the dialog is going to be shown modally or not. Or at the
very least, it seems that much of the complexity of having to change
things later on could be removed with this kind of deferred creation.

Again, any comments are welcome.

Thanks for reading,
Dan

P.S. I found this patch very helpful for debugging under Xcode:
https://sourceforge.net/tracker/?func=detail&atid=309863&aid=1896410&group_id=9863
Any idea when will this be included in a stable release?

On Mar 28, 2008, at 1:29 PM, Dan Korn wrote:
> Anyone have any more ideas about this? I'm stuck on the same
> problem in
> Mac with wxWidgets 2.8.7. The modeless dialog appears, but it doesn't
> seem to handle most events.
>
> Thanks,
> Dan
>
> -----Original Message-----
> From: Brian Ray [mailto:br...@sent.com]
> Sent: Thursday, April 05, 2007 4:37 PM
> To: wx-u...@lists.wxwidgets.org
> Subject: Modeless from Modal wxDialog
>

0 new messages