5

我有一个应用程序,我在 WPF 中创建一个用户可以拖动的窗口。我想限制它,这样它就不会越过父窗口的主菜单。如果我处理WindowLocationChanged事件,它会在更改已经发生后触发,所以我唯一能做的就是将窗口强制回到其他位置,这会产生不良的视觉效果。

在移动实际发生之前我可以处理任何事件,以便我可以拦截窗口并强制它保持在一定范围内?一些商业 WPF 库支持在屏幕上实际发生移动之前触发的OnMoving事件。本机 WPF 中是否有类似的东西(如果可能,留在托管代码环境中)?

或者,有没有办法使用依赖属性来设置 max 或 min x,y 值?(注意,我正在移动它,而不是调整它的大小)

提前致谢。

4

1 回答 1

8

这个例子是一个演示,展示了如何防止窗口被移动到它的起始 X/Y 位置以下......它应该给你一个你想做的事情的起点。

请注意,调整大小时可能会改变顶部和左侧位置,这就是为什么要处理 WM_SIZING 消息以确保调整大小不会这样做。

如果您不需要,那么只需取出 WM_SIZING 案例。

    <Window x:Class="WpfApplication12.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
        <Grid>

        </Grid>
    </Window>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace WpfApplication12
{
    [StructLayout(LayoutKind.Sequential)]
    public struct WIN32Rectangle
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        const int WM_SIZING = 0x0214;
        const int WM_MOVING = 0x0216;

        private Point InitialWindowLocation;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            WindowInteropHelper helper = new WindowInteropHelper(this);
            HwndSource.FromHwnd(helper.Handle).AddHook(HwndMessageHook);

            InitialWindowLocation = new Point(this.Left, this.Top);
        }

        private IntPtr HwndMessageHook(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool bHandled)
        {
            switch (msg)
            {
               // You may prefer to check the specific size action being done
               //
               //case WM_SIZING:
               //     {
               //         case (wParam)
               //         {
               //             case WMSZ_LEFT:
               //             {

               //             }
               //             break;

               //             case WSSZ_TOP:
               //             {
               //             }
               //             break;

               //             case WSSZ_TOPLEFT:
               //             {
               //             }
               //             break;
               //         }
               //     }
               //     break;

                case WM_SIZING:
                case WM_MOVING:
                    {
                        WIN32Rectangle rectangle = (WIN32Rectangle)Marshal.PtrToStructure(lParam, typeof(WIN32Rectangle));

                        if (rectangle.Left < this.InitialWindowLocation.X)
                        {
                            rectangle.Left = (int)this.InitialWindowLocation.X;
                            rectangle.Right = (int)this.Left + (int)this.Width;

                            bHandled = true;
                        }

                        if (rectangle.Top < this.InitialWindowLocation.Y)
                        {
                            rectangle.Top = (int)this.InitialWindowLocation.Y;
                            rectangle.Bottom = (int)this.Top + (int)this.Height;

                            bHandled = true;
                        }

                        if (bHandled)
                        {
                            Marshal.StructureToPtr(rectangle, lParam, true);
                        }
                    }
                    break;

            }
            return IntPtr.Zero;
        }
    }
}
于 2012-09-11T22:15:24.367 回答