如何在应用程序中禁用 Aero Snap?

发布于 2024-08-25 19:39:57 字数 45 浏览 9 评论 0 原文

是否可以在 WPF 应用程序中禁用 Windows 7 的自动窗口停靠功能?

Is it possible to disable the automatic window-docking feature of Windows 7 in a WPF application?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

木緿 2024-09-01 19:39:57

我最近需要对一个自定义的、可调整大小的 ResizeMode = CanResizeWithGrip WPF 窗口执行此操作,该窗口没有窗口装饰(没有标题栏和按钮)。我使用 DragMove() 来移动窗口,当它被 AeroSnap 最大化时,窗口变得不可移动并因此锁定到位。

我尝试了 Barn Monkey 的解决方案,该解决方案部分有效,但它仍然会显示 AeroSnap 图形并将应用程序大小调整为全屏大小。我在下面修改了它,现在它按预期工作:仍然可以调整大小,但根本没有 AeroSnap。

void Window1_MouseDown(object sender, MouseButtonEventArgs e)
{
    if( e.LeftButton == MouseButtonState.Pressed )
    {
        // this prevents win7 aerosnap
        if( this.ResizeMode != System.Windows.ResizeMode.NoResize )
        {
            this.ResizeMode = System.Windows.ResizeMode.NoResize;
            this.UpdateLayout();
        }

        DragMove();
    }
}

void Window1_MouseUp( object sender, MouseButtonEventArgs e )
{
    if( this.ResizeMode == System.Windows.ResizeMode.NoResize )
    {
        // restore resize grips
        this.ResizeMode = System.Windows.ResizeMode.CanResizeWithGrip;
        this.UpdateLayout();
    }
}

编辑:

自从我写这篇文章以来已经有一段时间了,但由于人们仍然在看这篇文章,我将用我现在使用的内容更新它。我仍然使用基本上相同的方法来防止边缘捕捉和移动窗口,但现在我将它们打包到自定义的行为类中,我可以将它们附加到窗口或用户控件。这使得它们非常容易与 MVVM 一起使用(我使用 Caliburn Micro)。

行为类是:

/// <summary>
/// behavior that makes a window/dialog draggable by clicking anywhere 
/// on it that is not a control (ie, button)
/// </summary>
public class DragMoveBehavior<T> : Behavior<T> where T : FrameworkElement
{
    protected override void OnAttached()
    {
        AssociatedObject.MouseLeftButtonDown += MouseDown;
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseLeftButtonDown -= MouseDown;
        base.OnDetaching();
    }

    void MouseDown( object sender, EventArgs ea ) => Window.GetWindow( sender as T )?.DragMove();
}

public class WinDragMoveBehavior : DragMoveBehavior<Window> { }

public class UCDragMoveBehavior : DragMoveBehavior<UserControl> { }

/// <summary>
/// behavior that makes a window/dialog not resizable while clicked.  this prevents
/// the window from being snapped to the edge of the screen (AeroSnap).  if DragMoveBehavior
/// is also used, this must be attached first.
/// </summary>
/// <typeparam name="T"></typeparam>
public class NoSnapBehavior<T> : Behavior<T> where T : FrameworkElement
{
    ResizeMode lastMode = ResizeMode.NoResize;
    protected override void OnAttached()
    {
        AssociatedObject.MouseLeftButtonDown += MouseDown;
        AssociatedObject.MouseLeftButtonUp += MouseUp;
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseLeftButtonDown -= MouseDown;
        AssociatedObject.MouseLeftButtonUp -= MouseUp;
        base.OnDetaching();
    }

    /// <summary>
    /// make it so the window can be moved by dragging
    /// </summary>
    void MouseDown( object sender, EventArgs ea )
    {
        var win = Window.GetWindow( sender as T );
        if( win != null && win.ResizeMode != ResizeMode.NoResize )
        {
            lastMode = win.ResizeMode;
            win.ResizeMode = ResizeMode.NoResize;
            win.UpdateLayout();
        }
    }

