Skip to content
Sam Johnson edited this page Jan 3, 2021 · 6 revisions

AppBars are windows that appear pinned to a screen edge, such as the Windows taskbar. ManagedShell includes several utilities for creating and managing AppBar windows.

When your app is running as the system shell, AppBarManager automatically sets the system work area based on the AppBarWindow(s) you have created. When your app is running alongside Windows Explorer (which is recommended on Windows 10), AppBarManager will register your AppBar windows with Explorer, which will set the system work area automatically.

AppBarWindow Class

The AppBarWindow class allows you to create a WPF window that registers itself as an AppBar.

Basic Setup

This example will create an AppBar across the top of the screen. It will automatically position itself, size itself to the width of the primary display, reduce the system work area, and get out of the way for full-screen windows.

MyAppBar.xaml

<appbar:AppBarWindow x:Class="MyApp.MyAppBar"
                     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                     xmlns:appbar="clr-namespace:ManagedShell.AppBar;assembly=ManagedShell.AppBar">
    <Grid>
        <TextBlock TextAlignment="Center">Hello World!</TextBlock>
    </Grid>
</appbar:AppBarWindow>

MyAppBar.xaml.cs

using System.Windows.Forms;
using ManagedShell;
using ManagedShell.AppBar;
using ManagedShell.Interop;

namespace MyApp
{
    /// <summary>
    /// Interaction logic for MyAppBar.xaml
    /// </summary>
    public partial class MyAppBar : AppBarWindow
    {
        public MyAppBar(ShellManager shellManager, Screen screen, NativeMethods.ABEdge edge, double desiredHeight)
            : base(shellManager.AppBarManager, shellManager.ExplorerHelper, shellManager.FullScreenHelper, screen, edge, desiredHeight)
        {
            InitializeComponent();
        }
    }
}

Display the window

Now that we have defined our basic AppBar window, we need to display it. This can be done where appropriate in your application, but you must have a reference to the ShellManager object, or direct references to the required singletons.

This will create an AppBar on the primary screen, at the top edge, 30 points in height.

MyAppBar appBar = new MyAppBar(_shellManager, Screen.PrimaryScreen, NativeMethods.ABEdge.ABE_TOP, 30);
appBar.Show();

Customizing Behavior

Hiding the Windows Explorer Taskbar

If your shell is running alongside Windows Explorer (which is recommended on Windows 10), you will likely want to hide the Windows taskbar. To do so, you can use the ExplorerHelper.HideExplorerTaskbar property. In your window's constructor, set the property to true, and when your window is closing, using the CustomClosing method, set the property to false.

This will cause the Windows taskbar to enter auto-hide mode, and be completely hidden, when the window opens. When the window closes, the Windows taskbar auto-hide setting will be restored to its previous state, and be made visible once again.

public MyAppBar(ShellManager shellManager, Screen screen, NativeMethods.ABEdge edge, double desiredHeight)
    : base(shellManager.AppBarManager, shellManager.ExplorerHelper, shellManager.FullScreenHelper, screen, edge, desiredHeight)
{
    InitializeComponent();

    _explorerHelper.HideExplorerTaskbar = true;
}

protected override void CustomClosing()
{
    if (AllowClose)
    {
        _explorerHelper.HideExplorerTaskbar = false;
    }
}

Users on Windows versions prior to Windows 10 may notice that if your AppBar is on the same screen edge as the hidden Windows taskbar, it will not be displayed in the correct place. To fix this, handle the LocationChanged event in your AppBar window, then adjust the window position accordingly. The following example is for a bottom-edge AppBar:

private void MyAppBar_OnLocationChanged(object? sender, EventArgs e)
{
    // primarily for win7/8, they will set up the appbar correctly but then put it in the wrong place
    double desiredTop = Screen.Bounds.Bottom / DpiScale - Height;

    if (Top != desiredTop) Top = desiredTop;
}

protected override void CustomClosing()

AppBarWindow prevents AppBars from closing unless the AllowClose property is true. Overriding the CustomClosing method allows you to perform operations when the AppBar has received a signal to close, such as disposing objects or manipulating AllowClose.

Calling AppBarManager.SignalGracefulShutdown() when the user chooses to close your app will flip AllowClose to true for all AppBars.

protected override void CustomClosing()
{
    if (AllowClose)
    {
        // Do stuff when closing
    }
    else
    {
        // Do stuff when not closing, such as changing AllowClose to true in a certain condition
    }
}

public override void SetPosition()

Override this method to customize what happens when the window's position changes (for example, on startup, or when the displays connected to the system change when the app is running in shell mode).

public override void SetPosition()
{
    base.SetPosition();

    // Do stuff on startup and when displays change (when running as shell)
}

public override void AfterAppBarPos(bool, NativeMethods.Rect)

Override this method to customize what happens when the window's position changes when the app is running alongside Windows Explorer.

public override void AfterAppBarPos(bool isSameCoords, NativeMethods.Rect rect)
{
    base.AfterAppBarPos(isSameCoords, rect);

    // Do stuff when Explorer tells us where to move our AppBar, such as on display change
}

Customizing Properties

There are several properties of AppBarWindow that can be modified:

  • bool AllowClose - Controls whether the window will be allowed to close when told to do so.
  • NativeMethods.ABEdge AppBarEdge - Sets the screen edge the AppBar should display on. ⚠ Note: Only ABE_TOP and ABE_BOTTOM are currently supported.
  • bool EnableAppBar - Toggles AppBar functionality for the window. When false, the window will not reduce the system work area.
  • bool RequiresScreenEdge - Controls whether the AppBar should respect the position of other AppBars on the same edge. If true, the AppBar will always be placed at the edge, regardless of other AppBars.

AppBarManager Class

The AppBar manager keeps track of all AppBars registered by your app. If Windows Explorer is running, your AppBars will automatically be registered with Explorer so that it can manage the system work area. If your app is running as the shell, AppBarManager will manage the system work area.

ExplorerHelper Class

This singleton class contains several useful functions for managing Windows Explorer while your app is running, such as showing and hiding the Windows taskbar. This can be done by setting the boolean property ExplorerHelper.HideExplorerTaskbar.

FullScreenHelper Class

This singleton class watches for any full-screen windows. If one is found, the FullScreenHelper.FullScreenApps collection is updated with a FullScreenApp object representing the window. You can handle the FullScreenHelper.FullScreenApps.CollectionChanged event to perform logic when an app enters or exits full-screen mode.

Clone this wiki locally