I think this trick can be used on any windowing system with below events supported.
WPF specific implementation is easier because if you handle mouse events on main window events will be raised even if some additional control cover dirty region on the form.
Of course OriginSource properly informs you which control your mouse is just hovering which can be useful to additional actions.
Due to that fact this routinue looks much simpler to the last one I coded ages ago for Visual C++ and WinAPI only.
Generally if you have WPF Window first what has to be done is to handle below events:
this.MouseMove += new MouseEventHandler(MainWindow_MouseMove);
this.MouseLeftButtonUp += new MouseButtonEventHandler(MainWindow_MouseLeftButtonUp);
this.MouseLeftButtonDown += new MouseButtonEventHandler(MainWindow_MouseLeftButtonDown);
Inside these events you just need below simple code:
void MainWindow_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
clickedMouseOffset.X = 0;
clickedMouseOffset.Y = 0;
void MainWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
clickedMouseOffset = e.GetPosition(this);
void MainWindow_MouseMove(object sender, MouseEventArgs e)
if (e.LeftButton == MouseButtonState.Pressed)
Point p = e.GetPosition(this);
this.Left += p.X - clickedMouseOffset.X;
this.Top += p.Y - clickedMouseOffset.Y;
It's not perfect but working example. As I said, you can handle additional conditions in MouseMove events.
Issues I found for example is that some of embedded controls trigger strange movement offset to the whole window through that event.
Hovered Controls which are troublemaking are: enabled TextBox and Slider for example.
You can also make your life even easier to handle it through the right click button which doesn't collide with other controls focus via left-click.
This code doesn't work perfect for dynamic (quick) mouse moves outside the form context.
You can use this base to play with more accurate resolution. Feel free to comment (of course)