    void MouseUp( object sender, EventArgs ea )
    {
        var win = Window.GetWindow( sender as T );
        if( win != null && win.ResizeMode != lastMode )
        {
            win.ResizeMode = lastMode;
            win.UpdateLayout();
        }
    }
}

public class WinNoSnapBehavior : NoSnapBehavior<Window> { }

public class UCNoSnapBehavior : NoSnapBehavior<UserControl> { }

然后我将它们附加到我的对话框视图:

<UserControl ...
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:util:="...">
  <i:Interaction.Behaviors>
    <util:UCNoSnapBehavior/>
    <util:UCDragMoveBehavior/>
  </i:Interaction.Behaviors>

  ...

</UserControl>

它就可以了!

I recently needed to do this to a custom, resizable ResizeMode = CanResizeWithGrip WPF window with no window decorations (no title bar and buttons). I used DragMove() to move the window, and when It is maximized by AeroSnap, the window becomes unmovable and hence locked in place.

I tried Barn Monkey's solution, which partially worked, but it would still show the AeroSnap graphic and resize the app to fullscreen size. I modified it below and now it works as expect: still resizable, but no AeroSnap at all.

void Window1_MouseDown(object sender, MouseButtonEventArgs e)
{
    if( e.LeftButton == MouseButtonState.Pressed )
    {
        // this prevents win7 aerosnap
        if( this.ResizeMode != System.Windows.ResizeMode.NoResize )
        {
            this.ResizeMode = System.Windows.ResizeMode.NoResize;
            this.UpdateLayout();
        }

        DragMove();
    }
}

void Window1_MouseUp( object sender, MouseButtonEventArgs e )
{
    if( this.ResizeMode == System.Windows.ResizeMode.NoResize )
    {
        // restore resize grips
        this.ResizeMode = System.Windows.ResizeMode.CanResizeWithGrip;
        this.UpdateLayout();
    }
}

EDIT:

It's been a while since I wrote this, but since people still look at this I'll update it with what I use now. I still use basically the same method for preventing edge snapping and moving my windows, but I now have them packed into custom Behavior<> classes that I can attach to a Window or UserControl. This makes them very easy to use with MVVM (I use Caliburn Micro).

The behavior classes are:

/// <summary>
/// behavior that makes a window/dialog draggable by clicking anywhere 
/// on it that is not a control (ie, button)
/// </summary>
public class DragMoveBehavior<T> : Behavior<T> where T : FrameworkElement
{
    protected override void OnAttached()
    {
        AssociatedObject.MouseLeftButtonDown += MouseDown;
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseLeftButtonDown -= MouseDown;
        base.OnDetaching();
    }

    void MouseDown( object sender, EventArgs ea ) => Window.GetWindow( sender as T )?.DragMove();
}

public class WinDragMoveBehavior : DragMoveBehavior<Window> { }

public class UCDragMoveBehavior : DragMoveBehavior<UserControl> { }

/// <summary>
/// behavior that makes a window/dialog not resizable while clicked.  this prevents
/// the window from being snapped to the edge of the screen (AeroSnap).  if DragMoveBehavior
/// is also used, this must be attached first.
/// </summary>
/// <typeparam name="T"></typeparam>
public class NoSnapBehavior<T> : Behavior<T> where T : FrameworkElement
{
    ResizeMode lastMode = ResizeMode.NoResize;
    protected override void OnAttached()
    {
        AssociatedObject.MouseLeftButtonDown += MouseDown;
        AssociatedObject.MouseLeftButtonUp += MouseUp;
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        AssociatedObject.MouseLeftButtonDown -= MouseDown;
        AssociatedObject.MouseLeftButtonUp -= MouseUp;
        base.OnDetaching();
    }

    /// <summary>
    /// make it so the window can be moved by dragging
    /// </summary>
    void MouseDown( object sender, EventArgs ea )
    {
        var win = Window.GetWindow( sender as T );
        if( win != null && win.ResizeMode != ResizeMode.NoResize )
        {
            lastMode = win.ResizeMode;
            win.ResizeMode = ResizeMode.NoResize;
            win.UpdateLayout();
        }
    }

