因此WPF 窗口只有四个调整大小模式选项:NoResize
、CanMinimize
和. 不幸的是,启用调整大小的选项也启用了最大化窗口,而那些对我没有用的选项。CanResize
CanResizeWithGrip
是否可以在保留调整大小功能的同时禁用最大化按钮?
我更喜欢不涉及WinAPI
东西的解决方案。
仅禁用最大化:
ResizeMode="CanMinimize"
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));
}
如果你设置
WindowStyle="ToolWindow"
在您的窗口属性中,它将为您提供一个可调整大小的窗口,顶部没有最小化或最大化按钮。它将是方形的,关闭按钮也是方形的,但至少最小化和最大化不存在!
P/调用方法
从托管 (.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 类的实例并在窗口的 SourceInitialized 事件的事件处理程序中访问其 Handle 属性来获取 WPF 窗口的句柄。当句柄完全创建时引发此事件。SetWindowLong 方法的第二个参数指定要设置的窗口的属性或值,以常量整数值表示。当你想改变窗口样式时,
private const int GWL_STYLE = -16;
最后第三个参数指定替换值。您可以在此处使用一组常量:
private const int WS_MAXIMIZEBOX = 0x10000; //maximize button
private const int WS_MINIMIZEBOX = 0x20000; //minimize button
但是请注意,由于您应该传入一个 DWORD,该 DWORD 指定由第二个参数指定的“属性”的完整值,即在这种情况下的窗口样式,您不能简单地将这些常量中的任何一个作为第三个参数传递到方法。还有另一个 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_MAXIMIZEBOX 常量替换为 WS_MINIMIZEBOX
另一种选择是捕获StateChanged
窗口最大化时引发的事件。然后只需将其设置WindowState
为“正常”。
然而,这并没有隐藏最大化框!
private void Window_StateChanged(object sender, EventArgs e)
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
}
您可以通过将 WindowStyle 设置为 None 来创建自定义窗口,这会删除最小化、最大化和关闭按钮,并自己创建您需要的按钮。这是一个很好的例子:
http://www.codeproject.com/Articles/131515/WPF-Custom-Chrome-Library
它为您提供了一些额外的工作,但如果您真的不想使用 WinAPI,这是一个选择。