Skip to main content

Bring your WPF apps to life – Snazzy Animated Window Borders

Checkout my project on GitHub showing how to create animated window borders in WPF. Before I explain, watch the video to see what I mean:

To try it out for yourself, download the demo app.

These kinds of animations have a range of applications:

  • Instant feedback, when button is pressed or action performed
  • Loading animations
  • Progress bars, where animation progress = percentage progress
  • Red flashes for warnings/alerts

The project was born while working on my upcoming new WPF application. I wanted a loading animation for a background task, that didn't take up space, and didn't prevent the user continuing using the app. The window borders seem a good place for this. And when the animation is only there for a few seconds, it isn't too distracting.

Older web browsers used to have very thin progress bars while a page was being fetched and rendered, so this doesn't seem too far fetched. In fact many modern web browsers still do, except pages load so fast it tends to be less noticable ... see the Chrome for Android screenshot below.

In web browsers these loading bars are placed between the application toolbar and the webpage content. For a desktop application that corresponds to placing it directly below the title bar, but above the window content. However, having tried this it looks a little strange, as if the title bar, being outside the border, isn't part of the application. Then I realised it really needs to be on the window border, which includes going above the title bar. Getting this to work in WPF was a bit of a pain, as it usually expects you to create graphic below the title bar, not above it. But eventually I found a reliable method.

Now I'll proceed to give a little FAQ summary, and explain the inner-workings.

Follow the instructions on the GitHub Readme. You can clone the project, and build on it. Or setup the required dependencies and copy the code into your own project.

Your Window class should take the following structure where <c:BorderLoop> is the component containing one example border animation effect. Different components are available for different effects, each with different properties such as BColor to set the color of the border animation.

<Window ...>
    <Grid>
        <!-- Add animations you want to use here -->
        <c:BorderLoop x:Name="BorderLoop" BColor="Yellow"></c:BorderLoop>

        <!-- Place your windows contents within this grid -->
        <Grid Margin="1">
            ...
        </Grid>
    </Grid>
</Window>

Then to start the animation use the .Start() method, e.g. BorderLoop.Start();.

Can I use it for border animations on other WPF controls?

Yes. Use the same structure as above in place of your component:

<Grid>
    <c:BorderLoop x:Name="BorderLoop" BColor="Yellow"></c:BorderLoop>
    <MyControl Margin="1"/>
</Grid>

How does it add colours above the TitleBar?

To colour the borders, the window border width is actually set to 0, and custom controls are used within the window to make the colours appear. That means on the top border, a control has to be rendered above the titlebar. So how does that work?

In WPF titlebars are difficult to customise. Default WPF titlebars cannot be changed, hence they need to be removed entirely with a custom title bar put in their place. That's not an easy thing to do; you often loose native functionality by reimplementing titlebars youself. See my previous attempts creating customiable titlebars in WPF, and HTML-based WPF titlebars in blazor dektop apps.

... but WinUI provides much better controls for this. Hence I recommend using the ModernWpf framework which takes native titlebars from WinUI and lets you use them in your WPF application - and place additional controls like fake window borders within them! This project uses ModernWpf for this purpose.

How do the animations work? Are there performance overheads?

It uses WPF's built-in animations and storyboards … so it's very efficient.

However, animations in WPF are usually pixel based. You assign a From value and a To value in terms of pixels. This doesn't work very well for window border animation which need to span the full width or half-width or third-width of the window, and smoothly animate between these points in a way that scales correctly on window resizes. Of course that's never a problem in web development as CSS allow percentage based widths and heights, but sadly not in WPF 😢

Instead the way to achieve this in WPF is using Grids with column/row widths/heights using stars. E.g. setting a column to have width "43*" and a second column of width "100*" creates a 43:100 ratio or width of 43%.

Animating grid column widths and row heights like is this not possible out-of-the-box, instead I found an existing custom AnimationTimeline implementation from MahApps. You can find the source here.

You assign the component a name:

<Grid.ColumnDefinition Width="*" x:Name="MyColumn"/>

If you look at the codebehind for each animation component, you'll see the animations created like this:

GridLengthAnimation anim = new GridLengthAnimation();
anim.From = new GridLength(fromValue, GridUnitType.Star);
anim.To = new GridLength(toValue, GridUnitType.Star);
anim.Duration = ... ;
Storyboard.SetTargetName(anim, "MyColumn");
Storyboard.SetTargetProperty(anim, new PropertyPath(ColumnDefinition.WidthProperty));

The top dash animation is more complex, it consists of 16 columns which alernate between empty and coloured-in. The idea being that you only need to animate the widths of the first and last columns. The animation comes in two stages, first expanding width of column 2 and shrinking column 16, followed by expanding column 1 and shrinking column 15. After which, the animation immediately resets.

The complete border dash animation applies this to all 4 edges of the window at the same time, to make it look like the dashes are flowing around the entire window border.

That’s it

If you find it useful please star the GitHub repository ⭐⭐⭐

Comments

Popular posts from this blog

Terminals in Sublime Text 3

If you need a quick answer on how to create terminals in Sublime Text 3, watch the following video, or read the instructions below it. How to set up Terminals in Sublime Text 3 Open Sublime Text. Open the Command Palette with Crtl+Shift+P Type  'Package Control: Install Package' until the option appears and select it [You'll need to install package control if you are using it for the first time] Type 'Terminus' and select it. Now the package Terminus will install. Wait for this to complete. Then restart Sublime Text. Next we will add Commands to the Command Palette. So you can open terminals using Crtl+Shift+P then typing a command. To do this open the Command Palette (Ctrl+Shift+P) and type 'Terminus: Command Palette' and open it. You'll be greeted by a split view. Basically there are settings defined in the code on the left panel and you can override them or add your own by typing code in the right panel. Copy ...

Generating a MSI Installer for a WPF Application

This post serves as a tutorial for creating a MSI installer for your WPF Applications in Visual Studio. For this we use WiX (recommended by Microsoft). Prerequisites I assume you already have a Visual Studio solution containing a WPF Project. And I assume you have some experience with Visual Studio and XML. You do not need any prior knowledge of WiX. Step 1: Install Wix We are going to need WiX to generate our MSI. If you don't already have Wix installed, go ahead and download it from here . You'll be redirected to the relevant GitHub releases page where you can download the .exe file to install WiX.

Fill your GitHub activity heatmap with the image of your choice

Taking 12 months to upload a 52x7 pixel image, through thousands of git commits, ... that's completely reasonable right?