2011-07-22 29 views
26

¿Cómo puedo crear una ventana personalizada básica de cromo para una ventana de WPF, que no incluye el botón de cerrar y sigue siendo una ventana movible y redimensionable?¿Cómo crear una ventana personalizada de cromo en wpf?

+1

http://blogs.msdn.com/b/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf .aspx – BoltClock

+0

Lo comprobé ... pero estaba buscando más de un tutorial ... –

+0

Una pregunta antigua, pero aún relevante aquí: [Creando Windows Bordless con visual personalizada] (http://stackoverflow.com/questions/ 2969521/creating-bordless-windows-with-custom-visual/2969652 # 2969652). –

Respuesta

43

Configura tu Ventana WindowStyle="None", luego construye tu propia interfaz de ventana. Necesitas construir tus propios manejadores de eventos Min/Max/Close/Drag, pero aún se mantiene el tamaño.

Por ejemplo:

<Window 
    WindowState="Maximized" 
    WindowStyle="None" 
    WindowStartupLocation="CenterScreen" 
    MaxWidth="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}" 
    MaxHeight="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}" 
> 

    <DockPanel x:Name="RootWindow"> 
     <DockPanel x:Name="TitleBar"> 
      <Button x:Name="CloseButton" DockPanel.Dock="Right" /> 
      <Button x:Name="MaxButton" DockPanel.Dock="Right" /> 
      <Button x:Name="MinButton" DockPanel.Dock="Right" /> 

      <TextBlock HorizontalAlignment="Center">Application Name</TextBlock> 
     </DockPanel> 

     <ContentControl Content="{Binding CurrentPage}" /> 
    </DockPanel> 

</Window> 

Y aquí está un cierto ejemplo de código subyacente para la funcionalidad de la ventana común

/// <summary> 
/// TitleBar_MouseDown - Drag if single-click, resize if double-click 
/// </summary> 
private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e) 
{ 
    if(e.ChangedButton == MouseButton.Left) 
     if (e.ClickCount == 2) 
     { 
      AdjustWindowSize(); 
     } 
     else 
     { 
      Application.Current.MainWindow.DragMove(); 
     } 
} 

/// <summary> 
/// CloseButton_Clicked 
/// </summary> 
private void CloseButton_Click(object sender, RoutedEventArgs e) 
{ 
    Application.Current.Shutdown(); 
} 

/// <summary> 
/// MaximizedButton_Clicked 
/// </summary> 
private void MaximizeButton_Click(object sender, RoutedEventArgs e) 
{ 
    AdjustWindowSize(); 
} 

/// <summary> 
/// Minimized Button_Clicked 
/// </summary> 
private void MinimizeButton_Click(object sender, RoutedEventArgs e) 
{ 
    this.WindowState = WindowState.Minimized; 
} 

/// <summary> 
/// Adjusts the WindowSize to correct parameters when Maximize button is clicked 
/// </summary> 
private void AdjustWindowSize() 
{ 
    if (this.WindowState == WindowState.Maximized) 
    { 
     this.WindowState = WindowState.Normal; 
     MaximizeButton.Content = "1"; 
    } 
    else 
    { 
     this.WindowState = WindowState.Maximized; 
     MaximizeButton.Content = "2"; 
    } 

} 
+0

+1 - buena solución para la manipulación de mouse en la barra de título –

+2

