如何在 wxWidgets 中转发事件

How to forward events in wxWidgets?

本文关键字:转发 事件 wxWidgets      更新时间:2023-10-16

我有一个带有GLCanvas和滚动条的窗口,我希望画布捕获滚动事件并将它们转发到滚动条,然后用于定位"相机"。所以我这样做了:

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);
    }
}

但是,除了打印输出之外,这没有任何作用。如何让滚动条处理滚轮事件?

====

========== 解决方案 ===============
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);
}

你不能将wx事件转发到本机控件,如果您考虑一下,当本机控件对wx一无所知时,这怎么可能工作?本机控件生成本机事件,然后将其转换为 wx 事件并提供给应用程序,但在另一个方向上没有任何反应,甚至无法真正完成。

在这种特殊情况下,您可以(相对)轻松地将滚动事件转换为对ScrollLines()ScrollPages()或仅SetScrollPos()的调用。这将允许您使用相同的滚动条控制另一个窗口滚动。

不要忘记在原始处理程序中调用Skip(),以使正在滚动的窗口也不再实际滚动。

你需要conect(),或者更好的bind(),如果你的wx版本允许的话,一个wxScrollEvent

如果选择使用 wxEVT_COMMAND_SCROLLwxEVT_SCROLL 处理所有滚动事件,则可以从处理程序函数中的 event 参数获取事件类型。

校正:

目前(wx 3.1)仍然没有wxEVT_COMMAND_SCROLL也没有wxEVT_SCROLL。只有部分定义(向上翻页、重磅跟踪等)。这似乎是一个错误。但是您可以以旧的BEGIN_EVENT_TABLE/END_EVENT_TABLE方式使用EVT_SCROLL。