One way is for the window to register an event handler for each of its child windows' mouse down events. That way the window can take control of the mouse if a certain condition is met (e.g. the Alt key is held down while clicking).
Some of this stuff is illustrated in the wxwidgets\samples\shaped\shaped.cpp
sample but basically you do this:
Add a method to your window that you call after all the child windows have been added:
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
);
}
You can roll your own window tree traversal but I use this little helper function here:
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)...);
}
Then you set up your mouse down event interception handler:
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();
}
}
And you handle mouse motion by moving the window along with the mouse:
void MyFrame::OnMouseMove(wxMouseEvent& event)
{
if(event.Dragging() && event.LeftIsDown())
{
const auto screenPosCurrent = ClientToScreen(event.GetPosition());
Move(screenPosCurrent - mouseDownPos_);
}
}
Be sure to call ReleaseMouse()
in the wxEVT_LEFT_UP
and wxEVT_MOUSE_CAPTURE_LOST
events.