Advise: Best handle wxMenu/accelerator event?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

Re: Advise: Best handle wxMenu/accelerator event?

Post by Mick P. »

DavidHart wrote: Sat Aug 31, 2019 6:43 pm No need to assume, just look at the doc
I wish the documentation were clear, then I would be here less. I couldn't find wxID_ANY in the Bind or Connect documentation. I don't doubt it's somewhere else, but it belongs alongside the parameters.
Shouldn't that be:
fr->Bind(wxEVT_COMMAND_MENU_SELECTED, &evt_command);
No (oops, see edit) the function is not a method. The event passes the frame to the procedure. But the procedure is uncalled when the menus and toolbars are selected. I can't think of anything that would short-circuit them since it's cut and dry that the menu is pressed, etc. I would think there isn't another event channel that could step on the toes of those events. I guess, next I have to try to locate the WM_COMMAND processing code in wxWidgets and see what it's up to.

EDITED: Oops, well the & is optional, and Bind works fine this way for other events. Sometimes with templates it's necessary.
ONEEYEMAN wrote: Sat Aug 31, 2019 10:37 pm Hi,
Or more precisely,

Code: Select all

fr->Bind(wxEVT_COMMAND_MENU_SELECTED, &<ClassName>::evt_command, this);
where this is an eventSink parameter (and very important one).

Thank you.
I guess I thought your suggestion was the same as David's. Anyway, the Bind call is identical to several other event bindings that ARE working, so the problem is elsewhere.
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

Re: Advise: Best handle wxMenu/accelerator event?

Post by Mick P. »

Here is the problem. On Windows menus don't have parents. So wxWidgets has a requirement that every submenu must be duplicated to appear in another parent menu. This is another design problem to workaround for me. It would be better if wxWidgets managed this for systems that require duplicating menus (GTK?) but I don't know... this is a whole new can of worms. It would be more logical for WM_COMMAND to forward the window.

Code: Select all

wxWindow *wxMenuBase::GetWindow() const
{
    // only the top level menus have non-NULL invoking window or a pointer to
    // the menu bar so recurse upwards until we find it
    const wxMenuBase *menu = this;
    while ( menu->GetParent() )
    {
        menu = menu->GetParent();
    }

    return menu->GetMenuBar() ? menu->GetMenuBar()->GetFrame()
                              : menu->GetInvokingWindow();
}
UPDATE: wxEVT_COMMAND_TOOL_CLICKED is working now. It's possible it was before also, when it was bound to a frame, though I'm sure I set a breakpoint, it's possible I compiled the application instead of the UI module. (It seemed to not be working because an element wasn't repainting.)
Last edited by Mick P. on Sun Sep 01, 2019 11:21 am, edited 1 time in total.
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

Re: Advise: Best handle wxMenu/accelerator event?

Post by Mick P. »

So far I devised a trick that works with Windows (untested elsewhere) that makes the menus reusable. wxWidgets should work this way itself, since duplicating menus is a headache.

This is a replacement for wxMenuBar. The menu commands have to be processed at the wxApp level. There may be an "Insert" method also that this class doesn't implement. I assume it's "virtual" if so.

Code: Select all

	//Unlike Windows wxWidgets menus have strict parents and so
	//cannot appear undere more than one menu. This is a hack to
	//make them reusable and work like GLUT, that is like Windows.
	struct menubar : wxMenuBar
	{
		virtual ~menubar()
		{
			m_menus.clear();
		}
		virtual bool Append(wxMenu *menu, const wxString& title)
		{
			menu->wxMenuBase::SetTitle(title);
			m_menus.Append(menu);
			//Don't attach so that the parent doesn't own menu.
			//menu->Attach(this);
			return true;
		}
	};
Note, wxWidgets has wxMenuInvokingWindowSetter and wxMenuBase::SetInvokingWindow that could be used as default for menus of this type. But it's not possible to use since A) it has tight assertions, and B) I still couldn't get it to work by setting the protected member that it sets inside of a MENU_OPEN event.

Currently I don't have a good system to determine the window. I'm using wxApp::GetTopWindow, but that may be completely inappropriate. A foreground-window API would do the trick, but I don't know one.

I now have two complaints to file with the tracker. Maybe I can package these into one feature request.
DavidHart
Site Admin
Site Admin
Posts: 4254
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: Advise: Best handle wxMenu/accelerator event?

Post by DavidHart »

