如何锁定WPF窗口,使其无法移动,调整大小,最小化,最大化或拖动

时间:2022-02-19 20:42:41

I am looking for a simple way to lock a WPF window. Is there a simple window style or property I can set on a WPF window to locked the window?

我正在寻找一种锁定WPF窗口的简单方法。我可以在WPF窗口上设置一个简单的窗口样式或属性来锁定窗口吗?

By lock I mean the user can not move, resize, drag, minimize or maximize the window.

通过锁定我的意思是用户无法移动,调整大小,拖动,最小化或最大化窗口。

2 个解决方案

#1


18  

Setup the window with:

设置窗口:

window.WindowStyle = WindowStyle.None;
window.ResizeMode = ResizeMode.NoResize;

This will prevent the user from minimizing, maximizing, or moving the Window.

这将阻止用户最小化,最大化或移动窗口。

#2


3  

To prevent a window from being moved or resized, handle the WM_WINDOWPOSCHANGING message in a WndProc hook. Using WM_WINDOWPOSCHANGING prevents the window from being moved even by Win + Shift + Left. An example of an attached property which adds this behavior is shown below.

要防止窗口被移动或调整大小,请在WndProc挂钩中处理WM_WINDOWPOSCHANGING消息。使用WM_WINDOWPOSCHANGING可以防止窗口被Win + Shift + Left移动。下面显示了添加此行为的附加属性的示例。

This can be combined with WindowStyle and ResizeMode to make the window look immovable too.

这可以与WindowStyle和ResizeMode结合使用,使窗口看起来也不可移动。

using static NativeMethods;

public class WindowPos : DependencyObject
{
    public static bool GetIsLocked(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsLockedProperty);
    }

    public static void SetIsLocked(DependencyObject obj, bool value)
    {
        obj.SetValue(IsLockedProperty, value);
    }

    public static readonly DependencyProperty IsLockedProperty =
        DependencyProperty.RegisterAttached("IsLocked", typeof(bool), typeof(WindowPos), 
            new PropertyMetadata(false, IsLocked_Changed));

    private static void IsLocked_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var window = (Window)d;
        var isHooked = d.GetValue(IsHookedProperty) != null;

        if (!isHooked)
        {
            var hook = new WindowLockHook(window);
            d.SetValue(IsHookedProperty, hook);
        }
    }

    private static readonly DependencyProperty IsHookedProperty =
        DependencyProperty.RegisterAttached("IsHooked", typeof(WindowLockHook), typeof(WindowPos), 
            new PropertyMetadata(null));

    private class WindowLockHook
    {
        private readonly Window Window;

        public WindowLockHook(Window window)
        {
            this.Window = window;

            var source = PresentationSource.FromVisual(window) as HwndSource;
            if (source == null)
            {
                // If there is no hWnd, we need to wait until there is
                window.SourceInitialized += Window_SourceInitialized;
            }
            else
            {
                source.AddHook(WndProc);
            }
        }

        private void Window_SourceInitialized(object sender, EventArgs e)
        {
            var source = (HwndSource)PresentationSource.FromVisual(Window);
            source.AddHook(WndProc);
        }

        public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_WINDOWPOSCHANGING && GetIsLocked(Window))
            {
                var wp = Marshal.PtrToStructure<WINDOWPOS>(lParam);
                wp.flags |= SWP_NOMOVE | SWP_NOSIZE;
                Marshal.StructureToPtr(wp, lParam, false);
            }

            return IntPtr.Zero;
        }
    }
}

internal static class NativeMethods
{
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public int flags;
    }

    public const int
        SWP_NOMOVE = 0x0002,
        SWP_NOSIZE = 0x0001;

    public const int
        WM_WINDOWPOSCHANGING = 0x0046;
}

Example use:

如何锁定WPF窗口,使其无法移动,调整大小,最小化,最大化或拖动

#1


18  

Setup the window with:

设置窗口:

window.WindowStyle = WindowStyle.None;
window.ResizeMode = ResizeMode.NoResize;

This will prevent the user from minimizing, maximizing, or moving the Window.

这将阻止用户最小化,最大化或移动窗口。

#2


3  

To prevent a window from being moved or resized, handle the WM_WINDOWPOSCHANGING message in a WndProc hook. Using WM_WINDOWPOSCHANGING prevents the window from being moved even by Win + Shift + Left. An example of an attached property which adds this behavior is shown below.

要防止窗口被移动或调整大小,请在WndProc挂钩中处理WM_WINDOWPOSCHANGING消息。使用WM_WINDOWPOSCHANGING可以防止窗口被Win + Shift + Left移动。下面显示了添加此行为的附加属性的示例。

This can be combined with WindowStyle and ResizeMode to make the window look immovable too.

这可以与WindowStyle和ResizeMode结合使用,使窗口看起来也不可移动。

using static NativeMethods;

public class WindowPos : DependencyObject
{
    public static bool GetIsLocked(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsLockedProperty);
    }

    public static void SetIsLocked(DependencyObject obj, bool value)
    {
        obj.SetValue(IsLockedProperty, value);
    }

    public static readonly DependencyProperty IsLockedProperty =
        DependencyProperty.RegisterAttached("IsLocked", typeof(bool), typeof(WindowPos), 
            new PropertyMetadata(false, IsLocked_Changed));

    private static void IsLocked_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var window = (Window)d;
        var isHooked = d.GetValue(IsHookedProperty) != null;

        if (!isHooked)
        {
            var hook = new WindowLockHook(window);
            d.SetValue(IsHookedProperty, hook);
        }
    }

    private static readonly DependencyProperty IsHookedProperty =
        DependencyProperty.RegisterAttached("IsHooked", typeof(WindowLockHook), typeof(WindowPos), 
            new PropertyMetadata(null));

    private class WindowLockHook
    {
        private readonly Window Window;

        public WindowLockHook(Window window)
        {
            this.Window = window;

            var source = PresentationSource.FromVisual(window) as HwndSource;
            if (source == null)
            {
                // If there is no hWnd, we need to wait until there is
                window.SourceInitialized += Window_SourceInitialized;
            }
            else
            {
                source.AddHook(WndProc);
            }
        }

        private void Window_SourceInitialized(object sender, EventArgs e)
        {
            var source = (HwndSource)PresentationSource.FromVisual(Window);
            source.AddHook(WndProc);
        }

        public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_WINDOWPOSCHANGING && GetIsLocked(Window))
            {
                var wp = Marshal.PtrToStructure<WINDOWPOS>(lParam);
                wp.flags |= SWP_NOMOVE | SWP_NOSIZE;
                Marshal.StructureToPtr(wp, lParam, false);
            }

            return IntPtr.Zero;
        }
    }
}

internal static class NativeMethods
{
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public int flags;
    }

    public const int
        SWP_NOMOVE = 0x0002,
        SWP_NOSIZE = 0x0001;

    public const int
        WM_WINDOWPOSCHANGING = 0x0046;
}

Example use:

如何锁定WPF窗口,使其无法移动,调整大小,最小化,最大化或拖动