C# 禁用 WPF 窗口的最大化按钮,保持调整大小功能不变
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18707782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Disable maximize button of WPF window, keeping resizing feature intact
提问by Peter W.
So WPF windows only have four resize mode options: NoResize
, CanMinimize
, CanResize
and CanResizeWithGrip
. Unfortunately, the options that enable resizing also enable maximizing the window, and those that don't are useless to me.
因此,WPF窗口只有四天调整模式选项:NoResize
,CanMinimize
,CanResize
和CanResizeWithGrip
。不幸的是,启用调整大小的选项也启用了最大化窗口,而那些不启用的选项对我来说毫无用处。
Is there an option to disable the maximize button while keeping the resize feature?
是否可以在保留调整大小功能的同时禁用最大化按钮?
I'd prefer solutions that don't involve WinAPI
stuff.
我更喜欢不涉及WinAPI
内容的解决方案。
采纳答案by Scott
WPF does not have the native capability to disable the Maximize button alone, as you can do with WinForms. You will need to resort to a WinAPI call. It's not scary:
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));
}
回答by Programmer
You can create a custom window by setting WindowStyle to None, which removes the Minimize, Maximize and Close buttons, and create yourself the buttons you need. That's a great example for this:
您可以通过将 WindowStyle 设置为 None 来创建自定义窗口,这将删除最小化、最大化和关闭按钮,并自己创建您需要的按钮。这是一个很好的例子:
http://www.codeproject.com/Articles/131515/WPF-Custom-Chrome-Library
http://www.codeproject.com/Articles/131515/WPF-Custom-Chrome-Library
It gives you some extra work, but if you realy don't want to use WinAPI, that's an option.
它为您提供了一些额外的工作,但如果您真的不想使用 WinAPI,这是一个选项。
回答by TranquilMarmot
If you set
如果你设置
WindowStyle="ToolWindow"
In your window's properties, it will give you a resizable window with no minimize or maximize buttons at the top. It'll be square looking and the close button is also square, but at least minimize and maximize aren't there!
在窗口的属性中,它会给你一个可调整大小的窗口,顶部没有最小化或最大化按钮。它将是方形的,关闭按钮也是方形的,但至少没有最小化和最大化!
回答by 5573352
Disabled only Maximize:
仅禁用最大化:
ResizeMode="CanMinimize"
回答by bytecode77
Another option is catching the StateChanged
event which is raised when the window is maximized. Then simply set the WindowState
to "Normal".
另一种选择是捕获StateChanged
窗口最大化时引发的事件。然后只需将其设置WindowState
为“正常”。
This however does nothide the maximize box!
然而,这并没有隐藏最大化框!
private void Window_StateChanged(object sender, EventArgs e)
{
if (WindowState == WindowState.Maximized)
{
WindowState = WindowState.Normal;
}
}
回答by Shahid Neermunda
P/Invoke Method
P/调用方法
The easiest way to call unmanaged code (C++ in this case) from managed (.NET) code is to use the Platform Invocation Services, often also referred to as P/Invoke. You simply provide the compiler with a declaration of the unmanaged function and call it like you would call any other managed method. There is an unmanaged SetWindowLong method that can be used to change an attribute of a specified window. To be able to call this method from your WPF window class using P/Invoke, you simply add the following declaration to the window class:
从托管 (.NET) 代码调用非托管代码(在本例中为 C++)的最简单方法是使用平台调用服务,通常也称为 P/Invoke。您只需向编译器提供非托管函数的声明,并像调用任何其他托管方法一样调用它。有一个非托管的 SetWindowLong 方法可用于更改指定窗口的属性。为了能够使用 P/Invoke 从 WPF 窗口类调用此方法,只需将以下声明添加到窗口类:
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
The DllImport attribute specifies the name of the DLL that contains the method and the extern keyword tells the C# compiler that the method is implemented externally and that it won't find any implementation or method body for it when compiling the application. The first argument to be passed to the SetWindowLong method is a handle for the window for which you want to disable any of the mentioned buttons. You can get handle for a WPF window by creating an instance of the managed WindowInteropHelper class and access its Handle property in an event handler for the window's SourceInitialized event. This event is raised when the handle has been completely created. The second argument of the SetWindowLong method specifies the attribute or value of the window to be set, expressed as a constant integer value. When you want to change the window style, you should pass the GWL_STYLE (= -16) constant as the second argument to the method.
DllImport 属性指定包含该方法的 DLL 的名称,extern 关键字告诉 C# 编译器该方法是在外部实现的,并且在编译应用程序时它不会为它找到任何实现或方法体。要传递给 SetWindowLong 方法的第一个参数是要禁用任何上述按钮的窗口的句柄。您可以通过创建托管 WindowInteropHelper 类的实例并在窗口的 SourceInitialized 事件的事件处理程序中访问其 Handle 属性来获取 WPF 窗口的句柄。当句柄完全创建时引发此事件。SetWindowLong 方法的第二个参数指定要设置的窗口的属性或值,表示为常量整数值。
private const int GWL_STYLE = -16;
Finally the third argument specifies the the replacement value. There are a set of constants that you could use here:
最后,第三个参数指定替换值。您可以在此处使用一组常量:
private const int WS_MAXIMIZEBOX = 0x10000; //maximize button
private const int WS_MINIMIZEBOX = 0x20000; //minimize button
Note however that since you are supposed to pass in a DWORD that specifies the complete value for the “property” specified by the second argument, i.e. the window style in this case, you cannot simply pass any of these constants by themselves as the third argument to the method. There is another GetWindowLong method that retrieves the current value of a specific property – again the GWL_STYLE in this case – and you can then use bitwise operators to get the correct value of the third parameter to pass to the SetWindowLong method. Below is a complete code sample of how you for example could disable the minimize button for a window in WPF:
但是请注意,由于您应该传入一个 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);
}
}
Disabling the minimize button is then simply a matter of replacing the WS_MAXIMIZEBOX constant with the WS_MINIMIZEBOX
禁用最小化按钮只需将 WS_MAXIMIZEBOX 常量替换为 WS_MINIMIZEBOX