ravenspoint
ravenspoint

Reputation: 20615

Propagate wxWindows mouse events upwards

How can I arrange to propagate wxWindows right click mouse events up to the parent window from static text controls?

Motivation:

My GUI looks like this

enter image description here

Each box ( wxPanel ) represents a 'device' I want a right click on the box to pop-up a dialog to edit the device info.

This works fine so long as the user clicks on the background of the panels. If the click falls on any of the text ( wxStaticText ), then the panel never sees the click event. Since the text covers a big fraction of the device panels, this is unsatisfactory.

I understand the cause is that mouse events do not inherit from wxCommandEvent. The documentation states: by default only wxCommandEvent-derived events are set to propagate. But I do not see how to change the default behaviour so that the right click events are set to propagate. It seems that this should be possible because the docs also say other events can be propagated as well because the event handling code uses wxEvent::ShouldPropagate() to check whether an event should be propagated.

Maybe I need to need to specialize the wxStaticText class, so that it 'handles' the right click event, calling wxEvent::ResumePropagation( 1 ) on it?

Here is the device panel constructor

cDevicePanel::cDevicePanel( wxWindow* parent, devicify::cDevice& device )
    : wxPanel( parent,-1,wxDefaultPosition,wxSize(200,110),wxBORDER_RAISED )
    , myDevice( device )
{
    switch( device.myMatch )
    {
    case devicify::cDevice::eMatch::OK:
        SetBackgroundColour( wxColor(120,180,255) );
        break;
    case devicify::cDevice::eMatch::noDevice:
        SetBackgroundColour( wxColor(255,180,120) );
        break;
    case devicify::cDevice::eMatch::noDetails:
        SetBackgroundColour( wxColor(255,255,0) );
        break;
    }
    myName = new wxStaticText(this,-1,device.myName,wxPoint(10,10));
    myPower = new wxStaticText(this,-1,
                               wxString::Format("Power: %f kw",myDevice.myPower),
                               wxPoint(20,30));
    myEnergy = new wxStaticText(this,-1,
                                wxString::Format("Energy: %f kwh",myDevice.myEnergy),
                                wxPoint(20,50));
    myButton = new wxButton(this,ButtonDeviceOnOff,"OFF",wxPoint(10,70),wxSize(40,20));
    Bind(wxEVT_BUTTON,&cDevicePanel::OnSwitch, this,ButtonDeviceOnOff );
    new wxButton(this,ButtonDevicePlot,"Plot",wxPoint(90,70),wxSize(40,20));
    Bind(wxEVT_BUTTON,&cDevicePanel::OnPlot, this,ButtonDevicePlot );
    Bind(wxEVT_RIGHT_UP,&cDevicePanel::OnRightClick, this );
}

Upvotes: 0

Views: 474

Answers (2)

ravenspoint
ravenspoint

Reputation: 20615

As VZ suggests, it is easiest to ignore propagation issues and to solve the problem using bind.

Important:

  • Call bind as a member of the child window

  • Pass pointer to parent window as parameter to bind

So, my constructor looks like this:

myName = new wxStaticText(this,-1,device.myName,wxPoint(10,10));
myName->Bind( wxEVT_RIGHT_DOWN, &cDevicePanel::OnRightClick, this );
myPower = new wxStaticText(this,-1,
                           wxString::Format("Power: %f kw",myDevice.myPower),
                           wxPoint(20,30));
myPower->Bind( wxEVT_RIGHT_DOWN, &cDevicePanel::OnRightClick, this );

myEnergy = new wxStaticText(this,-1,
                            wxString::Format("Energy: %f kwh",myDevice.myEnergy),
                            wxPoint(20,50));
myEnergy->Bind( wxEVT_RIGHT_DOWN, &cDevicePanel::OnRightClick, this );

// right clicks on panel background
Bind(wxEVT_RIGHT_DOWN,&cDevicePanel::OnRightClick, this );

Upvotes: 0

VZ.
VZ.

Reputation: 22753

All this propagation stuff predates Bind() and maybe even Connect(). Now that we have those, the simplest solution is to just bind to the event you're interested in in each of the controls. It does mean that you need to do it for all the controls, but it's simple to iterate over all the children and you would need to do something for all windows with any other solution anyhow.

The "other events can be propagated" refers to custom events you could define, I think. I.e. if you're defining a new event class, you could set m_propagationLevel to wxEVENT_PROPAGATE_MAX for it to make it behave as wxCommandEvent.

Upvotes: 1

Related Questions