En realidad, el uso de esta aplicación -vs- principal de ventana -vs- es un poco agitado (como propenso a errores). Alex tenía una [implementación] más sólida (http://web.archive.org/web/20081006142447/http://blog.opennetcf.com/ayakhnin/PermaLink,guid,23a7be17-d833-4e45-b498-34ef04d98cb2.aspx) , aunque también omite algunas piezas funcionales menores. –

+2

Probablemente también quieras 'DockPanel.Dock =" Top "' en el panel de puertos 'Titlebar'. – Aaron

35

.NET 4.5 añade una nueva clase que simplifica en gran medida esto.

El WindowChrome class le permite ampliar el contenido de Windows Presentation Foundation (WPF) en la zona de no cliente de una ventana que está típicamente reservado para gestor de ventanas del sistema operativo.

Puede encontrar un tutorial here.

Y aquí hay un short example usage.

+0

El tutorial está lleno de enlaces inactivos e información obsoleta, y el ejemplo breve incluye una referencia de ensamblado que ya no funciona. –

+0

Gracias por avisarme. Si encuentro algo mejor, lo publicaré. – dss539

1

Acabo de utilizar el ejemplo a continuación para .net 4.5 y funciona muy bien. Curiosamente, utiliza un código detrás de un diccionario de recursos para los eventos de clic. Todo lo que tiene que hacer es hacer referencia al diccionario de recursos en su archivo app.xaml y luego asignarle a la ventana el Estilo CustomWindowStyle. Esto fue descaradamente robado de http://www.eidias.com/blog/2014/1/27/restyle-your-window.

<ResourceDictionary x:Class="WpfApp7.WindowStyle" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 


    <Style x:Key="CustomWindowStyle" TargetType="{x:Type Window}"> 
     <Setter Property="WindowChrome.WindowChrome"> 
      <Setter.Value> 
       <WindowChrome CaptionHeight="30" 
           CornerRadius="4" 
           GlassFrameThickness="0" 
           NonClientFrameEdges="None" 
           ResizeBorderThickness="5" 
           UseAeroCaptionButtons="False" /> 
      </Setter.Value> 
     </Setter> 

     <Setter Property="BorderBrush" Value="Black" /> 
     <Setter Property="Background" Value="Gray" /> 

     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type Window}"> 
        <Grid> 
         <Border Background="{TemplateBinding Background}" 
           BorderBrush="{TemplateBinding BorderBrush}" 
           BorderThickness="5,30,5,5"> 
          <AdornerDecorator> 
           <ContentPresenter /> 
          </AdornerDecorator> 
         </Border> 

         <Grid Height="30" 
          VerticalAlignment="Top"> 

          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="Auto"/> 
           <ColumnDefinition Width="*"/> 
           <ColumnDefinition Width="Auto"/> 
          </Grid.ColumnDefinitions> 

          <StackPanel Orientation="Horizontal" Margin="5,0"> 
           <Button Content="A" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/> 
           <Button Content="B" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/> 
           <Button Content="C" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/> 
           <Button Content="D" Margin="0,0,5,0" VerticalAlignment="Center" Click="Button_Click" WindowChrome.IsHitTestVisibleInChrome="True"/> 
          </StackPanel> 


          <TextBlock Margin="5,0,0,0" 
             VerticalAlignment="Center" 
             HorizontalAlignment="Center" 
             FontSize="16" 
             Foreground="White" 
             Text="{TemplateBinding Title}" 
             Grid.Column="1"/> 


          <StackPanel Orientation="Horizontal" 
             Grid.Column="2"> 
           <Button x:Name="btnClose" 
            Width="15" 
            Margin="5" 
            Click="CloseClick" 
            Content="X" 
            WindowChrome.IsHitTestVisibleInChrome="True" /> 


           <Button x:Name="btnRestore" 
            Width="15" 
            Margin="5" 
            Click="MaximizeRestoreClick" 
            Content="#" 
            WindowChrome.IsHitTestVisibleInChrome="True" /> 

           <Button x:Name="btnMinimize" 
            Width="15" 
            Margin="5" 
            VerticalContentAlignment="Bottom" 
            Click="MinimizeClick" 
            Content="_" 
            WindowChrome.IsHitTestVisibleInChrome="True" /> 
          </StackPanel> 
         </Grid> 

        </Grid> 

       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

Y para el código subyacente:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 

namespace WpfApp7 
{ 
    public partial class WindowStyle : ResourceDictionary 
    { 
     public WindowStyle() 
     { 
      InitializeComponent(); 
     } 

     private void CloseClick(object sender, RoutedEventArgs e) 
     { 
      var window = (Window)((FrameworkElement)sender).TemplatedParent; 
      window.Close(); 
     } 

     private void MaximizeRestoreClick(object sender, RoutedEventArgs e) 
     { 
      var window = (Window)((FrameworkElement)sender).TemplatedParent; 
      if (window.WindowState == System.Windows.WindowState.Normal) 
      { 
       window.WindowState = System.Windows.WindowState.Maximized; 
      } 
      else 
      { 
       window.WindowState = System.Windows.WindowState.Normal; 
      } 
     } 

     private void MinimizeClick(object sender, RoutedEventArgs e) 
     { 
      var window = (Window)((FrameworkElement)sender).TemplatedParent; 
      window.WindowState = System.Windows.WindowState.Minimized; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      MessageBox.Show("Hello!"); 
     } 
    } 
} 
Cuestiones relacionadas