概要
wpf自带移动窗口方法DragMove,但仅限于鼠标主键(左键)按下时生效,有时候需求是非鼠标左键按下时可以实现鼠标移动窗口,则无法使用此方法。故采用win32的方法GetWindowRect和SetWindowPos来实现任意按键结合鼠标移动事件来实现移动窗口。
实现流程
以鼠标右键移动为例:
- 监控鼠标右键按下,记录当前鼠标位置
- 监控鼠标移动,每次移动内获取鼠标移动后的位置,计算鼠标位置变化,让目标窗口相对原位置偏移
- 监控鼠标松开,标记按键事件已处理
代码
xaml
PreviewMouseMove="Window_PreviewMouseMove"
PreviewMouseRightButtonDown="Window_PreviewMouseRightButtonDown"
PreviewMouseRightButtonUp="Window_PreviewMouseRightButtonUp"
xaml.cs
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, int hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref System.Drawing.Rectangle rect);
private Point _pressedPos;
bool _isDragMoved = false;
private void Window_PreviewMouseMove(object sender, MouseEventArgs e)
{
var currentPos = e.GetPosition(this);
if (Mouse.RightButton == MouseButtonState.Pressed && _pressedPos != currentPos)
{
_isDragMoved = true;
var hwnd = (System.Windows.Interop.HwndSource.FromDependencyObject(this) as System.Windows.Interop.HwndSource).Handle;
var windowRect = new System.Drawing.Rectangle();
GetWindowRect(hwnd,ref windowRect);
//0x0001 SWP_NOSIZE | 0x0004 SWP_NOZORDER
//忽略hWndlnsertAfter和cy、cx,即不改变窗口显示顺序和显示长宽,仅移动位置
SetWindowPos(hwnd,0, windowRect.X + (int)(currentPos.X - _pressedPos.X), windowRect.Y + (int)(currentPos.Y - _pressedPos.Y), 0,0, 0x0001 | 0x0004);
}
}
private void Window_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isDragMoved)
{
_isDragMoved = false;
e.Handled = true;
}
}
private void Window_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
_pressedPos = e.GetPosition(this);
}