Как убрать сворачивание и разворачивание окна с изменяемым размером в WPF?

80

WPF не предоставляет возможности иметь окно, которое позволяет изменять размер, но не имеет кнопок развертывания или минимизации. Я хотел бы создать такое окно, чтобы иметь диалоговые окна с изменяемым размером.

Я знаю, что решение будет означать использование pinvoke, но я не уверен, что и как звонить. Поиск на сайте pinvoke.net не обнаружил ничего, что бы показалось мне нужным, в основном я уверен, потому что Windows Forms предоставляет CanMinimizeиCanMaximize свойства на своих окнах.

Может ли кто-нибудь указать мне или предоставить код (предпочтительно C #) о том, как это сделать?

Нидоноку
источник

Ответы:

114

Я украл код, который нашел на форумах MSDN, и создал метод расширения для класса Window, например:

internal static class WindowExtensions
{
    // from winuser.h
    private const int GWL_STYLE      = -16,
                      WS_MAXIMIZEBOX = 0x10000,
                      WS_MINIMIZEBOX = 0x20000;

    [DllImport("user32.dll")]
    extern private static int GetWindowLong(IntPtr hwnd, int index);

    [DllImport("user32.dll")]
    extern private static int SetWindowLong(IntPtr hwnd, int index, int value);

    internal static void HideMinimizeAndMaximizeButtons(this Window window)
    {
        IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(window).Handle;
        var currentStyle = GetWindowLong(hwnd, GWL_STYLE);

        SetWindowLong(hwnd, GWL_STYLE, (currentStyle & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX));
    }
}

Единственное, что нужно помнить, это то, что по какой-то причине это не работает из конструктора окна. Я обошел это, вставив это в конструктор:

this.SourceInitialized += (x, y) =>
{
    this.HideMinimizeAndMaximizeButtons();
};

Надеюсь это поможет!

Мэтт Гамильтон
источник
3
Несколько более красивый код в окне: защищенное переопределение void OnSourceInitialized (EventArgs e) {base.OnSourceInitialized (e); this.HideMinimizeAndMaximizeButtons (); }
Дмитрий Шехтман
1
Почему бы не сделать его еще проще и не подписаться на событие SourceInitialized прямо в методе HideMinimizeAndMaximizeButtons ()? Затем вы можете вызвать метод из конструктора и больше ничего не делать.
jmatthias
1
это решение не распространяется на двойной щелчок по строке заголовка.
Lonli-Lokli
1
Записка о воскресении! Метод должен быть помещен в событие Windows Loaded, поскольку дескриптор не определен в событии Initialized.
SezMe
4
После всего этого времени, зная, что эта функциональность присутствует в формах Windows, я просто не понимаю, что Microsoft не поместила такую ​​функциональность в WPF с самого начала. Откровенно говоря, диалог с полем минимизации и развернутой книгой выглядит непрофессионально, и двойной щелчок по строке заголовка - та же проблема. Извините, что немного преувеличиваю мое разочарование по поводу WPF, он очень хорош и имеет строковые активы, но время от времени вы натыкаетесь на что-то, что должно быть простым, что в конечном итоге не так.
Филип Стейк 09
92

Один из способов - установить ваш ResizeMode="NoResize". Он будет вести себя так. введите описание изображения здесь

Надеюсь, это поможет!

Musikero31
источник
33
Это сделало бы окно не изменяемым, что прямо противоречит вопросу.
Машмагар
5
Обычно гуглеры, которые ищут способ отключить кнопки сворачивания и разворачивания, не имеют особых требований к изменению размера окна. В настоящее время это лучший результат для запроса «wpf window disable минимум», и этот ответ правильно отвечает на вопрос. Как бы то ни было, позор, что MS не сделала строку заголовка или все окно хромом как «просто еще один элемент управления или свойство». Слишком много наследия 90-го ...
Император Орионии
2
В этом случае элементы с динамической шириной (например, DockPanel) по-прежнему могут изменять размер окна. Но уже не пользователь. Итак, этот вариант действительно соответствовал моим требованиям.
OneWorld
4
Не отвечает на вопросы, но был мне полезен. Благодарю.
dkantowitz
@EmperorOrionii, хотя в то время эта страница могла быть лучшим результатом Google, это никоим образом не означает, что этот ответ является лучшим, если вы считаете, что он не касается «Как удалить минимизацию и максимизацию из a resizable windowв WPF?» когда он снимает с «изменяемым» аспектом из готового продукта. Это все равно, что помочь кому-то, кто хочет покрасить свою машину в красный цвет, и при этом вы снимаете двигатель.
MickyD
22

Не знаю, работает ли это для вашего запроса. визуально .. Это

<Window x:Class="DataBinding.MyWindow" ...Title="MyWindow" Height="300" Width="300" 
    WindowStyle="ToolWindow" ResizeMode="CanResizeWithGrip">
Гишу
источник
3
Это почти работает, но по-прежнему можно развернуть или свернуть окно, если дважды щелкнуть строку заголовка, щелкнуть правой кнопкой мыши и использовать меню управления или кнопку на панели задач, если она доступна. Плюс, конечно, это похоже на окно инструментов, а не на обычное.
Nidonocu
Правильно ... но опять же, ИМХО, ограничение кажется странным, что пользователю не разрешено максимизировать, но он может вручную перетаскивать окно, изменяя размер. Но это ваше окно .. ваши правила :)
Gishu
это может быть удобно в ситуациях, когда установлено окно MaxWidthи / или MaxHeightокно.
Бретт Райан
6

