web-dev-qa-db-fra.com

Désactivez le bouton Agrandir de la fenêtre WPF, en conservant la fonction de redimensionnement intacte

Les fenêtres WPF n'ont donc que quatre options de mode de redimensionnement: NoResize, CanMinimize, CanResize et CanResizeWithGrip. Malheureusement, les options qui permettent le redimensionnement permettent également de maximiser la fenêtre, et celles qui ne me sont pas inutiles.

Existe-t-il une option pour désactiver le bouton Agrandir tout en conservant la fonction de redimensionnement?

Je préférerais des solutions qui n'impliquent pas WinAPI.

40
Peter W.

WPF n'a pas la capacité native de désactiver le bouton Maximiser seul, comme vous pouvez le faire avec WinForms. Vous devrez recourir à un appel WinAPI. Ce n'est pas effrayant:

[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));
}
29
Scott

Désactivé uniquement Agrandir:

ResizeMode="CanMinimize"
64
5573352

Si vous définissez

WindowStyle="ToolWindow"

Dans les propriétés de votre fenêtre, il vous donnera une fenêtre redimensionnable sans boutons de minimisation ou de maximisation en haut. Ce sera carré et le bouton de fermeture est également carré, mais au moins minimiser et maximiser ne sont pas là!

26
TranquilMarmot

Méthode P/Invoke

Le moyen le plus simple d'appeler du code non managé (C++ dans ce cas) à partir de code managé (.NET) consiste à utiliser les services d'invocation de plateforme, souvent également appelés P/Invoke. Vous fournissez simplement au compilateur une déclaration de la fonction non managée et l'appelez comme vous appelleriez n'importe quelle autre méthode gérée. Il existe une méthode SetWindowLong non managée qui peut être utilisée pour modifier un attribut d'une fenêtre spécifiée. Pour pouvoir appeler cette méthode à partir de votre classe de fenêtre WPF à l'aide de P/Invoke, vous ajoutez simplement la déclaration suivante à la classe de fenêtre:

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

L'attribut DllImport spécifie le nom du DLL qui contient la méthode et le mot clé extern indique au compilateur C # que la méthode est implémentée en externe et qu'il ne trouvera aucune implémentation ou corps de méthode pour elle lors de la compilation de l'application. Le premier argument à transmettre à la méthode SetWindowLong est un descripteur pour la fenêtre pour laquelle vous souhaitez désactiver l'un des boutons mentionnés. Vous pouvez obtenir le descripteur d'une fenêtre WPF en créant une instance de la classe WindowInteropHelper gérée. et accéder à sa propriété Handle dans un gestionnaire d'événements pour l'événement SourceInitialized de la fenêtre. Cet événement est déclenché lorsque le handle a été complètement créé. Le deuxième argument de la méthode SetWindowLong spécifie l'attribut ou la valeur de la fenêtre à définir, exprimé sous la forme d'une constante valeur entière. Lorsque vous souhaitez modifier le style de fenêtre, vous devez passer la constante GWL_STYLE (= -16) comme deuxième argument à la méthode.

private const int GWL_STYLE = -16;

Enfin, le troisième argument spécifie la valeur de remplacement. Il existe un ensemble de constantes que vous pouvez utiliser ici:

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

Notez cependant que puisque vous êtes censé passer un DWORD qui spécifie la valeur complète de la "propriété" spécifiée par le deuxième argument, c'est-à-dire le style de fenêtre dans ce cas, vous ne pouvez pas simplement passer aucune de ces constantes par elles-mêmes comme troisième argument. à la méthode. Il existe une autre méthode GetWindowLong qui récupère la valeur actuelle d'une propriété spécifique - encore une fois GWL_STYLE dans ce cas - et vous pouvez ensuite utiliser des opérateurs au niveau du bit pour obtenir la valeur correcte du troisième paramètre à passer à la méthode SetWindowLong. Voici un exemple de code complet de la façon dont vous pouvez par exemple désactiver le bouton de réduction pour une fenêtre dans 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);
 }
}

Désactiver le bouton minimiser revient alors simplement à remplacer la constante WS_MAXIMIZEBOX par la WS_MINIMIZEBOX

9
Shahid Neermunda

Une autre option consiste à intercepter l'événement StateChanged qui est déclenché lorsque la fenêtre est agrandie. Réglez ensuite simplement le WindowState sur "Normal".

Cependant, cela pas cache la boîte de maximisation!

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

Vous pouvez créer une fenêtre personnalisée en définissant WindowStyle sur Aucun, ce qui supprime les boutons Réduire, Agrandir et Fermer et créer vous-même les boutons dont vous avez besoin. Voilà un excellent exemple pour cela:

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

Cela vous donne du travail supplémentaire, mais si vous ne voulez vraiment pas utiliser WinAPI, c'est une option.

1
Programmer