Can't get menu title for popup menus in Windows

I've got a program that I created for both Windows and Linux. It
works great under Linux, but I'm having trouble in Windows that I
can't seem to figure out. In one window I have a context menu (right
click menu) with a couple submenu's. When creating the menu I use the
call SetTitle on the submenu's. Here's what I have for my menu event:

    def OnPopupMenu(self, evt):
        menu = evt.GetEventObject()
        title = menu.GetTitle()
        print "Title = " + title
        item = evt.GetId()
        text = menu.GetLabel(item)
        print "Menu item selected: " + text
        if title == 'Menu1':
            self.DoSomething1(text)
        if title == 'Menu2':
            self.DoSomething2(text)
        evt.Skip()

On Linux things work as expected. For title I get either "Menu1" or
"Menu2" depending on which submenu the item was selected from.
However, on Windows the title is always an empty string. Is this a wx
issue or is it a Windows issue? Does anyone know any workarounds?

Thanks,

Isaac

I've never tried this, although I suspect it's a Windows artifact that
wx should probably try to work around. The reason why I've never tried
it, though, is that I bind the submenus to different event handlers by
using different IDs instead of doing secondary dispatch. You might try
taking that approach.

···

On 2/2/07, Isaac Wagner <geekyisaac@gmail.com> wrote:

I've got a program that I created for both Windows and Linux. It
works great under Linux, but I'm having trouble in Windows that I
can't seem to figure out. In one window I have a context menu (right
click menu) with a couple submenu's. When creating the menu I use the
call SetTitle on the submenu's. Here's what I have for my menu event:

    def OnPopupMenu(self, evt):
        menu = evt.GetEventObject()
        title = menu.GetTitle()
        print "Title = " + title
        item = evt.GetId()
        text = menu.GetLabel(item)
        print "Menu item selected: " + text
        if title == 'Menu1':
            self.DoSomething1(text)
        if title == 'Menu2':
            self.DoSomething2(text)
        evt.Skip()

On Linux things work as expected. For title I get either "Menu1" or
"Menu2" depending on which submenu the item was selected from.
However, on Windows the title is always an empty string. Is this a wx
issue or is it a Windows issue? Does anyone know any workarounds?

Unfortunately, my menus are generated from info collected at runtime,
so I am never sure what the menu title will end up being. That makes
it hard to create different handlers for the different menus.

···

On 2/2/07, Chris Mellon <arkanes@gmail.com> wrote:

On 2/2/07, Isaac Wagner <geekyisaac@gmail.com> wrote:
> I've got a program that I created for both Windows and Linux. It
> works great under Linux, but I'm having trouble in Windows that I
> can't seem to figure out. In one window I have a context menu (right
> click menu) with a couple submenu's. When creating the menu I use the
> call SetTitle on the submenu's. Here's what I have for my menu event:
>
> def OnPopupMenu(self, evt):
> menu = evt.GetEventObject()
> title = menu.GetTitle()
> print "Title = " + title
> item = evt.GetId()
> text = menu.GetLabel(item)
> print "Menu item selected: " + text
> if title == 'Menu1':
> self.DoSomething1(text)
> if title == 'Menu2':
> self.DoSomething2(text)
> evt.Skip()
>
> On Linux things work as expected. For title I get either "Menu1" or
> "Menu2" depending on which submenu the item was selected from.
> However, on Windows the title is always an empty string. Is this a wx
> issue or is it a Windows issue? Does anyone know any workarounds?
>

I've never tried this, although I suspect it's a Windows artifact that
wx should probably try to work around. The reason why I've never tried
it, though, is that I bind the submenus to different event handlers by
using different IDs instead of doing secondary dispatch. You might try
taking that approach.

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

You already have different handlers for different menus - that is
exactly what you're doing in your sample code. You're just doing
secondary dispatch - you have one menu event handler and you are
inspecting the menu title to determine where to go next. You can bind
the IDs directly and skip the seconday dispatch. Here's a sample:

import wx
class TFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)
        menu = wx.Menu("File")
        menu.Append(wx.NewId(), "Item")

        #submenu one
        sm = wx.Menu("Submenu1")
        id1, id2 = wx.NewId(), wx.NewId()
        sm.Append(id1, "Subitem 1")
        sm.Append(id2, "Subitem 2")
        self.Bind(wx.EVT_MENU, self.OnSubmenuOne, id=id1)
        self.Bind(wx.EVT_MENU, self.OnSubmenuOne, id=id2)
        menu.AppendMenu(wx.NewId(), "Submenu One", sm)

        sm = wx.Menu("Submenu2")
        id1, id2 = wx.NewId(), wx.NewId()
        sm.Append(id1, "Subitem 1")
        sm.Append(id2, "Subitem 2")
        self.Bind(wx.EVT_MENU, self.OnSubmenuTwo, id=id1)
        self.Bind(wx.EVT_MENU, self.OnSubmenuTwo, id=id2)
        menu.AppendMenu(wx.NewId(), "Submenu Two", sm)

        mb = wx.MenuBar()
        mb.Append(menu, "File")
        self.SetMenuBar(mb)

    def OnSubmenuOne(self, evt):
        print "Do something one"
    def OnSubmenuTwo(self, evt):
        print "Do something two"

if __name__ == '__main__':
    app = wx.App(False)
    f = TFrame(None)
    f.Show()
    app.MainLoop()

···

