wxWidgets中如何转发事件?
How to forward events in wxWidgets?
我有一个带有 GLCanvas 和滚动条的 window,我希望 canvas 捕获滚动事件并将它们转发到滚动条,然后用于定位 'camera.' 所以我这样做了:
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);
}
你需要 conect()
,如果你的 wx 版本允许,最好 bind()
,一个 wxScrollEvent
如果您选择使用wxEVT_COMMAND_SCROLL或wxEVT_SCROLL[=24=来处理所有滚动事件] 然后你可以从处理函数中的事件参数中获取事件类型。
更正:
目前 (wx 3.1) 仍然没有 wxEVT_COMMAND_SCROLL 也没有 wxEVT_SCROLL。只有部分定义(向上翻页、thumtrack 等)。这似乎是一个错误。但是你可以用旧的 BEGIN_EVENT_TABLE/END_EVENT_TABLE 方式使用 EVT_SCROLL。
你不能把wx事件转发给native控件,你想想,native控件对wx一点概念都没有,这怎么行得通?本机控件生成本机事件,然后将其转换为 wx 事件并提供给您的应用程序,但在另一个方向上没有任何反应,甚至无法真正完成。
在这种特殊情况下,您可以(相对)轻松地将滚动事件转换为对 ScrollLines()
、ScrollPages()
或 SetScrollPos()
的调用。这将允许您使用相同的滚动条控制另一个 window 滚动。
不要不要忘记在原始处理程序中调用Skip()
,让window从实际滚动中滚动。
我有一个带有 GLCanvas 和滚动条的 window,我希望 canvas 捕获滚动事件并将它们转发到滚动条,然后用于定位 'camera.' 所以我这样做了:
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);
}
你需要 conect()
,如果你的 wx 版本允许,最好 bind()
,一个 wxScrollEvent
如果您选择使用wxEVT_COMMAND_SCROLL或wxEVT_SCROLL[=24=来处理所有滚动事件] 然后你可以从处理函数中的事件参数中获取事件类型。
更正:
目前 (wx 3.1) 仍然没有 wxEVT_COMMAND_SCROLL 也没有 wxEVT_SCROLL。只有部分定义(向上翻页、thumtrack 等)。这似乎是一个错误。但是你可以用旧的 BEGIN_EVENT_TABLE/END_EVENT_TABLE 方式使用 EVT_SCROLL。
你不能把wx事件转发给native控件,你想想,native控件对wx一点概念都没有,这怎么行得通?本机控件生成本机事件,然后将其转换为 wx 事件并提供给您的应用程序,但在另一个方向上没有任何反应,甚至无法真正完成。
在这种特殊情况下,您可以(相对)轻松地将滚动事件转换为对 ScrollLines()
、ScrollPages()
或 SetScrollPos()
的调用。这将允许您使用相同的滚动条控制另一个 window 滚动。
不要不要忘记在原始处理程序中调用Skip()
,让window从实际滚动中滚动。