【问题标题】:Disable maximizing WPF window on double click on the caption双击标题时禁用最大化 WPF 窗口
【发布时间】:2013-04-11 01:16:16
【问题描述】:

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


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

ResizeMode="CanMinimize"

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

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


附:我正在尝试一些技巧来处理 WM_GETMINMAXINFO、WM_SYSCOMMAND 等。但是seems it's not working...

【问题讨论】:

    标签: wpf window double-click wndproc maximize


    【解决方案1】:

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

    如果msg == WM_NCLBUTTONDBLCLKWndProc 中调用handled = true 将阻止用户双击非客户区时窗口最大化。

    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

    【讨论】:

    • @Klaus - 我知道这已经有一段时间了,但这可能会对您有所帮助(对于未来!)。
    • 迄今为止我发现的唯一真正有效的选择。所有其他都受到限制,或者被黑客攻击,或者只是无效。
    【解决方案2】:

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

    我选择了去掉标题栏和禁止双击窗口的方式。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            MouseDoubleClick += (sender, args) =>
            {
                args.Handled = true;
            };
        }
    }
    

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

    【讨论】:

    • PreviewMouseDoubleClick 是更好的选择,MouseDoubleClick 并不总是有效
    【解决方案3】:

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

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

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

    【讨论】:

    • 它可能很难看,但它是最好的解决方案,因为它不需要 WINAPI 导入并且不会闪烁。干得好
    【解决方案4】:

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

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

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

    【讨论】:

    • 这很笨拙,因为窗口会立即最大化,然后又恢复下来,从而产生丑陋的视觉响应。
    【解决方案5】:

    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 中完成的。之后处理双击事件。

    【讨论】:

      【解决方案6】:

      这对你有用吗?

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

      【讨论】:

      • 它实际上并没有禁用最大化并导致窗口闪烁。因此,我无法将其标记为答案。
      猜你喜欢
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多