Skip to content

Instantly share code, notes, and snippets.

@fabric-io-rodrigues
Created June 8, 2020 01:47
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabric-io-rodrigues/4cd83f1aeb41dc8f60fe9535184cbe10 to your computer and use it in GitHub Desktop.
Save fabric-io-rodrigues/4cd83f1aeb41dc8f60fe9535184cbe10 to your computer and use it in GitHub Desktop.
Changing WPF title bar background color - HardMode :-)

I don't know if there is any easy way, without using external components, but I just wanted to change the background color of a screen in WPF. It was a saga. I had to: 1. Create custom buttons (with the same font used in Windows 10) 2. Disable WindowStyle and ResizeMode. 3. Define functionality to move the window (DragWindow) with 1 click, restore the window (Maximizing or Restoring) with 2 clicks. 4. Resize mode (custom) using Rectangles 5. Set maximum window size, so as not to overlap the taskbar. 6. Create icon and Text to use as Title of the application.

<Application x:Class="BasicApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup"
Exit="Application_Exit">
<Application.Resources>
<Style x:Key="CaptionButtonStyleDefault" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="LayoutRoot" Background="Transparent" Width="46" Height="30">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" FontFamily="Segoe MDL2 Assets" FontSize="10"
Foreground="#E5E5E5" HorizontalAlignment="Center" VerticalAlignment="Center"
RenderOptions.ClearTypeHint="Auto" TextOptions.TextRenderingMode="Aliased" TextOptions.TextFormattingMode="Display"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="LayoutRoot" Property="Background" Value="#E5E5E5"/>
<Setter TargetName="txt" Property="Foreground" Value="#000000"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CaptionButtonStyleClose" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="LayoutRoot" Background="Transparent" Width="46" Height="30">
<TextBlock x:Name="txt" Text="{TemplateBinding Content}" FontFamily="Segoe MDL2 Assets" FontSize="10"
Foreground="#E5E5E5" HorizontalAlignment="Center" VerticalAlignment="Center"
RenderOptions.ClearTypeHint="Auto" TextOptions.TextRenderingMode="Aliased" TextOptions.TextFormattingMode="Display"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="LayoutRoot" Property="Background" Value="#E81123"/>
<Setter TargetName="txt" Property="Foreground" Value="#FFFFFF"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="MinimizeButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyleDefault}">
<Setter Property="Content" Value="&#xE949;"/>
</Style>
<Style x:Key="MaximizeButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyleDefault}">
<Setter Property="Content" Value="&#xE739;"/>
</Style>
<Style x:Key="RestoreButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyleDefault}">
<Setter Property="Content" Value="&#xE923;"/>
</Style>
<Style x:Key="CloseButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyleClose}">
<Setter Property="Content" Value="&#xE8BB;"/>
</Style>
</Application.Resources>
</Application>
<Window x:Class="BasicApp.Window1"
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"
Title="Window1" Height="450" Width="800"
MinHeight="30" MinWidth="250" WindowStyle="None" ResizeMode="CanMinimize" WindowState="Maximized">
<Window.Resources>
<Style x:Key="RectBorderStyle" TargetType="Rectangle">
<Setter Property="Focusable" Value="False" />
<Setter Property="Fill" Value="Transparent" />
<Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}" />
<EventSetter Event="MouseLeftButtonDown" Handler="Resize_Init"/>
<EventSetter Event="MouseLeftButtonUp" Handler="Resize_End"/>
<EventSetter Event="MouseMove" Handler="Resizeing_Form"/>
</Style>
</Window.Resources>
<Grid>
<Grid MouseDown="StackPanel_MouseDown" VerticalAlignment="Top" Margin="0" Background="#3e4a59">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image x:Name="HeaderIcon" Grid.Column="0" Width="20" Height="20" Margin="5, 4, 5, 4" HorizontalAlignment="Left" />
<TextBlock x:Name="HeaderTitle" Grid.Column="1" Margin="5" TextAlignment="Left" Foreground="#FFFFFF" FontSize="13" HorizontalAlignment="Left" />
<StackPanel Grid.Column="2" VerticalAlignment="Top" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="MinimizeButton" Style="{DynamicResource MinimizeButtonStyle}" Click="MinimizeWindow" KeyboardNavigation.IsTabStop="False" />
<Button x:Name="MaximizeButton" Style="{DynamicResource MaximizeButtonStyle}" Click="MaximizeClick" KeyboardNavigation.IsTabStop="False" />
<Button x:Name="CloseButton" Style="{DynamicResource CloseButtonStyle}" Click="CloseButton_Click" KeyboardNavigation.IsTabStop="False" />
</StackPanel>
</Grid>
<Grid Margin="0,30,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="LightBlue">
<!-- Here -->
</Grid>
<Rectangle x:Name="leftSizeGrip" Width="7" HorizontalAlignment="Left" Cursor="SizeWE" Style="{StaticResource RectBorderStyle}" />
<Rectangle x:Name="rightSizeGrip" Width="7" HorizontalAlignment="Right" Cursor="SizeWE" Style="{StaticResource RectBorderStyle}" />
<Rectangle x:Name="topSizeGrip" Height="7" VerticalAlignment="Top" Cursor="SizeNS" Style="{StaticResource RectBorderStyle}" />
<Rectangle x:Name="bottomSizeGrip" Height="7" VerticalAlignment="Bottom" Cursor="SizeNS" Style="{StaticResource RectBorderStyle}" />
<!-- Corners -->
<Rectangle Name="topLeftSizeGrip" Width="7" Height="7" HorizontalAlignment="Left" VerticalAlignment="Top" Cursor="SizeNWSE" Style="{StaticResource RectBorderStyle}" />
<Rectangle Name="bottomRightSizeGrip" Width="7" Height="7" HorizontalAlignment="Right" VerticalAlignment="Bottom" Cursor="SizeNWSE" Style="{StaticResource RectBorderStyle}" />
<Rectangle Name="topRightSizeGrip" Width="7" Height="7" HorizontalAlignment="Right" VerticalAlignment="Top" Cursor="SizeNESW" Style="{StaticResource RectBorderStyle}" />
<Rectangle Name="bottomLeftSizeGrip" Width="7" Height="7" HorizontalAlignment="Left" VerticalAlignment="Bottom" Cursor="SizeNESW" Style="{StaticResource RectBorderStyle}" />
</Grid>
</Window>
using System;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace BasicApp
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
#region ResizeWindows
bool ResizeInProcess = false;
private void Resize_Init(object sender, MouseButtonEventArgs e)
{
Rectangle senderRect = sender as Rectangle;
if (senderRect != null)
{
ResizeInProcess = true;
senderRect.CaptureMouse();
}
}
private void Resize_End(object sender, MouseButtonEventArgs e)
{
Rectangle senderRect = sender as Rectangle;
if (senderRect != null)
{
ResizeInProcess = false; ;
senderRect.ReleaseMouseCapture();
}
}
private void Resizeing_Form(object sender, MouseEventArgs e)
{
if (ResizeInProcess)
{
Rectangle senderRect = sender as Rectangle;
Window mainWindow = senderRect.Tag as Window;
if (senderRect != null)
{
double width = e.GetPosition(mainWindow).X;
double height = e.GetPosition(mainWindow).Y;
senderRect.CaptureMouse();
if (senderRect.Name.ToLower().Contains("right"))
{
width += 5;
if (width > 0)
mainWindow.Width = width;
}
if (senderRect.Name.ToLower().Contains("left"))
{
width -= 5;
mainWindow.Left += width;
width = mainWindow.Width - width;
if (width > 0)
{
mainWindow.Width = width;
}
}
if (senderRect.Name.ToLower().Contains("bottom"))
{
height += 5;
if (height > 0)
mainWindow.Height = height;
}
if (senderRect.Name.ToLower().Contains("top"))
{
height -= 5;
mainWindow.Top += height;
height = mainWindow.Height - height;
if (height > 0)
{
mainWindow.Height = height;
}
}
}
}
}
#endregion
#region TitleButtons
private void MinimizeWindow(object sender, RoutedEventArgs e)
{
App.Current.MainWindow.WindowState = WindowState.Minimized;
}
private void MaximizeClick(object sender, RoutedEventArgs e)
{
AdjustWindowSize();
}
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
if (e.ClickCount == 2)
{
AdjustWindowSize();
}
else
{
App.Current.MainWindow.DragMove();
}
}
}
private void AdjustWindowSize()
{
if (App.Current.MainWindow.WindowState == WindowState.Maximized)
{
App.Current.MainWindow.WindowState = WindowState.Normal;
MaximizeButton.Content = "";
}
else if (App.Current.MainWindow.WindowState == WindowState.Normal)
{
App.Current.MainWindow.WindowState = WindowState.Maximized;
MaximizeButton.Content = "";
}
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
App.Current.MainWindow.Close();
}
#endregion
public Window1()
{
InitializeComponent();
//limit for height to not overlay system taskbar
this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
HeaderIcon.Source = BitmapFrame.Create(new Uri("pack://application:,,,/IconApp.ico", UriKind.RelativeOrAbsolute));
HeaderTitle.Text = "Title of Window";
}
}
}
@fabric-io-rodrigues
Copy link
Author

image

@cvdevol
Copy link

cvdevol commented Apr 27, 2021

When Maximized, the lower edge of the window goes behind the TaskBar, obscuring whatever is at the bottom edge of the window.

@CsCode000
Copy link

When resizing window, the Resize_End is called before the mouse button is released.

adding this line to the top of Resize_End, prevent this issue

if (e.LeftButton == MouseButtonState.Pressed) return;

@rudy-rojas
Copy link

If you need to change ResizeMode="CanMinimize" to ResizeMode="CanResize", don't forget to add the <WindowChrome.WindowChrome> tag inside the <Window> tag

<Window ...> 
     <WindowChrome.WindowChrome>
       <WindowChrome CaptionHeight="0" ResizeBorderThickness="5" />  
     </WindowChrome.WindowChrome>
   ...
</Window>

That will remove the top white border.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment