Click here to Skip to main content
15,123,585 members
Articles / Desktop Programming / WPF
Article
Posted 29 Dec 2019

Tagged as

Stats

21.8K views
2.4K downloads
6 bookmarked

Use WindowChrome to Customize the Title Bar in WPF

Rate me:
Please Sign up or sign in to vote.
4.05/5 (8 votes)
29 Dec 2019CPOL5 min read
Change the title bar color, or anything else in the Windows chrome of a WPF application

Problem Statement

You can’t modify the Windows Chrome from WPF. You just can’t.

Too Long – Didn’t Read

Copy the sample code into your MainWindow, then modify it to suit your project. If you’re comfortable with WPF, you won’t have any problem with it.

The Long Answer

I recently had to change the title bar color in a WPF application for Windows 10 on a project at work, and although I found all the information I needed on the web, it was scattered across a dozen different sites and it took a while to get it all figured out. I thought it would be nice to have it all packaged up in one article.

The basic concept with the WindowChrome object is that all the default Windows Chrome goes away, and WindowChrome overlays your app with mouse event handlers to replace the functionality that was lost.

What you lose:

  • The Windows title bar, along with its buttons, system menu and window drag behavior
  • The Windows sizing border and its associated behaviors

What you get back:

  • An invisible title bar overlay with system menu, window drag, and title bar button behaviors
  • An invisible window border overlay that handles window sizing events
  • An interesting quirk that occurs when the app is maximized (see Borders and Sizing, below)

The bottom line is that the Chrome is now completely customizable.

Title Bar

What you get for free with WindowChrome is a sizeable title bar that provides:

  • Right-mouse handler to open the system menu
  • Left-mouse handler for the minimize button
  • Left-mouse handler for the maximize/restore button
  • Left-mouse handler for the close button

WindowChrome doesn’t provide any graphics – you get to do that yourself. The sample app shows how to duplicate the images of the Windows title bar buttons, but obviously you can make them look however you want.

Unfortunately, WindowChrome eats all mouse messages in the title bar area. If you want to do anything fancy like tooltips and hover state, you must override the WindowChrome mouse handling. Simply add a button in the desired location and give it the property:

C#
WindowChrome.IsHitTestVisibleInChrome="True"

That turns off WindowChrome mouse handling above your button and lets you take over. The trade off is that you must handle the system calls yourself and handle the logic for maximize vs. restore. But as you see in the sample code, it’s not a big deal.

Borders and Sizing

The default window sizing provided by WindowChrome works well. It handles changing the mouse pointer to the sizing arrow icons, and the default resizable border width seems fine. You can adjust the resize border by setting ResizeBorderThickness. To disable window sizing, simply add:

C#
ResizeBorderThickness="0"

to the WindowChrome declaration in XAML.

The quirk I mentioned in the opening section is that when maximized, WindowChrome causes the app to overflow the screen by 8 pixels (DIPs) in each direction. The size of the maximized app is 16 pixels larger than the viewable screen area, and the app origin is set to (-8, -8) in screen coordinates. To correct for that, you must do something to shrink your app by 8 pixels in each direction when it is maximized.

The white diamond shown in the sample app is to illustrate exactly where the edges of the application are. You can see that the points of the diamond are always touching the edge of the app, whether it’s maximized or not. I accomplish this by adding a border with a thickness of 8 when maximized, and a thickness of 0 otherwise. Obviously, there are other ways you could handle this as well.

The extra 8 pixels are never viewable. On a multi-monitor system, the extra pixels do not overflow onto the adjacent monitor. They’re just phantom pixels that will hide the edges of your app if you don’t account for them. I recommend playing with the border logic in the sample app to get a feel for what’s going on.

Putting It All Together

Without WindowChrome, the sample app would look like this:

Image 1

The specified window height of 200 pixels (DIPs) consists of the default non-client area that Windows controls, and the client area that WPF controls. This client area just happens to contain of a fully functional “fake” title bar sitting at the top of the client area.

With WindowChrome added, the sample app looks like this:

Image 2

The non-client area is gone. The 200-pixel window is filled with the fake title bar and the remaining “client area.” Note that if you’re dropping WindowChrome into an existing application, this will change any sizing arithmetic that includes the non-client area height.

Maximized, the sample app looks like this:

Image 3

The outer 8 pixels of the client area spill off the edge of the screen. As mentioned above, I account for this by adding a border that only shows up when the app is maximized. Specifically, I handle the StateChanged event and switch the border Thickness property between 0 and 8, depending on the value of WindowState. There are other ways you could accomplish the same thing, of course.

Note that the 8 pixels coming and going may affect sizing arithmetic within your app. Be sure to test your UI in both maximized and normal states if you’re using WindowChrome.

One Final Note

The default Windows title bar handles left-click on the application icon to open the system menu. WindowChrome does not do that. It handles right-clicks across the entire title bar to open the system menu, but it doesn’t handle left click on the app icon. If you want that behavior, you can easily add it by following the same pattern as the other title bar buttons.

Thanks for reading!

Special thanks to the nice folks at icon-icons.com for the cool watermelon icon.

History

  • 30th December, 2019: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

R.A.Dain
United States United States
No Biography provided

Comments and Discussions

 
GeneralDetermine accent color in titlebar on WIN10 Pin
Member 150086151-Dec-20 3:54
MemberMember 150086151-Dec-20 3:54 
QuestionThank You Pin
Mr. Nandkishor Sonwale27-Nov-20 15:35
MemberMr. Nandkishor Sonwale27-Nov-20 15:35 
PraiseThank you! Pin
JN at Shutterfly14-Sep-20 4:53
MemberJN at Shutterfly14-Sep-20 4:53 
PraiseThanks! Pin
amb98009-Apr-20 11:09
Memberamb98009-Apr-20 11:09 
Questionchange button styles Pin
Keyvan Kabirnia8-Apr-20 1:53
MemberKeyvan Kabirnia8-Apr-20 1:53 
PraiseThank you very much Pin
Saqo1995s1-Apr-20 0:38
MemberSaqo1995s1-Apr-20 0:38 
QuestionWas it obvious whether you do this or not Pin
Sacha Barber31-Dec-19 0:21
mvaSacha Barber31-Dec-19 0:21 
GeneralMy vote of 5 Pin
John Schroedl30-Dec-19 6:35
professionalJohn Schroedl30-Dec-19 6:35 
Nice writeup, thanks!
SuggestionBroken images Pin
Сергій Ярошко29-Dec-19 22:28
professionalСергій Ярошко29-Dec-19 22:28 
GeneralRe: Broken images Pin
R.A.Dain30-Dec-19 18:36
MemberR.A.Dain30-Dec-19 18:36 
GeneralRe: Broken images Pin
Franc Morales1-Jan-20 16:01
MemberFranc Morales1-Jan-20 16:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.