Shady Atef
Shady Atef

Reputation: 2401

How to programmatically close wxMenu used as popup menu via `wxWindow::PopupMenu` in wxWidgets?

I have a set of instances of plotting view that's added/removed dynamically according to incoming signals from tcp port from another process.

In each instance, the user can right click to open a popup menu, invoked via wxWindow::PopupMenu.

If the plotting view instance is to got shutted-down dynamically while the popup menu is visible, the view instance window is closed while the popup menu is still floating. Then any GUI action crashes the application.

I've been going through the APIs for wxWidgets to find a way to programmatically close the popup menu in the plotting view destructor, but with no-luck.

I found this forum post suggesting it's an impossible thing to close the popup menu programmatically. But it's too old, so not sure if it's still valid assumption.


Here are the trials that failed till now :

  1. Trying to call SetFocus and SetFocusFromKbd on the plotting view as a way to move focus.
  2. Generating mouse left click event and send it to the popup menu.
  3. Generating a keyboard event and send it to the popup menu.

    PlottingView::~PlottingView()
    {
        cout << "Sending wxMouseEvent to the popup menu" << endl;
        wxMouseEvent e(wxEVT_LEFT_UP);
        this->GetPopupMenu()->ProcessEvent(e);
    
        wxKeyEvent ke(wxEVT_CHAR);
        ke.m_keyCode = WXK_DOWN;
        this->GetPopupMenu()->ProcessEvent(ke);
    
        ke.m_keyCode = WXK_RETURN;
        this->GetPopupMenu()->ProcessEvent(ke);
    
    // the rest of the destruction
    }
    

So I will appreciate any idea to programmatically close this popup menu.


Platform:
CentOS: 6.7
wxWidgets 2.8.12
G++: 4.3.3


Edit #1

Note: For commenters and answers suggesting upgrading the wxWidgets version, it's a debate in my team for everyday. But the answer is still no.

Most of the trials has failed. But I found a workaround to stop crashing but the popup menu don't close.

The solution was to nullify the following members using their setters, so the menu callback won't access them.

this->GetPopupMenu()->SetInvokingWindow(NULL);
this->GetPopupMenu()->SetEventHandler(NULL);

Upvotes: 1

Views: 505

Answers (1)

VZ.
VZ.

Reputation: 22688

The best is probably to delay destroying the underlying window until PopupMenu() returns. As it is, your program logic is very convoluted because you're dispatching the event which results in closing of the window from inside PopupMenu() function and this just can't end well, even if you could use wxUIActionSimulator to close the menu (but you definitely should consider upgrading your 15 year old wxWidgets version in any case).

Upvotes: 2

Related Questions