imran
imran

Reputation: 66

Add button to Window Border

I have a WPF window with property WindowStyle="SingleBorderWindow". Now I want to know how to set a button on left upper corner of the window border.

Upvotes: 0

Views: 1130

Answers (3)

Upendra Chaudhari
Upendra Chaudhari

Reputation: 6543

You need to make custom window by setting transparency, background and style like below :

<Window x:Class="WpfApplication2.Window2" 
            Name="Window2xx" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
        Title="window1"
         xmlns:m="clr-namespace:WpfApplication2"
       AllowsTransparency="True" WindowStyle="None" 
       WindowStartupLocation="CenterOwner" d:DesignWidth="410" StateChanged="Window_StateChanged" 
        SizeToContent="WidthAndHeight" ShowInTaskbar="False" Background="Transparent">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Style.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <m:MasterWindow Width="400">
            <m:MasterWindow.WindowTitle>
                <ContentPresenter Content="window1"  MouseLeftButtonDown="Window_MouseLeftButtonDown"></ContentPresenter>
            </m:MasterWindow.WindowTitle>
            <m:MasterWindow.Content>
                <Grid>
                </Grid>
            </m:MasterWindow.Content>
        </m:MasterWindow>
    </Grid>
</Window> 

Code behind window2 :

namespace WpfApplication2
{
    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();
        }

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

        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                DragMove();
            }
            catch ()
            {}
        }

}
    }

Master window is like below :

namespace WpfApplication2
{
    public class MasterWindow : ContentControl
        {
            public static RoutedCommand CloseWindowCommand;

            static MasterWindow()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(MasterWindow), new FrameworkPropertyMetadata(typeof(MasterWindow)));
                CloseWindowCommand = new RoutedCommand("CloseWindow", typeof(MasterWindow));
                CommandManager.RegisterClassCommandBinding(typeof(MasterWindow), new CommandBinding(CloseWindowCommand, CloseWindowEvent));

            }


            public static readonly DependencyProperty WindowTitleProperty = DependencyProperty.Register("WindowTitle", typeof(object), typeof(MasterWindow), new UIPropertyMetadata());

            public object WindowTitle
            {
                get { return (object)GetValue(WindowTitleProperty); }
                set { SetValue(WindowTitleProperty, value); }
            }

            private static void CloseWindowEvent(object sender, ExecutedRoutedEventArgs e)
            {
                MasterWindow control = sender as MasterWindow;
                if (control != null)
                {
                    Window objWindow = Window.GetWindow(((FrameworkElement)sender));
                    if (objWindow != null)
                    {
                        if (objWindow.Name.ToLower() != "unlockscreenwindow")
                        {
                            Window.GetWindow(((FrameworkElement)sender)).Close();
                        }
                    }
                }
            }
        }  
}