    void MouseUp( object sender, EventArgs ea )
    {
        var win = Window.GetWindow( sender as T );
        if( win != null && win.ResizeMode != lastMode )
        {
            win.ResizeMode = lastMode;
            win.UpdateLayout();
        }
    }
}

public class WinNoSnapBehavior : NoSnapBehavior<Window> { }

public class UCNoSnapBehavior : NoSnapBehavior<UserControl> { }

I then attach them to my dialog box Views with:

<UserControl ...
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
  xmlns:util:="...">
  <i:Interaction.Behaviors>
    <util:UCNoSnapBehavior/>
    <util:UCDragMoveBehavior/>
  </i:Interaction.Behaviors>

  ...

</UserControl>

And it just works!

请恋爱 2024-09-01 19:39:57

如果您以Win7的“便笺”为例,您可能已经注意到它没有标准的窗口边框。以此为基础,我只能告诉您,除了设置 ResizeMode="NoResize" 并手动处理调整大小行为之外,没有直接的方法可以做到这一点。以下是我快速创建的一个非常基本的非专业解决方案,以帮助您入门,但如果您愿意,您可以附加更多功能:)

<Window
    x:Class="WpfApplication1.Window1"
    x:Name="window"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    Width="300"
    Height="300"
    ResizeMode="NoResize"
    WindowStyle="None"
    AllowsTransparency="True"
    Background="Transparent"
    WindowState="Maximized">

    <Window.Resources>
        <x:Array
            x:Key="TextBlockList"
            Type="{x:Type TextBlock}">
            <TextBlock
                Text="○ Resize Horizontally by dragging right grip" />
            <TextBlock
                Text="○ Resize Vertically by dragging bottom grip" />
            <TextBlock
                Text="○ Move Horizontally by dragging left grip" />
            <TextBlock
                Text="○ Move Verticallyby dragging top grip" />
        </x:Array>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition
                Height="Auto" />
            <RowDefinition
                Height="{Binding Height, Mode=OneWay, ElementName=window}" />
            <RowDefinition
                Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition
                Width="Auto" />
            <ColumnDefinition
                Width="{Binding Width, Mode=OneWay, ElementName=window}" />
            <ColumnDefinition
                Width="Auto" />
        </Grid.ColumnDefinitions>

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            HorizontalAlignment="Left"
            MinWidth="5" />

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            HorizontalAlignment="Right"
            MinWidth="5" />

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            VerticalAlignment="Top"
            MinHeight="5"
            ResizeDirection="Rows"
            HorizontalAlignment="Stretch" />

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            VerticalAlignment="Bottom"
            MinHeight="5"
            ResizeDirection="Rows"
            HorizontalAlignment="Stretch" />

        <Border
            Grid.Column="1"
            Grid.Row="1"
            Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
            Margin="5">

            <Grid x:Name="root">
                <ItemsControl
                    ItemsSource="{StaticResource TextBlockList}" />
            </Grid>

        </Border>

    </Grid>
</Window>

您甚至可以制作一个可以调整大小和移动的控件(基本上是一个面板)它的父画布。现在这个控件可以填充到一个透明的最大化窗口中。这会给您一种错觉,认为您的控件是一个不响应“窗口捕捉”并且不会停靠的窗口!

希望这有帮助。
问候,
米希尔·戈卡尼

If you are giving example of "Sticky Notes" of Win7, you may have noticed that it does NOT have standard window border. On that as a base, I can only tell you that there's no direct way of doing this except you set ResizeMode="NoResize" and handling the resize behavior manually. Following is a very basic, non-professional solution that i've quickly created to get you started, but you can append more functions if you like :)

