4

如何在双击标题时禁用最大化 WPF 窗口并保持调整大小可用?


我知道ResizeMode禁用最大化,但它也阻止调整表单大小

ResizeMode="CanMinimize"

我知道如何删除最大化和最小化按钮,但仍然可以通过双击标题来最大化。

在 WinForms 中可以轻松实现。只需将FormBorderStyleNone设置为FixedSingleFixed3D。但这不再是 WPF 中的选项。


PS 我正在尝试一些技巧来处理 WM_GETMINMAXINFO、WM_SYSCOMMAND 等。但似乎它不起作用......

4

6 回答 6

8

我有一个类似的问题。我的窗口没有任何窗体边框或标题栏,但可以移动(使用鼠标)。问题是如果用户将窗口移动到屏幕的顶部边缘,那么 Windows 会自动将窗口最大化。

StateChanged我设法通过将以下处理程序附加到窗口的事件来解决这个问题。

private void OnWindowStateChanged(object sender, EventArgs e)
{
    if (this.WindowState == WindowState.Maximized)
    {
        this.WindowState = WindowState.Normal;
    }
}
于 2014-03-08T16:51:09.830 回答
8

很好的解决方案,我在 MSDN 的一点帮助下在 WPF 窗口中检测非客户端鼠标活动。

当用户双击非客户区时,调用 if 将阻止handled = true窗口最大化WndProcmsg == WM_NCLBUTTONDBLCLK

myClass()  //c'tor
{
  InitializeComponent();
  SourceInitialized += new EventHandler(myClass_SourceInitialized);  
}

void myClass_SourceInitialized(object sender, EventArgs e)
{
    System.Windows.Interop.HwndSource source = System.Windows.Interop.HwndSource.FromHwnd(new System.Windows.Interop.WindowInteropHelper(this).Handle);
    source.AddHook(new System.Windows.Interop.HwndSourceHook(WndProc));
}

int WM_NCLBUTTONDBLCLK { get { return 0x00A3; } }

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == WM_NCLBUTTONDBLCLK)
    {
        handled = true;  //prevent double click from maximizing the window.
    }

    return IntPtr.Zero;
}

有用的 MSDN 参考: https ://social.msdn.microsoft.com/Forums/vstudio/en-US/f54dde25-b748-4724-a7fe-a355b086cfd4/mouse-event-in-the-nonclient-window-area

于 2014-11-07T21:32:19.977 回答
2

在遇到这个问题并研究了这个 SO question 之后,我认为答案是不够的。删除标题栏后,双击靠近窗口顶部时,窗口仍会最大化。

我选择了删除标题栏并禁用双击窗口的方法。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        MouseDoubleClick += (sender, args) =>
        {
            args.Handled = true;
        };
    }
}

在我的应用程序中,我使用的是从MetroWindow而不是Window继承的 MahApps.Metro,但是上面的示例在这两种情况下都适用。

于 2014-03-23T09:40:42.500 回答
2

WPF没有禁用最大化窗口的本机方法(与WinForms不同)。因此,请考虑以下关键点:

1.隐藏最大化按钮

使用WinAPI是一种可行的方法,但仅用于隐藏最大化按钮。使用以下内容:

[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_SourceInitialized(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));
}

2. 手动处理最大化

上面的代码仍然允许最大化(例如通过双击窗口的标题)。

WPF无法控制标题栏的行为。如果要更改双击行为,则需要删除标题栏并创建自己的标题栏。看看它是如何在MahApps.Metro中完成的-链接到示例。之后处理双击事件。

于 2013-11-26T02:06:16.610 回答
1

这对你有用吗?

public partial class MainWindow : Window
 {
    public MainWindow()
   {

    InitializeComponent();
    this.SizeChanged += MainWindow_SizeChanged;
   }    
    void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
    {

      if (this.WindowState == WindowState.Maximized)
      {
       this.WindowState = System.Windows.WindowState.Normal;
      }


}
}
于 2013-04-18T05:13:44.803 回答
1

另一个简单(但丑陋)的解决方案:

// inside a Window class
protected override void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
{
    base.OnPreviewMouseDoubleClick(e);

    const int titleHeight = 30;
    var position = e.GetPosition(this);

    if (position.Y <= titleHeight)
    {
        e.Handled = true;
    }
}

注意:用户仍然可以使用标题栏上的上下文菜单最大化窗口/将窗口移动到屏幕的上边缘。

于 2014-03-10T10:28:03.653 回答