Search code examples
c++wxwidgets

How to forward events in wxWidgets?


I have a window with a GLCanvas and scroll bars, I want the canvas to capture scroll events and forward them to the scroll bars, which are then used to position the 'camera.' So I've done this:

MainWindow::MainWindow(wxWindow* parent,wxWindowID id)
{
//...
   GlCanvas->Connect(ID_GLCANVAS1, wxEVT_MOUSEWHEEL, (wxObjectEventFunction)&MainWindow::onMouseWheel, 0L, this);
}

void MainWindow::onMouseWheel(wxMouseEvent & event)
{
    if(event.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL)
    {
        std::cerr << "vertical scroll" << std::endl;
        verticalScroll->ProcessWindowEvent(event);
    }
    else
    {
        std::cerr << "horizontal scroll" << std::endl;
        horizontalScroll->ProcessWindowEvent(event);
    }
}

However, this isn't doing anything aside from the printouts. What do I do to get the scrollbars to process the wheel events?

============== Solution ==============

void MainWindow::onMouseWheel(wxMouseEvent & event)
{
    event.Skip();
    double rotation = ((double) event.GetWheelRotation()) / event.GetWheelDelta();

    wxScrollBar * scrollBar;
    double * delta;

    if(event.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL)
    {
        scrollBar = verticalScroll; 
        delta     = &verticalDelta;
        rotation *= -1;
    }
    else
    {
        scrollBar = horizontalScroll;
        delta     = &horizontalDelta;
    }

    if(event.IsPageScroll())
    {
        rotation *= scrollBar->GetPageSize();
    }
    else
    {
        if(event.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL)
        {
            rotation *= event.GetLinesPerAction();
        }
        else
        {
            rotation *= event.GetColumnsPerAction();
        }
    }

    *delta += rotation;

    int scroll = scrollBar->GetThumbPosition();
    int ds = (int) *delta;

    *delta -= ds;
    scroll += ds;

    if(scroll < 0)
    {
        *delta = 0;
        scroll = 0;
    }
    else if(scroll > scrollBar->GetRange())
    {
        *delta = 0;
        scroll = scrollBar->GetRange();
    }

    scrollBar->SetThumbPosition(scroll);
}

Solution

  • You can't forward wx events to native controls, if you think about it, how would it be possible for this to work when the native controls don't have any idea about wx? Native controls generate native events which are then translated to wx events and given to your application, but nothing happens, or even can be really done, in the other direction.

    In this particular case you can (relatively) easily translate scroll events to the calls to ScrollLines(), ScrollPages() or just SetScrollPos(). This will allow you to control another window scrolling using the same scrollbar.

    Do not forget to call Skip() in the original handler to let the window being scrolled from actually scrolling too.