No need to assume, just look at the doc

I wish the documentation were clear, then I would be here less. I couldn't find wxID_ANY in the Bind or Connect documentation. I don't doubt it's somewhere else, but it belongs alongside the parameters.
Where were you looking? A click on the above link would have shown you:

Code: Select all

template<typename EventTag , typename Functor >
void wxEvtHandler::Bind	(const EventTag & eventType,
		Functor  functor,
		int  id = wxID_ANY,
		int  lastId = wxID_ANY,
		wxObject * userData = NULL 
	) 	
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

Re: Advise: Best handle wxMenu/accelerator event?

Post by Mick P. »

DavidHart wrote: Sun Sep 01, 2019 9:16 am
No need to assume, just look at the doc

I wish the documentation were clear, then I would be here less. I couldn't find wxID_ANY in the Bind or Connect documentation. I don't doubt it's somewhere else, but it belongs alongside the parameters.
Where were you looking? A click on the above link would have shown you:

Code: Select all

template<typename EventTag , typename Functor >
void wxEvtHandler::Bind	(const EventTag & eventType,
		Functor  functor,
		int  id = wxID_ANY,
		int  lastId = wxID_ANY,
		wxObject * userData = NULL 
	) 	
Sorry, I think you mean the defaults are wxID_ANY? But consider that the semantics of what wxID_ANY mean are unspecified. The values are in the code, the semantics aren't. It's not important, at the time I did not test it with say 0,65535.
DavidHart
Site Admin
Site Admin
Posts: 4254
Joined: Thu Jan 12, 2006 6:23 pm
Location: IoW, UK

Re: Advise: Best handle wxMenu/accelerator event?

Post by DavidHart »

Sorry, I think you mean the defaults are wxID_ANY?
Yes.
But consider that the semantics of what wxID_ANY mean are unspecified.
They are specified elsewhere: in the Events and Event Handling overview, which you should also read.
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

Re: Advise: Best handle wxMenu/accelerator event?

Post by Mick P. »

Just posting to report wxEVT_COMMAND_TOOL_CLICKED is working, at least at the wxApp level. I think it may have been working before except for some accidents. I updated an earlier post with extra personal details.

EDITED: Also, hotkeys work for the nonstandard menus. (The toolbar's do too.)
DavidHart wrote: Sun Sep 01, 2019 11:18 am
Sorry, I think you mean the defaults are wxID_ANY?
Yes.
But consider that the semantics of what wxID_ANY mean are unspecified.
They are specified elsewhere: in the Events and Event Handling overview, which you should also read.
I've read it several times. The nature of programming is, you need parameters documented at the site of use, but it's reasonable to assume that's what wxID_ANY means. Programmers don't memorize manuals. If I want to know what CreateFile (Win32) does I go to CreateFile's documentation.
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Advise: Best handle wxMenu/accelerator event?

Post by ONEEYEMAN »

Hi,
Keep in mind that handling the menu should be handled at the frame level and not at wxApp level.

Also, you should check the menu sample - remember samples are you first reproduction step if something is not working.

Thank you.
Mick P.
Earned some good credits
Earned some good credits
Posts: 145
Joined: Thu Jun 06, 2019 3:41 am
Contact:

Re: Advise: Best handle wxMenu/accelerator event?

Post by Mick P. »

ONEEYEMAN wrote: Sun Sep 01, 2019 2:01 pm Hi,
Keep in mind that handling the menu should be handled at the frame level and not at wxApp level.
It's working at wxApp level. In this case that's all that can work. The ports would have to all be upgraded to use setInvokingWindow to make it work otherwise, or pass the window directly to the event invocation code.
ONEEYEMAN wrote: Sun Sep 01, 2019 2:01 pm Also, you should check the menu sample - remember samples are you first reproduction step if something is not working.

Thank you.
I've never worked from samples in my life, but that would be easier if the samples were linked into the documentation. Not that it matters since an example doubtful exists in this instance.Unless there is a blessed way to override wxMenuBar to get the desired behavior that has its own example. (Nor likely for the OP.)
ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 7477
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Advise: Best handle wxMenu/accelerator event?

Post by ONEEYEMAN »

Hi,
Just open the samples folder.
If you look how it is structured, I believe you will know which sample corresponds to which control. Unless of course you are not understand the basic programming paradigm, that if you have a problem with menu you should look on the menu implementation...

Thank you.
Post Reply