wxMessageDialog Modality

Okay, maybe I'm just confused here, but I have found something that I think
is rather weird. I've included code to demonstrate the problem. I'm on
Win2k using wxPython 2.5.2.8.

My demo code opens two frames. In one of those frames, there is a button
that causes a modal wxMessageDialog box. However, it appears that the
wxMessageDialog is only modal to that frame, as you can clearly click on the
other frame and choose an item from its menu, such as the one that closes
the program.

Am I wrong to expect the wxMessageDialog to be modal to the application
rather than to the frame? Can anyone tell me what I need to change to make
the wxMessageDialog be modal to the application?

Obviously, the attached example is trivial, but Transana has multiple
windows, and I'm finding that certain error messages which should be modal
to the application are ending up being modal only to the parent frame. Yet
other dialog boxes I've written myself are successfully modal to the whole
application. Do I have to write my own wxMessageDialog class in order to
fix this problem? That just doesn't make sense to me.

David K. Woods
Transana Lead Developer (http://www.tranana.org)
Wisconsin Center for Education Research
University of Wisconsin, Madison

  "Quick. Cheap. Good. Pick two."

import wx

MENU_FILE_EXIT = wx.NewId()
BUTTON_ID = wx.NewId()

class MainWindow(wx.Frame):
   """ This window displays a variety of GUI Widgets. """
   def __init__(self,parent,id,title):
       self.frame1 = wx.Frame(parent,-4, title, size = (300,300),
pos=(10,10), style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
       self.frame2 = wx.Frame(parent,-4, title, size = (300,300), pos=(10,
320), style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
       self.frame1.SetBackgroundColour(wx.WHITE)
       self.frame2.SetBackgroundColour(wx.WHITE)

   def Setup(self):
       # Menu Bar
       # Create a MenuBar
       menuBar = wx.MenuBar()
       # Build a Menu Object to go into the Menu Bar
       menu1 = wx.Menu()
       menu1.Append(MENU_FILE_EXIT, "E&xit", "Quit Application")
       #Place the Menu Item in the Menu Bar
       menuBar.Append(menu1, "&File")

       self.frame1.SetMenuBar(menuBar)
       #Define Events for the Menu Items
       wx.EVT_MENU(self.frame1, MENU_FILE_EXIT, self.CloseWindow)

       # Status Bar
       self.frame1.CreateStatusBar()
       self.frame1.SetStatusText("Status Bar")
       self.frame2.Show(True)
       self.frame1.Show(True)

       # Button for Window 2
       btn1 = wx.Button(self.frame2, BUTTON_ID, "Push Me!", (135, 140), (60,
20))
       wx.EVT_BUTTON(self.frame2, BUTTON_ID, self.OnButtonPress)

   def CloseWindow(self, event):
       self.frame1.Close()
       self.frame2.Close()

   def OnButtonPress(self, event):
       dlg = wx.MessageDialog(self.frame2, "This is a Modal Dialog.")
       dlg.ShowModal()
       dlg.Destroy()

class MyApp(wx.App):
   def OnInit(self):
      frame = MainWindow(None, -1, "MiniApp")
      frame.Setup()
      self.SetTopWindow(frame.frame1)
      return True

app = MyApp(0)
app.MainLoop()

David Woods wrote:

Okay, maybe I'm just confused here, but I have found something that I think
is rather weird. I've included code to demonstrate the problem. I'm on
Win2k using wxPython 2.5.2.8.

My demo code opens two frames. In one of those frames, there is a button
that causes a modal wxMessageDialog box. However, it appears that the
wxMessageDialog is only modal to that frame, as you can clearly click on the
other frame and choose an item from its menu, such as the one that closes
the program.

Am I wrong to expect the wxMessageDialog to be modal to the application
rather than to the frame? Can anyone tell me what I need to change to make
the wxMessageDialog be modal to the application?

Obviously, the attached example is trivial, but Transana has multiple
windows, and I'm finding that certain error messages which should be modal
to the application are ending up being modal only to the parent frame. Yet
other dialog boxes I've written myself are successfully modal to the whole
application.

Keep in mind that the wxMessageDialog is just a wrapper around the win32 MessageBox API so we are somewhat at the mercy of how it behaves. wxWidgets does use the MB_APPLMODAL style when calling MessageBox, but the description of what that really means is a little ambiguous. From MSDN:

"""
MB_APPLMODAL The user must respond to the message box before continuing work in the current window. However, the user can move to the windows of other applications and work in those windows.
"""

So it's not real clear if it is really modal to the whole application or just the current window.

Do I have to write my own wxMessageDialog class in order to
fix this problem? That just doesn't make sense to me.

That's what I would do. You could use the code for the generic message dialog (used on platforms other than MSW and Mac) as a starting point:

http://cvs.wxwidgets.org/viewcvs.cgi/wxWidgets/src/generic/msgdlgg.cpp

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!