Если кто-то использует окно Devexpress (DXWindow), принятый ответ не работает. Один уродливый подход

public partial class MyAwesomeWindow : DXWindow
{
    public MyAwesomeWIndow()
    {
       Loaded += OnLoaded;
    }

    private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        // hides maximize button            
        Button button = (Button)DevExpress.Xpf.Core.Native.LayoutHelper.FindElementByName(this, DXWindow.ButtonParts.PART_Maximize.ToString());
        button.IsHitTestVisible = false;
        button.Opacity = 0;

        // hides minimize button
        button = (Button)DevExpress.Xpf.Core.Native.LayoutHelper.FindElementByName(this, DXWindow.ButtonParts.PART_Minimize.ToString());
        button.IsHitTestVisible = false;
        button.Opacity = 0;

        // hides close button
        button = (Button)DevExpress.Xpf.Core.Native.LayoutHelper.FindElementByName(this, DXWindow.ButtonParts.PART_CloseButton.ToString());
        button.IsHitTestVisible = false;
        button.Opacity = 0;
    } 
}
Эльдар
источник
Я, наверное, прочитал пять разных постов, прежде чем заметил ваш ответ здесь. Это работает, но фу. Вы когда-нибудь находили лучший способ?
DonBoitnott
3

Вот решение, которое я использую. Обратите внимание, что кнопка развертывания все еще отображается.

Разметка:

<Window x:Class="Example"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Example"
        StateChanged="Window_StateChanged">

Код позади:

// Disable maximizing this window
private void Window_StateChanged(object sender, EventArgs e)
{
    if (this.WindowState == WindowState.Maximized)
        this.WindowState = WindowState.Normal;
}
Андрей
источник
1
Он спросил, как скрыть кнопки, но сохранить функциональность.
Alexandru Dicu
Каким бы минимальным оно ни было, окно мерцает. Не очень хорошо.
Mugen
2

Вы можете установить ResizeMode = "NoResize" окна, если хотите удалить кнопки "Свернуть" и "Развернуть".

Чинмай Бехера
источник
1
Эх, но тогда вы не можете изменить его размер, должно быть,
Карстен
0

Этот вариант решения, предложенный @MattHamilton, может (и должен) вызываться в конструкторе Window. Хитрость заключается в том, чтобы подписать делегата на SourceInitializedсобытие в методе расширения.

private const int GWL_STYLE = -16, WS_MAXIMIZEBOX = 0x10000, WS_MINIMIZEBOX = 0x20000;

[DllImport("user32.dll")]
extern private static int GetWindowLong(IntPtr hwnd, int index);

[DllImport("user32.dll")]
extern private static int SetWindowLong(IntPtr hwnd, int index, int value);

/// <summary>
/// Hides the Minimize and Maximize buttons in a Window. Must be called in the constructor.
/// </summary>
/// <param name="window">The Window whose Minimize/Maximize buttons will be hidden.</param>
public static void HideMinimizeAndMaximizeButtons(this Window window)
{
    window.SourceInitialized += (s, e) => {
        IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(window).Handle;
        int currentStyle = GetWindowLong(hwnd, GWL_STYLE);

        SetWindowLong(hwnd, GWL_STYLE, currentStyle & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX);
    };
}
Оливье Жако-Декомб
источник