Один из способов заключается в том, чтобы окно регистрировало обработчик событий для каждого из событий мыши, связанных с дочерними окнами.Таким образом, окно может управлять мышью, если выполняется определенное условие (например, удерживается нажатой клавиша Alt при нажатии).
Некоторые из этих вещей показаны в примере wxwidgets\samples\shaped\shaped.cpp
, но в основном вы делаетеthis:
Добавьте метод к вашему окну, который вы вызываете после того, как были добавлены все дочерние окна:
void MyFrame::BindChildEvents()
{
visit_recursively(this,
[] (wxWindow *window, MyFrame *thiz) {
// Bind all but the main window's event
if(window != thiz)
{
window->Bind(wxEVT_LEFT_DOWN, &MyFrame::OnChildLeftDown, thiz);
}
},
this
);
}
Вы можете свернуть свой собственный обход дерева окон, ноЯ использую эту маленькую вспомогательную функцию здесь:
template<typename F, typename... Args>
void
visit_recursively(wxWindow *window, F func, Args&&... args)
{
for(auto&& child : window->GetChildren())
{
visit_recursively(child, func, std::forward<Args>(args)...);
}
func(window, std::forward<Args>(args)...);
}
Затем вы настраиваете свой обработчик перехвата событий при отключении мыши:
void MyFrame::OnChildLeftDown(wxMouseEvent& event)
{
// If Alt is pressed while clicking the child window start dragging the window
if(event.GetModifiers() == wxMOD_ALT)
{
// Capture the mouse, i.e. redirect mouse events to the MyFrame instead of the
// child that was clicked.
CaptureMouse();
const auto eventSource = static_cast<wxWindow *>(event.GetEventObject());
const auto screenPosClicked = eventSource->ClientToScreen(event.GetPosition());
const auto origin = GetPosition();
mouseDownPos_ = screenPosClicked - origin;
}
else
{
// Do nothing, i.e. pass the event on to the child window
event.Skip();
}
}
И вы управляете движением мыши, перемещая окно вместе с мышью:
void MyFrame::OnMouseMove(wxMouseEvent& event)
{
if(event.Dragging() && event.LeftIsDown())
{
const auto screenPosCurrent = ClientToScreen(event.GetPosition());
Move(screenPosCurrent - mouseDownPos_);
}
}
Обязательно позвоните ReleaseMouse()
в событиях wxEVT_LEFT_UP
и wxEVT_MOUSE_CAPTURE_LOST
.