2011-07-22 11 views
26

Jak utworzyć podstawowy niestandardowy karnacji okna dla okna WPF, który nie zawiera przycisku zamykania i nadal jest ruchomy i ma rozmiar okna?Jak utworzyć niestandardowe okno chrome w wpf?

+1

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

+0

Sprawdziłem to ... ale szukałem więcej samouczka ... –

+0

Dawne, ale wciąż aktualne pytanie: [Tworzenie systemu Bordless Windows z niestandardowym obrazem] (http://stackoverflow.com/questions/ 2969521/tworzenie-bordless-windows-with-custom-visual/2969652 # 2969652). –

Odpowiedz

43

Ustawiasz okno na WindowStyle="None", a następnie budujesz własny interfejs okna. Musisz zbudować własne funkcje obsługi zdarzeń Min/Max/Zamknij/Przeciągnij, ale zmiana rozmiaru jest nadal zachowywana.

Na przykład:

<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> 

A oto kilka przykładów kodu źródłowego dla funkcjonalności wspólne okna

/// <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 - dobre rozwiązanie dla obsługi pasku tytułowego –

+2

Właściwie użycie tego -vs- głównego okna -vs- aplikacja jest nieco gorączkowa (jak w przypadku podatności na błędy). Alex miał mocniejszą [implementację] (http://web.archive.org/web/20081006142447/http://blog.opennetcf.com/ayakhnin/PermaLink,guid,23a7be17-d833-4e45-b498-34ef04d98cb2.aspx) , choć pomija również kilka drobnych elementów funkcjonalnych. –

+2

Prawdopodobnie również chcesz 'DockPanel.Dock =" Top "' na panelu "Titlebar' dockpanel. – Aaron

35

.NET 4.5 dodano nową klasę, która znacznie upraszcza to.

The WindowChrome class pozwala rozszerzyć zawartość Windows Presentation Foundation (WPF) w obszarze non-roboczym okna, które jest zazwyczaj zarezerwowane dla menedżera okien systemu operacyjnego.

Możesz znaleźć tutorial here.

A tutaj jest short example usage.

+0

Samouczek jest pełen martwych łączy i nieaktualnych informacji, a krótki przykład zawiera odwołanie do zestawu, które już nie działa. –

+0

Dzięki za poinformowanie mnie. Jeśli znajdę coś lepszego, opublikuję to. – dss539

1

Właśnie użyłem przykładu poniżej dla .net 4.5 i działa bardzo dobrze. Interesujące jest to, że używa kodu w słowniku zasobów dla zdarzeń kliknięcia. Wszystko, co musisz zrobić, to odwołać się do słownika zasobów w pliku app.xaml, a następnie przypisać okno Styl CustomWindowStyle. Zostało to bezwstydnie skradzione z 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> 

I związany kod:

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!"); 
     } 
    } 
}