WPF实现窗体在屏幕内移动拖拽,不超过屏幕边界

原文: WPF实现窗体在屏幕内移动拖拽,不超过屏幕边界

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

你可能感兴趣的:(WPF实现窗体在屏幕内移动拖拽,不超过屏幕边界)