Page 1 of 1

C# WPF custom title bar tutorial Learn how to make your own title bar using C# and WPF

#1 ls_nerd  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 5
  • View blog
  • Posts: 23
  • Joined: 30-January 09

Posted 21 August 2009 - 12:28 PM

In this tutorial I'm going to show you how to make your own title bar using WPF, please note that we will not change the existing title bar.
The result looks like this:
Attached ImageAttached Image

Step 1 - preparations:
Create a new WPF application and set the window properties "WindowStyle" and "Background" to "None" and "Transparent" respectively.
Now you should end up with a completely transparent window, when running the project.

Step 2 - Create the actual title bar:
Now we need to switch to "xaml view" and add some rectangles:
<!--this goes into the "<grid>" section -->
<Rectangle Height="77" Width="5" VerticalAlignment="Top" HorizontalAlignment="Left" MouseDown="move_window">
			<Rectangle.Fill>
				<ImageBrush ImageSource="UI_RES\Title_top_left.png" /> <!-- could be solidcolor as well -->
			</Rectangle.Fill>
		</Rectangle>
<Rectangle Height="77" Margin="5,0,5,0" VerticalAlignment="Top" HorizontalAlignment="Stretch" MouseDown="move_window">
			<Rectangle.Fill>
				<ImageBrush ImageSource="UI_RES\Title_top_middle.png" /> <!-- could be solidcolor as well -->
			</Rectangle.Fill>
		</Rectangle>
<Rectangle Height="77" Width="5" VerticalAlignment="Top" HorizontalAlignment="Right" MouseDown="move_window">
			<Rectangle.Fill>
				<ImageBrush ImageSource="UI_RES\Title_top_right.png" /> <!-- could be solidcolor as well -->
			</Rectangle.Fill>
		</Rectangle>


As you can see I added three rectangles (because I wanted rounded corners) and set the center rectangle to "stretch" (this way you can maximize without loosing your title bar). Now we need some C# code (yourwindow.xaml.cs) to move the window:

using System.Runtime.InteropServices;
using System.Windows.Interop;

public const int WM_NCLBUTTONDOWN = 0xA1;
		public const int HT_CAPTION = 0x2;

		[DllImportAttribute("user32.dll")]
		public static extern int SendMessage(IntPtr hWnd, int Msg, 
				int wParam, int lParam);

		[DllImportAttribute("user32.dll")]
		public static extern bool ReleaseCapture();

		public void move_window(object sender, MouseButtonEventArgs e)
		{
			ReleaseCapture();
			SendMessage(new WindowInteropHelper(this).Handle,
				WM_NCLBUTTONDOWN, HT_CAPTION, 0);
		}


Step 3 - Adding icons to close, maximize and minimize:
Now we add the xaml code to create the three buttons and add the events. I decided to go for brushes in the resource section to describe the different states...
<!--this goes into the "<window>" section -->
<Grid.Resources>
			<ImageBrush x:Key="Close_inact" ImageSource="UI_RES\Close_inact.png" />
			<ImageBrush x:Key="Min_inact" ImageSource="UI_RES\Minimize_inact.png" />
			<ImageBrush x:Key="Max_inact" ImageSource="UI_RES\Maximize_inact.png" />
			<ImageBrush x:Key="Close_act" ImageSource="UI_RES\Close_act.png" />
			<ImageBrush x:Key="Min_act" ImageSource="UI_RES\Minimize_act.png" />
			<ImageBrush x:Key="Max_act" ImageSource="UI_RES\Maximize_act.png" />
			<ImageBrush x:Key="Close_pr" ImageSource="UI_RES\Close_pr.png" />
			<ImageBrush x:Key="Min_pr" ImageSource="UI_RES\Minimize_pr.png" />
			<ImageBrush x:Key="Max_pr" ImageSource="UI_RES\Maximize_pr.png" />
		</Grid.Resources>

<!--this goes into the "<grid>" section -->
<Rectangle Margin="8,4,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"
				   Width="56" Height="15" Fill="Transparent"
				   MouseEnter="Activate_Title_Icons" MouseLeave="Deactivate_Title_Icons" />