Styles for master window :

 <ResourceDictionary  
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
    mc:Ignorable="d" 
    xmlns:local="clr-namespace:WpfApplication2" 
    x:Class="MasterWindow">

    <Style x:Key="WindowTitle" TargetType="ContentPresenter">
        <Setter Property="Control.FontFamily" Value="Segoe UI"></Setter>
        <Setter Property="Control.FontSize" Value="14"></Setter>
        <Setter Property="Control.FontWeight" Value="SemiBold"></Setter>
        <Setter Property="Control.Foreground" Value="White"></Setter>
        <Setter Property="Control.VerticalAlignment" Value="Top"></Setter>
        <Setter Property="Control.HorizontalAlignment" Value="Left"></Setter>
        <Setter Property="Control.VerticalContentAlignment" Value="Top"></Setter>
    </Style>

    <Style x:Key="closebutton" BasedOn="{x:Null}" TargetType="{x:Type Button}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid>
                        <Rectangle 
                                    Opacity="1" 
                                    RadiusX="2" 
                                    RadiusY="2" 
                                    Stroke="#ffffff" 
                                    StrokeThickness="1">
                            <Rectangle.Fill>
                                <LinearGradientBrush 
                                            StartPoint="0.6190476190476191,-0.5" 
                                            EndPoint="1.1128888811383928,1.426776123046875">
                                    <LinearGradientBrush.GradientStops>
                                        <GradientStopCollection>
                                            <GradientStop 
                                                        Color="#2E4C87" 
                                                        Offset="0" />
                                            <GradientStop 
                                                        Color="#FFffffff" 
                                                        Offset="1" />
                                        </GradientStopCollection>
                                    </LinearGradientBrush.GradientStops>
                                </LinearGradientBrush>
                            </Rectangle.Fill>
                        </Rectangle>
                        <Path 
                                    Margin="5,5,5,5" 
                                    Stretch="Fill" 
                                    Opacity="1" 
                                    Data="M 808.8311767578125,278.7662353515625 C808.8311767578125,278.7662353515625 820,268 820,268 " 
                                    Stroke="#ffffff" 
                                    StrokeThickness="2" />
                        <Path 
                                    Margin="5,5,5,5" 
                                    Stretch="Fill" 
                                    Opacity="1" 
                                    Data="M 809.4155883789062,268.3636474609375 C809.4155883789062,268.3636474609375 820,279 820,279 " 
                                    Stroke="#ffffff" 
                                    StrokeThickness="2" />
                        <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsFocused" Value="True"/>
                        <Trigger Property="IsDefaulted" Value="True"/>
                        <Trigger Property="IsMouseOver" Value="True"/>
                        <Trigger Property="IsPressed" Value="True"/>
                        <Trigger Property="IsEnabled" Value="False"/>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style TargetType="{x:Type local:MasterWindow}">
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MasterWindow}">
                    <StackPanel>
                        <Border x:Name="border" Background="WhiteSmoke" BorderBrush="#2E4C87" BorderThickness="7" CornerRadius="8,8,8,8" >
                            <Border.BitmapEffect>
                                <DropShadowBitmapEffect Color="Black" Direction="320" Opacity="0.75" ShadowDepth="8"></DropShadowBitmapEffect>
                            </Border.BitmapEffect>
                            <Border.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform ScaleX="0.95" ScaleY="0.95"/>
                                    <SkewTransform AngleX="0" AngleY="0"/>
                                    <RotateTransform Angle="0"/>
                                    <TranslateTransform X="0" Y="0"/>
                                </TransformGroup>
                            </Border.RenderTransform>
                            <Border.Triggers>
                                <EventTrigger RoutedEvent="Border.Loaded">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" From="0" To="0.96" Duration="0:0:0.6"/>
                                            <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" From="0" To="0.96" Duration="0:0:0.6"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                            </Border.Triggers>

                            <Grid HorizontalAlignment="Stretch" >
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="32"></RowDefinition>
                                    <RowDefinition Height="*" />
                                </Grid.RowDefinitions>
                                <Border BorderThickness="5,5,3,0"  Background="#2E4C87" BorderBrush="#2E4C87" CornerRadius="5,4,0,0" VerticalAlignment="Top" Height="32" Margin="-6,-6,-4,0" >
                                    <Grid Background="Transparent" HorizontalAlignment="Stretch" Height="32" VerticalAlignment="Center"  >
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="30"/>
                                        </Grid.ColumnDefinitions>
                                        <ContentPresenter Content="{TemplateBinding WindowTitle}" Margin="0,4,0,0" HorizontalAlignment="Stretch"  Style="{StaticResource WindowTitle}" />
                                        <Button Name="btnClose" Style="{StaticResource closebutton}" Cursor="Hand" Command="{x:Static local:MasterWindow.CloseWindowCommand}" VerticalAlignment="Top" Height="18" HorizontalAlignment="Right" Width="18" Margin="0,5,8,0" Grid.Column="1" />
                                    </Grid>
                                </Border>
                                <Border BorderBrush="Transparent" BorderThickness="7,0,7,7" VerticalAlignment="Top" HorizontalAlignment="Left" CornerRadius="0,0,10,10" Grid.Row="1"></Border>
                                <ContentPresenter Grid.Row="1" Content="{TemplateBinding Content}" VerticalAlignment="Top" Margin="0,-6,0,0"/>
                            </Grid>
                        </Border>

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

</ResourceDictionary> 

Upvotes: 0

Dennis
Dennis

Reputation: 20561

I assume this is so you can re-create the Minimize/Maximize/Close buttons.

You have two options, use a Grid or a DockPanel. I have included a sample for a Grid below.

<Grid>
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="*" />
     <Grid.RowDefinitions>
     <StackPanel Orientation="Horizontal" Margin="2,0" HorizontalAlignment="Right" VerticalAlignment="Top">
     </StackPanel>
</Grid>

A Grid with a RowDefinition Height="Auto" that has a StackPanel Orientation="Horizontal" that is right-aligned.


However

If you want to make a true border-less window, you will have more work to do than simply setting the WindowStyle to None.

One main stumbling block I encountered was that when WindowStyle is None, it will not respect the task bar (i.e. overlap it) and you will need to hook into the message pump to set the correct window constraints.

Let me know in the comments if you want to know how to do this, will happy post sample code.

Upvotes: 0

bartosz.lipinski
bartosz.lipinski

Reputation: 2667

You probably need to use window chrome library which is described here.

Upvotes: 3

Related Questions