On 2/2/07, Isaac Wagner <geekyisaac@gmail.com> wrote:

Unfortunately, my menus are generated from info collected at runtime,
so I am never sure what the menu title will end up being. That makes
it hard to create different handlers for the different menus.

Chris Mellon wrote:

On Linux things work as expected. For title I get either "Menu1" or
"Menu2" depending on which submenu the item was selected from.
However, on Windows the title is always an empty string. Is this a wx
issue or is it a Windows issue? Does anyone know any workarounds?

I've never tried this, although I suspect it's a Windows artifact that
wx should probably try to work around. The reason why I've never tried
it, though, is that I bind the submenus to different event handlers by
using different IDs instead of doing secondary dispatch. You might try
taking that approach.

On Windows event.GetEventObject is returning the parent menu, not the submenu. It looks like it is just due to the way that menus are sent in Windows. The command event comes to the window and wx just checks if it was due to there being a popup menu active and if so it sets the popup as the event object.

A workaround would be to use the event ID to get the wx.MenuItem, then you can use GetMenu to find the (sub)menu it belongs to. But Chris's suggestion of binding the events directly to their handlers as you create the items is the better way to solve this problem.

···

On 2/2/07, Isaac Wagner <geekyisaac@gmail.com> wrote:

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

Sorry if I am being unclear. I've been programming all day and my
brain is having a hard time speaking human. :slight_smile:

Normally, I would do the menus as you suggest. However, this
situation does not lend itself well to that solution. Here's
basically the menu structure I have:

SomeText->
        Option 1
        Option 2
        Option 3
ItemA->
        Option 1
        Option 2
        Option 3
SomethingElse->
        Option 1
        Option 2
        Option 3

Information collected from runtime determines what the particular
submenu is called, in this case SomeText, ItemA, and SomethingElse.
However, the items on the submenus are always the same, in this case
Option 1, Option 2, Option 3.

Because the Submenus are generated from runtime info I have no idea
what they are ahead of time. This is why I am doing a secondary
dispatch. I need to determine which submenu the particular item
belongs to.

Thanks for the suggestions.

-Isaac

···

On 2/2/07, Chris Mellon <arkanes@gmail.com> wrote:

On 2/2/07, Isaac Wagner <geekyisaac@gmail.com> wrote:
> Unfortunately, my menus are generated from info collected at runtime,
> so I am never sure what the menu title will end up being. That makes
> it hard to create different handlers for the different menus.
>

You already have different handlers for different menus - that is
exactly what you're doing in your sample code. You're just doing
secondary dispatch - you have one menu event handler and you are
inspecting the menu title to determine where to go next. You can bind
the IDs directly and skip the seconday dispatch. Here's a sample:

import wx
class TFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent)
        menu = wx.Menu("File")
        menu.Append(wx.NewId(), "Item")

        #submenu one
        sm = wx.Menu("Submenu1")
        id1, id2 = wx.NewId(), wx.NewId()
        sm.Append(id1, "Subitem 1")
        sm.Append(id2, "Subitem 2")
        self.Bind(wx.EVT_MENU, self.OnSubmenuOne, id=id1)
        self.Bind(wx.EVT_MENU, self.OnSubmenuOne, id=id2)
        menu.AppendMenu(wx.NewId(), "Submenu One", sm)

        sm = wx.Menu("Submenu2")
        id1, id2 = wx.NewId(), wx.NewId()
        sm.Append(id1, "Subitem 1")
        sm.Append(id2, "Subitem 2")
        self.Bind(wx.EVT_MENU, self.OnSubmenuTwo, id=id1)
        self.Bind(wx.EVT_MENU, self.OnSubmenuTwo, id=id2)
        menu.AppendMenu(wx.NewId(), "Submenu Two", sm)

        mb = wx.MenuBar()
        mb.Append(menu, "File")
        self.SetMenuBar(mb)

    def OnSubmenuOne(self, evt):
        print "Do something one"
    def OnSubmenuTwo(self, evt):
        print "Do something two"

if __name__ == '__main__':
    app = wx.App(False)
    f = TFrame(None)
    f.Show()
    app.MainLoop()

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org

Thanks! That works perfectly.

···

On 2/2/07, Robin Dunn <robin@alldunn.com> wrote:

Chris Mellon wrote:
> On 2/2/07, Isaac Wagner <geekyisaac@gmail.com> wrote:

>> On Linux things work as expected. For title I get either "Menu1" or
>> "Menu2" depending on which submenu the item was selected from.
>> However, on Windows the title is always an empty string. Is this a wx
>> issue or is it a Windows issue? Does anyone know any workarounds?
>>
>
> I've never tried this, although I suspect it's a Windows artifact that
> wx should probably try to work around. The reason why I've never tried
> it, though, is that I bind the submenus to different event handlers by
> using different IDs instead of doing secondary dispatch. You might try
> taking that approach.

On Windows event.GetEventObject is returning the parent menu, not the
submenu. It looks like it is just due to the way that menus are sent in
Windows. The command event comes to the window and wx just checks if it
was due to there being a popup menu active and if so it sets the popup
as the event object.

A workaround would be to use the event ID to get the wx.MenuItem, then
you can use GetMenu to find the (sub)menu it belongs to. But Chris's
suggestion of binding the events directly to their handlers as you
create the items is the better way to solve this problem.

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

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwidgets.org
For additional commands, e-mail: wxPython-users-help@lists.wxwidgets.org