双击标题时禁用最大化WPF窗口

时间:2013-04-18 03:59:02

标签: wpf window double-click wndproc maximize

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


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

ResizeMode="CanMinimize"

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

在WinForms中,它可以轻松实现。只需将 FormBorderStyle 设置为 FixedSingle Fixed3D 。但它不再是WPF中的一个选项了。


P.S。我正在尝试处理WM_GETMINMAXINFO,WM_SYSCOMMAND等的一些技巧但是seems it's not working ......

6 个答案:

答案 0 :(得分:7)

我有类似的问题。我的窗口没有任何表格边框或标题栏,但它可以移动(使用鼠标)。问题是,如果用户将窗口移动到屏幕的上边缘,则Windows会自动最大化窗口。

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

private void OnWindowStateChanged(object sender, EventArgs e)
{
    if (this.WindowState == WindowState.Maximized)
    {
        this.WindowState = WindowState.Normal;
    }
}

答案 1 :(得分:6)

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

handled = true如果WndProc调用msg == 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

答案 2 :(得分: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 - link to sample中完成的。之后处理双击事件。

答案 3 :(得分:2)

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

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

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

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

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

答案 4 :(得分: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;
      }


}
}

答案 5 :(得分:0)

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

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

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