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

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

最近在项目中遇到WPF弹出窗体只能在屏幕内移动的需求,使用WndProc截获系统消息、ClipCursor API函数控制鼠标可用区域解决了问题,特意记录以备后用。

   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);
             }
         }


    }

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