<Window
    x:Class="WpfApplication1.Window1"
    x:Name="window"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1"
    Width="300"
    Height="300"
    ResizeMode="NoResize"
    WindowStyle="None"
    AllowsTransparency="True"
    Background="Transparent"
    WindowState="Maximized">

    <Window.Resources>
        <x:Array
            x:Key="TextBlockList"
            Type="{x:Type TextBlock}">
            <TextBlock
                Text="○ Resize Horizontally by dragging right grip" />
            <TextBlock
                Text="○ Resize Vertically by dragging bottom grip" />
            <TextBlock
                Text="○ Move Horizontally by dragging left grip" />
            <TextBlock
                Text="○ Move Verticallyby dragging top grip" />
        </x:Array>
    </Window.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition
                Height="Auto" />
            <RowDefinition
                Height="{Binding Height, Mode=OneWay, ElementName=window}" />
            <RowDefinition
                Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition
                Width="Auto" />
            <ColumnDefinition
                Width="{Binding Width, Mode=OneWay, ElementName=window}" />
            <ColumnDefinition
                Width="Auto" />
        </Grid.ColumnDefinitions>

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            HorizontalAlignment="Left"
            MinWidth="5" />

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            HorizontalAlignment="Right"
            MinWidth="5" />

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            VerticalAlignment="Top"
            MinHeight="5"
            ResizeDirection="Rows"
            HorizontalAlignment="Stretch" />

        <GridSplitter
            Grid.Column="1"
            Grid.Row="1"
            VerticalAlignment="Bottom"
            MinHeight="5"
            ResizeDirection="Rows"
            HorizontalAlignment="Stretch" />

        <Border
            Grid.Column="1"
            Grid.Row="1"
            Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
            Margin="5">

            <Grid x:Name="root">
                <ItemsControl
                    ItemsSource="{StaticResource TextBlockList}" />
            </Grid>

        </Border>

    </Grid>
</Window>

You can even make a control (basically a panel) that can be resized and moved within its parent canvas. Now this control can be filled into a transparent maximized window. This'll give you an illusion of your control being a window that doesn't respond to 'Window Snap' and will not dock!

Hope this helps.
Regards,
Mihir Gokani

请止步禁区 2024-09-01 19:39:57

我使用安东尼的解决方案有一段时间了,但是如果你切换 ResizeMode,窗口会暂时删除大小边框,这有点烦人。这是另一个解决方案。通过设置 WS_OVERLAPPEDWINDOW 标志并删除 WS_THICKFRAME 标志将禁用窗口的 Aero Snap 功能,同时不会临时删除尺寸边框。您可以尝试使用样式来获得所需的确切样式,但关键是删除 WS_THICKFRAME 标志。

        public enum WindowStyles: int
{
    WS_BORDER = 0x00800000,
    WS_CAPTION = 0x00C00000,
    WS_CHILD = 0x40000000,
    WS_CHILDWINDOW = 0x40000000,
    WS_CLIPCHILDREN = 0x02000000,
    WS_CLIPSIBLINGS = 0x04000000,
    WS_DISABLED = 0x08000000,
    WS_DLGFRAME = 0x00400000,
    WS_GROUP = 0x00020000,
    WS_HSCROLL = 0x00100000,
    WS_ICONIC = 0x20000000,
    WS_MAXIMIZE = 0x01000000,
    WS_MAXIMIZEBOX = 0x00010000,
    WS_MINIMIZE = 0x20000000,
    WS_MINIMIZEBOX = 0x00020000,
    WS_OVERLAPPED = 0x00000000,
    WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
    WS_POPUP = unchecked((int)0x80000000),
    WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
    WS_SIZEBOX = 0x00040000,
    WS_SYSMENU = 0x00080000,
    WS_TABSTOP = 0x00010000,
    WS_THICKFRAME = 0x00040000,
    WS_TILED = 0x00000000,
    WS_TILEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
    WS_VISIBLE = 0x10000000,
    WS_VSCROLL = 0x00200000,
}

