禁用WPF窗口的最大化按钮,保持调整大小功能完好无损

时间:2013-09-09 22:04:40

标签: c# .net wpf

因此,WPF窗口只有四种调整大小模式选项:NoResizeCanMinimizeCanResizeCanResizeWithGrip。不幸的是,启用调整大小的选项也可以使窗口最大化,而那些对窗口没有用的选项也是无用的。

是否有选项可以在保持调整大小功能的同时禁用最大化按钮?

我更喜欢不涉及WinAPI内容的解决方案。

6 个答案:

答案 0 :(得分:63)

仅限停用最大化:

ResizeMode="CanMinimize"

答案 1 :(得分:28)

WPF没有单独禁用“最大化”按钮的本机功能,就像使用WinForms一样。您需要使用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 :(得分:25)

如果您设置

WindowStyle="ToolWindow"

在您的窗口属性中,它会为您提供一个可调整大小的窗口,顶部没有最小化或最大化按钮。它看起来是方形的,关闭按钮也是方形的,但至少最小化和最大化都没有!

答案 3 :(得分:8)

P / Invoke方法

从托管(.NET)代码调用非托管代码(在本例中为C ++)的最简单方法是使用平台调用服务,通常也称为P / Invoke。您只需向编译器提供非托管函数的声明,并像调用任何其他托管方法一样调用它。有一个非托管的SetWindowLong方法,可用于更改指定窗口的属性。为了能够使用P / Invoke从WPF窗口类调用此方法,只需将以下声明添加到窗口类:

[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

DllImport属性指定包含该方法的DLL的名称,extern关键字告诉C#编译器该方法是在外部实现的,并且在编译应用程序时它不会找到任何实现或方法体。要传递给SetWindowLong方法的第一个参数是要禁用任何提到的按钮的窗口的句柄。您可以通过创建托管的WindowInteropHelper类的实例来获取WPF窗口的句柄,并在窗口的SourceInitialized事件的事件处理程序中访问其Handle属性。完全创建句柄后会引发此事件。 SetWindowLong方法的第二个参数指定要设置的窗口的属性或值,表示为常量整数值。如果要更改窗口样式,则应将GWL_STYLE(= - 16)常量作为方法的第二个参数传递。

private const int GWL_STYLE = -16;

最后,第三个参数指定替换值。您可以在此处使用一组常量:

private const int WS_MAXIMIZEBOX = 0x10000; //maximize button
private const int WS_MINIMIZEBOX = 0x20000; //minimize button

但请注意,由于您应该传入一个DWORD,该DWORD指定第二个参数指定的“property”的完整值,即本例中的窗口样式,您不能简单地将这些常量中的任何一个传递给方法的第三个参数。还有另一个GetWindowLong方法可以检索特定属性的当前值 - 在本例中也是GWL_STYLE - 然后您可以使用按位运算符来获取第三个参数的正确值以传递给SetWindowLong方法。下面是一个完整的代码示例,说明如何在WPF中禁用窗口的最小化按钮:

public partial class MainWindow : Window
{
 [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; //maximize button
 private const int WS_MINIMIZEBOX = 0x20000; //minimize button

 public MainWindow() {
  InitializeComponent();
  this.SourceInitialized += MainWindow_SourceInitialized;
}

private IntPtr _windowHandle;
private void MainWindow_SourceInitialized(object sender, EventArgs e) {
_windowHandle = new WindowInteropHelper(this).Handle;

 //disable minimize button
 DisableMinimizeButton();
}

protected void DisableMinimizeButton() {
  if (_windowHandle == IntPtr.Zero)
    throw new InvalidOperationException("The window has not yet been completely initialized");

   SetWindowLong(_windowHandle, GWL_STYLE, GetWindowLong(_windowHandle,  GWL_STYLE) & ~WS_MAXIMIZEBOX);
 }
}

禁用最小化按钮只需用WS_MINIMIZEBOX替换WS_MAXIMIZEBOX常量

答案 4 :(得分:3)

另一个选择是捕获窗口最大化时引发的StateChanged事件。然后只需将WindowState设置为"正常"。

然而隐藏最大化框!

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

答案 5 :(得分:1)

您可以通过将WindowStyle设置为None来创建自定义窗口,这会删除最小化,最大化和关闭按钮,并自己创建所需的按钮。 这是一个很好的例子:

http://www.codeproject.com/Articles/131515/WPF-Custom-Chrome-Library

它为您提供了额外的工作,但如果您真的不想使用WinAPI,那么这是一个选项。