Отключить кнопку максимизации окна WPF, сохраняя неизменную функцию изменения размера

Таким образом, окна WPF имеют только четыре режима изменения размера: NoResize, CanMinimize, CanResize и CanResizeWithGrip. К сожалению, параметры, которые позволяют изменять размер, также позволяют максимизировать окно, а те, которые для меня не бесполезны.

Можно ли отключить кнопку максимизации при сохранении функции изменения размера?

Я бы предпочел решения, которые не включают WinAPI.

Ответ 1

WPF не имеет собственной возможности отключать кнопку Maximize самостоятельно, как это можно сделать с 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

Только отключено Максимизировать:

ResizeMode="CanMinimize"

Ответ 3

Если вы установили

WindowStyle="ToolWindow"

В свойствах вашего окна он предоставит вам окно с изменяемым размером без кнопок минимизации или максимизации вверху. Он будет квадратным, и кнопка закрытия также квадратная, но, по крайней мере, минимизировать и максимизировать, нет!

Ответ 4

Метод P/Invoke

Самый простой способ вызвать неуправляемый код (С++ в этом случае) из управляемого (.NET) кода - использовать службы Invocation Services, часто называемые P/Invoke. Вы просто предоставляете компилятору объявление неуправляемой функции и вызываете ее так, как если бы вы вызывали любой другой управляемый метод. Существует неуправляемый метод SetWindowLong, который можно использовать для изменения атрибута указанного окна. Чтобы иметь возможность вызывать этот метод из вашего класса окон WPF с помощью P/Invoke, вы просто добавляете следующее объявление в класс окна:

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

Атрибут DllImport указывает имя DLL, которое содержит этот метод, и ключевое слово extern сообщает компилятору С#, что метод реализован извне, и что он не найдет для него никакой реализации или тела метода при компиляции приложения. Первый аргумент, который должен быть передан методу SetWindowLong, является дескриптором окна, для которого вы хотите отключить любую из указанных кнопок. Вы можете получить ручку для окна WPF, создав экземпляр управляемого класса WindowInteropHelper и получив доступ к свойству Handle в обработчике событий для события SourceInitialized. Это событие возникает, когда дескриптор полностью создан. Второй аргумент метода 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, который определяет полное значение для свойства, указанного вторым аргументом, то есть стиль окна в этом случае, вы не можете просто передать какую-либо из этих констант сами по себе, как третий аргумент метода. Существует еще один метод 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

Ответ 5

Другим вариантом является захват события StateChanged, которое возникает при максимальном увеличении окна. Затем просто установите для параметра WindowState значение "Normal".

Тем не менее не скрывает поле максимизации!

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

Ответ 6

Вы можете создать собственное окно, установив WindowStyle в None, который удаляет кнопки "Свернуть", "Развернуть" и "Закрыть" и создайте нужные вам кнопки. Это отличный пример для этого:

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

Это дает вам дополнительную работу, но если вы действительно не хотите использовать WinAPI, это вариант.