int newWinLongStyle = 0;
newWinLongStyle |= (int)WindowStyles.WS_OVERLAPPEDWINDOW;
newWinLongStyle ^= (int)WindowStyles.WS_THICKFRAME; 
WindowInteropHelper helper = new WindowInteropHelper(this);
NativeMethods.SetWindowLong(helper.Handle, (int)WindowStyles.GWL_STYLE, newWinLongStyle);

I was using anthony's solution for awhile, but if you switch ResizeMode the window would temporary remove the sizing border, which is a little anoying. Here's another solution. By setting the WS_OVERLAPPEDWINDOW flag and removing the WS_THICKFRAME flag will disable Aero Snap feature for the window while not temporary removing the sizing border. You can play around with the styles to get the exact style you need, but key is removing the WS_THICKFRAME flag.

        public enum WindowStyles: int
{
    WS_BORDER = 0x00800000,
    WS_CAPTION = 0x00C00000,
    WS_CHILD = 0x40000000,
    WS_CHILDWINDOW = 0x40000000,
    WS_CLIPCHILDREN = 0x02000000,
    WS_CLIPSIBLINGS = 0x04000000,
    WS_DISABLED = 0x08000000,
    WS_DLGFRAME = 0x00400000,
    WS_GROUP = 0x00020000,
    WS_HSCROLL = 0x00100000,
    WS_ICONIC = 0x20000000,
    WS_MAXIMIZE = 0x01000000,
    WS_MAXIMIZEBOX = 0x00010000,
    WS_MINIMIZE = 0x20000000,
    WS_MINIMIZEBOX = 0x00020000,
    WS_OVERLAPPED = 0x00000000,
    WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
    WS_POPUP = unchecked((int)0x80000000),
    WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
    WS_SIZEBOX = 0x00040000,
    WS_SYSMENU = 0x00080000,
    WS_TABSTOP = 0x00010000,
    WS_THICKFRAME = 0x00040000,
    WS_TILED = 0x00000000,
    WS_TILEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
    WS_VISIBLE = 0x10000000,
    WS_VSCROLL = 0x00200000,
}

int newWinLongStyle = 0;
newWinLongStyle |= (int)WindowStyles.WS_OVERLAPPEDWINDOW;
newWinLongStyle ^= (int)WindowStyles.WS_THICKFRAME; 
WindowInteropHelper helper = new WindowInteropHelper(this);
NativeMethods.SetWindowLong(helper.Handle, (int)WindowStyles.GWL_STYLE, newWinLongStyle);
简单 2024-09-01 19:39:57

这是我的解决方案。如果 Windows 的 ResizeMode 设置为 ResizeMode.NoResize,则 Windows 将不会捕捉,因此,技巧是可靠地确定拖动/移动何时开始和结束。

编辑: alexandrud 正确地指出,这仅适用于“无边框”窗口(WPF 术语中的 WindowStyle = None)。

为了给我们带来这个信息,许多博萨人付出了生命的代价。

class NoSnapWindow : System.Windows.Window
{
    public NoSnapWindow()
    {
        SourceInitialized += delegate {
            var source = HwndSource.FromVisual(this) as HwndSource;
            source.AddHook(SourceHook);
        };
    }

    private IntPtr SourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch (msg)
        {
            case 0x112: // WM_SYSCOMMAND
                switch (wParam.ToIn32() & ~0x0F)
                {
                    case 0xF010: // SC_MOVE
                        ResizeMode = ResizeMode.NoResize;
                        break;
                }
                break;
            case 0x2A2: // WM_MOUSELEAVE
                ResizeMode = ResizeMode.CanResize;
                break;
        }

        return IntPtr.Zero;
    }
}

Here's my solution. Windows will not snap if their ResizeMode is set to ResizeMode.NoResize, therefore, the trick is to determine reliably when a drag/move begins and ends.

EDIT: alexandrud correctly pointed out that this will only work for "borderless" windows (WindowStyle = None in WPF terms).

Many Bothans died to bring us this information.

