How to create custom window chrome in wpf?

被刻印的时光 ゝ 提交于 2019-12-17 02:55:12

问题


How can I create a basic custom window chrome for a WPF window, that doesn't include the close button and still a moveable and resizeable window?


回答1:


You set your Window's WindowStyle="None", then build your own window interface. You need to build in your own Min/Max/Close/Drag event handlers, but Resizing is still maintained.

For example:

<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" DockPanel.Dock="Top">
            <Button x:Name="CloseButton" Content="X"
                    Click="CloseButton_Click"                 
                    DockPanel.Dock="Right" />
            <Button x:Name="MaxButton" Content="Restore" 
                    Click="MaximizeButton_Click"
                    DockPanel.Dock="Right" />
            <Button x:Name="MinButton" Content="Min"
                    Click="MinimizeButton_Click"
                    DockPanel.Dock="Right" />

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

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

</Window>

And here's some example code-behind for common window functionality

/// <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";
    }

}



回答2:


.NET 4.5 added a new class that greatly simplifies this.

The WindowChrome class enables you to extend Windows Presentation Foundation (WPF) content into the non-client area of a window that is typically reserved for the operating system’s window manager.

You can find a tutorial here.

And here's a short example usage.




回答3:


I've just used the example below for .net 4.5 and it works very well. Interestingly, it uses a code behind for a resource dictionary for the click events. All you have to do is reference the resource dictionary in your app.xaml file and then assign the Window the Style CustomWindowStyle. This was shamelessly stolen from 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>

And for the code behind:

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



回答4:


Here is an easy solution which looks very similar to the default Windows 10 buttons, it simply uses the same Font for the symbols:

<StackPanel Orientation="Horizontal" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True">
<Button Click="Minimize_Click" Content="&#xE949;" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,15,15,5" Background="Transparent" BorderBrush="Transparent" />
<Button Click="Maximize_Click" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,10" Background="Transparent" BorderBrush="Transparent">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Button.Content" Value="&#xE739;" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=WindowState}" Value="Maximized">
                    <Setter Property="Button.Content" Value="&#xE923;" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>
<Button Click="Close_Click" Content="&#xE106;" FontFamily="Segoe MDL2 Assets" FontSize="10" Padding="15,10" Background="Transparent" BorderBrush="Transparent" />
</StackPanel>

If you want Support for older Windows Versions (7 and 8) have a look here: https://stackoverflow.com/a/27911618/9758687



来源:https://stackoverflow.com/questions/6792275/how-to-create-custom-window-chrome-in-wpf

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!