WPF实现窗体在屏幕内移动拖拽,不超过屏幕边界
最近在项目中遇到WPF弹出窗体只能在屏幕内移动的需求,使用WndProc截获系统消息、ClipCursor API函数控制鼠标可
用区域解决了问题,特意记录以备后用。
- 1
- 2
public partial class MainWindow : Window
{
private POINT _mouseDownPos;
private bool _move;
[DllImport("user32.dll")]
public static extern bool ClipCursor(ref RECT lpRect);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool GetCursorPos(out POINT pt);
public MainWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
if (hwndSource != null)
{
hwndSource.AddHook(new HwndSourceHook((this.WndProc)));
}
}
protected virtual IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
RECT nativeRect;
switch (msg)
{
case 0x20:
{
int lp = lParam.ToInt32();
if ((lp & 0xFFFF) == 2 &&
((lp >> 0x10) & 0xFFFF) == 0x201)
{
GetCursorPos(out _mouseDownPos);
_move = true;
}
}
break;
case 0x231:
if (_move)
{
System.Drawing.Rectangle rect = System.Windows.Forms.SystemInformation.VirtualScreen;
Point ptLeftUp = new Point(0, 0);
Point ptRightDown = new Point(this.ActualWidth, this.ActualHeight);
ptLeftUp = this.PointToScreen(ptLeftUp);
ptRightDown = this.PointToScreen(ptRightDown);
nativeRect = new RECT(
(int)(_mouseDownPos.X - ptLeftUp.X),
(int)( _mouseDownPos.Y - ptLeftUp.Y),
(int)( rect.Right - (ptRightDown.X - _mouseDownPos.X)),
(int)( rect.Bottom - (ptRightDown.Y - _mouseDownPos.Y)));
ClipCursor(ref nativeRect);
}
break;
case 0x0232:
if (_move)
{
nativeRect = new RECT(System.Windows.Forms.SystemInformation.VirtualScreen);
ClipCursor(ref nativeRect);
_move = false;
}
break;
}
return IntPtr.Zero;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
public override string ToString()
{
return ("X:" + X + ", Y:" + Y);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public RECT(System.Drawing.Rectangle rect)
{
Left = rect.Left;
Top = rect.Top;
Right = rect.Right;
Bottom = rect.Bottom;
}
public System.Drawing.Rectangle Rect
{
get
{
return new System.Drawing.Rectangle(
Left,
Top,
Right - Left,
Bottom - Top);
}
}
public Size Size
{
get
{
return new Size(Right - Left, Bottom - Top);
}
}
public static RECT FromXYWH(int x, int y, int width, int height)
{
return new RECT(x,
y,
x + width,
y + height);
}
public static RECT FromRectangle(System.Drawing.Rectangle rect)
{
return new RECT(rect.Left,
rect.Top,
rect.Right,
rect.Bottom);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140