class NoSnapWindow : System.Windows.Window
{
    public NoSnapWindow()
    {
        SourceInitialized += delegate {
            var source = HwndSource.FromVisual(this) as HwndSource;
            source.AddHook(SourceHook);
        };
    }

    private IntPtr SourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        switch (msg)
        {
            case 0x112: // WM_SYSCOMMAND
                switch (wParam.ToIn32() & ~0x0F)
                {
                    case 0xF010: // SC_MOVE
                        ResizeMode = ResizeMode.NoResize;
                        break;
                }
                break;
            case 0x2A2: // WM_MOUSELEAVE
                ResizeMode = ResizeMode.CanResize;
                break;
        }

        return IntPtr.Zero;
    }
}
北笙凉宸 2024-09-01 19:39:57

我需要检测 Windows 7 Aero 捕捉/停靠以防止 WPF 应用程序上的窗口大小发生变化。在我的搜索过程中,我偶然发现了这篇文章,并找到了 anthony 给出的答案非常有帮助。

以下是对我有用的。

private void DisplayWindow_MouseMove(object sender, MouseEventArgs e) 
{
    if (e.LeftButton == MouseButtonState.Released) 
    {
        this.ResizeMode = System.Windows.ResizeMode.CanResizeWithGrip;
    }
}

private void DisplayWindow_LocationChanged(object sender, EventArgs e) 
{
    this.ResizeMode = System.Windows.ResizeMode.NoResize;
}

窗口的 XAML 具有 ResizeMode="CanResizeWithGrip" 设置。

编辑
我的反应是无法正确处理 Windows 7 Aero 快照。 bjo的回应优雅地为我解决了这个问题。

I needed to detect Windows 7 Aero snaps/docks to prevent window-size changes on a WPF application. During my search, I stumbled upon this post and found the answer given by anthony very helpful.

Following is what worked for me.

private void DisplayWindow_MouseMove(object sender, MouseEventArgs e) 
{
    if (e.LeftButton == MouseButtonState.Released) 
    {
        this.ResizeMode = System.Windows.ResizeMode.CanResizeWithGrip;
    }
}

private void DisplayWindow_LocationChanged(object sender, EventArgs e) 
{
    this.ResizeMode = System.Windows.ResizeMode.NoResize;
}

The window's XAML had the ResizeMode="CanResizeWithGrip" setting.

Edit:
My response was not handle the Windows 7 Aero snap properly. bjo's response elegantly solved the problem for me.

朮生 2024-09-01 19:39:57

这对你来说可能不是完美的解决方案,但对我来说,将表单设置为不可调整大小就可以了。

It might not be the perfect solution for you, but for me setting the form as non-resizable did the trick.

关于从前 2024-09-01 19:39:57

DragMove 暂停 UI 线程。
该代码也有效。

void Window1_MouseDown(object sender, MouseButtonEventArgs e)
{
    if( e.LeftButton == MouseButtonState.Pressed )
    {
        // this prevents win7 aerosnap
        this.ResizeMode = System.Windows.ResizeMode.NoResize;
        this.UpdateLayout();

        DragMove();

        // restore resize grips
        this.ResizeMode = System.Windows.ResizeMode.CanResizeWithGrip;
        this.UpdateLayout();
    }
}

DragMove suspends the UI Thread.
That code also works.

void Window1_MouseDown(object sender, MouseButtonEventArgs e)
{
    if( e.LeftButton == MouseButtonState.Pressed )
    {
        // this prevents win7 aerosnap
        this.ResizeMode = System.Windows.ResizeMode.NoResize;
        this.UpdateLayout();

        DragMove();

        // restore resize grips
        this.ResizeMode = System.Windows.ResizeMode.CanResizeWithGrip;
        this.UpdateLayout();
    }
}
拥有 2024-09-01 19:39:57