<Ellipse Margin="8,4,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" 
				 Width="14" Height="15" MouseLeftButtonUp="EXIT" 
				 MouseEnter="Activate_Title_Icons" MouseLeave="Deactivate_Title_Icons" 
				 MouseLeftButtonDown="Close_pressing" Name="Close_btn" 
				 Fill="{DynamicResource Close_inact}" />
		<Ellipse Margin="29,4,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" 
				 Width="14" Height="15" MouseLeftButtonUp="MINIMIZE" 
				 MouseEnter="Activate_Title_Icons" MouseLeave="Deactivate_Title_Icons" 
				 MouseLeftButtonDown="Min_pressing" Name="Min_btn" 
				 Fill="{StaticResource Min_inact}" />
		<Ellipse Margin="50,4,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" 
				 Width="14" Height="15" MouseLeftButtonUp="MAX_RESTORE" 
				 MouseEnter="Activate_Title_Icons" MouseLeave="Deactivate_Title_Icons" 
				 MouseLeftButtonDown="Max_pressing" Name="Max_btn" 
				 Fill="{StaticResource Max_inact}" />

I added an additional rectangle to describe the hover effect on all three icons(just like the real osx does it).
Now we need the c# code to handle all those events.
private void EXIT(object sender, MouseButtonEventArgs e)
		{
			Environment.Exit(0);
		}

		private void MINIMIZE(object sender, MouseButtonEventArgs e)
		{
			this.WindowState = WindowState.Minimized;
		}

		private void MAX_RESTORE(object sender, MouseButtonEventArgs e)
		{
			if (this.WindowState == WindowState.Normal) this.WindowState = WindowState.Maximized;
			else this.WindowState = WindowState.Normal;
		}

		private void Activate_Title_Icons(object sender, MouseEventArgs e)
		{
			//hover effect, make sure your grid is named "Main" or replace "Main" with the name of your grid
			Close_btn.Fill = (ImageBrush)Main.Resources["Close_act"];
			Min_btn.Fill = (ImageBrush)Main.Resources["Min_act"];
			Max_btn.Fill = (ImageBrush)Main.Resources["Max_act"];
		}

		private void Deactivate_Title_Icons(object sender, MouseEventArgs e)
		{
			Close_btn.Fill = (ImageBrush)Main.Resources["Close_inact"];
			Min_btn.Fill = (ImageBrush)Main.Resources["Min_inact"];
			Max_btn.Fill = (ImageBrush)Main.Resources["Max_inact"];
		}

		private void Close_pressing(object sender, MouseButtonEventArgs e)
		{
			Close_btn.Fill = (ImageBrush)Main.Resources["Close_pr"];
		}

		private void Min_pressing(object sender, MouseButtonEventArgs e)
		{
			Min_btn.Fill = (ImageBrush)Main.Resources["Min_pr"];
		}

		private void Max_pressing(object sender, MouseButtonEventArgs e)
		{
			Max_btn.Fill = (ImageBrush)Main.Resources["Max_pr"];
		}



I hope this tutorial helped you on your journey away from crappy windows classic design.
And the visual studio solution:Attached File  Custom_title_bar.zip (120.57K)
Number of downloads: 4442

This post has been edited by ls_nerd: 22 August 2009 - 01:39 AM


Is This A Good Question/Topic? 1
  • +

Replies To: C# WPF custom title bar tutorial

#2 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 148
  • View blog
  • Posts: 1,589
  • Joined: 16-December 08

Posted 21 August 2009 - 01:24 PM

Great tut!
Was This Post Helpful? 0
  • +
  • -

#3 verogabri  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 02-November 09

Posted 02 November 2009 - 03:51 PM

Fantastic!!
:^: :^:
Was This Post Helpful? 0
  • +
  • -

#4 Guest_Brian*


Reputation:

Posted 24 February 2010 - 10:50 PM

I tried downloading the zip file but it seems corrupt. It's only about 70k and winzip finds nothing in it.

Thanks
Brian
Was This Post Helpful? 0

#5 bpoojary  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 29-August 11

Posted 29 August 2011 - 05:44 AM

Hi i noticed that when you double click on title bar the window dosent changes its state.

So i have modified the code to do that.

You can us ethis link to see how to add MouseDoubleClick on rectangle How-to-add-a-mousedoubleclick-event-to-any-wpf-control/.

And use this code in your code.

  private void RectangleWrapper_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
            {
                this.WindowState = WindowState.Normal;
            }
            else if (this.WindowState == WindowState.Normal)
            {
                this.WindowState = WindowState.Maximized;
            }
        }


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1