我发现一个相当简单的解决方案也适用于无边框窗口:只需隐藏最大化按钮(如果由于缺少标题栏而尚未显示,则发生此情况):

    [DllImport("user32.dll")]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    private const int GWL_STYLE = -16;
    private const int WS_MAXIMIZEBOX = 0x10000;

    private void Window_OnSourceInitialized(object sender, EventArgs e)
    {
            var hwnd = new WindowInteropHelper((Window)sender).Handle;
            var value = GetWindowLong(hwnd, GWL_STYLE);
            SetWindowLong(hwnd, GWL_STYLE, (int)(value & ~WS_MAXIMIZEBOX));
    }

A rather simple solution I found that works with borderless windows as well: Just hide the maximize button (event if it's already not displayed due to the lack of caption bar):

    [DllImport("user32.dll")]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    private const int GWL_STYLE = -16;
    private const int WS_MAXIMIZEBOX = 0x10000;

    private void Window_OnSourceInitialized(object sender, EventArgs e)
    {
            var hwnd = new WindowInteropHelper((Window)sender).Handle;
            var value = GetWindowLong(hwnd, GWL_STYLE);
            SetWindowLong(hwnd, GWL_STYLE, (int)(value & ~WS_MAXIMIZEBOX));
    }
终遇你 2024-09-01 19:39:57

我这里没有 Windows 7 盒子,所以我无法测试这个,但我会尝试以下方法:

1- 创建一个测试表单并覆盖 WndProc
2- 测试并记录与大小、位置和窗口状态更改相关的特定消息。
3- 确定停靠时发送到窗口的消息是否是大小/位置/窗口状态的组合,或者是否有另一条新的 Windows 7 消息(5 分钟的搜索没有向我透露任何信息) .)
4- 收到消息后,检查是否存在“独特”情况正在发生。
5-修改您的代码以适应这种独特的情况。

如果没有其他人想出任何办法,我可能会在这个周末在家尝试一下。

I don't have a Windows 7 box here, so I can't test this, but here's what I would try:

1- Create a test form and override the WndProc
2- Test and log specific messages pertaining to Size, Position and WindowState changing.
3- Determine if the messages sent to the window when docked are a combination of Size/Position/WindowState or if there is another, new Windows 7 message (5 minutes of searching didn't reveal anything to me.)
4- Once you have the messages, check to see if there is a "unique" case that is occurring.
5- Modify your code to accommodate that unique case.

If no one else comes up with anything, I might give this a whirl at home this weekend.

倦话 2024-09-01 19:39:57

设置“this.MaximizeBox = false”实际上会破坏 Windows 10 上的 Snap。
也许这对你有用?

Setting "this.MaximizeBox = false" actually breaks Snap for me on Windows 10.
Maybe this will work for you?

薯片软お妹 2024-09-01 19:39:57

我们开始...

最后我找到了真正的解决方案。

我正在为我的应用程序寻找真正的解决方案。
我为此浪费了一整天的时间。
有很多技巧,但使用 reg 我们需要重新启动计算机。

您可以从 powershell 禁用它。您需要从代码中调用此文件。

这是链接。

检查底部名为“DisableAeroSnap.ps1”的下载文件

https://michlstechblog.info/blog/windows-disable-aerosnap-automatically-window-arranging-and-resizing-while-dragging/#more-951

干杯!

Here We go ...

Finally i found real solution for this.

I was searching a real solution for my application.
I wasted my whole day for this.
There are many tricks but using reg we need to restart computer.

You can disable it from powershell. You need to call this file from your code.

Here is link.

Check download file at bottom called "DisableAeroSnap.ps1"

https://michlstechblog.info/blog/windows-disable-aerosnap-automatically-window-arranging-and-resizing-while-dragging/#more-951

Cheers !!!

梦行七里 2024-09-01 19:39:57

在控制面板的“轻松访问”中,选择“

更轻松地专注于任务”

并勾选

“防止窗口移动到屏幕边缘时自动排列”

In Ease of Access in control panel, choose

Make it easier to focus on tasks

and tick

Prevent windows from being automatically arranged when moved to the edge of the screen

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文