Accessing the System Task Bar in C#

In this post I’ll show you how to access the system taskbar and obtain information like its location, size, etc. You may find yourself needing to do something like this if you had a “popup” window for instance that is always supposed to “pop up” from the system tray. This is a common feature in many of today’s applications; however the task bar may be docked somewhere other than the bottom of the screen or maybe even on a different monitor in a multi-monitor setup.

The Taskbar is an APPBAR

First, the task bar is considered an appbar (or desktop application toolbar) albeit with some special restrictions. Being an appbar we can talk to it with the Win32 API function SHAppBarMessage. SHAppBarMessage allows us to send a message to the system to get or set information about a registered appbar. The necessary C# definitions to access the function are as follows:

[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
      public int top;
      public int right;
      public int bottom;
}
 
[StructLayout(LayoutKind.Sequential)]
private struct APPBARDATA
{
public Int32 cbSize;
      public IntPtr hWnd;
      public Int32 uCallbackMessage;
      public ABEdge uEdge;
      public RECT rc;
      public IntPtr lParam;
}
 
private enum ABMsg
{
ABM_NEW = 0,
      ABM_REMOVE = 1,
      ABM_QUERYPOS = 2,
      ABM_SETPOS = 3,
      ABM_GETSTATE = 4,
      ABM_GETTASKBARPOS = 5,
      ABM_ACTIVATE = 6,
      ABM_GETAUTOHIDEBAR = 7,
      ABM_SETAUTOHIDEBAR = 8,
      ABM_WINDOWPOSCHANGED = 9,
      ABM_SETSTATE = 10
}
 
private enum ABEdge
{
ABE_LEFT = 0,
      ABE_TOP = 1,
      ABE_RIGHT = 2,
      ABE_BOTTOM = 3,
}
 
private enum ABState
{
ABS_MANUAL = 0,
      ABS_AUTOHIDE = 1,
      ABS_ALWAYSONTOP = 2,
      ABS_AUTOHIDEANDONTOP = 3
}
 
[DllImport("shell32.dll")]
private static extern IntPtr SHAppBarMessage(ABMsg dwMessage, [In, Out] ref APPBARDATA pData);

Using SHAppBarMessage

In order to use SHAppBarMessage we must first fill out the APPBAR struct with at least the cbSize and hWnd members. For hWnd we need to get the handle to the system taskbar window. It just so happens that you can use the FindWindow API function with a system class name of “Shell_TrayWnd” to get the required handle. Of course, to the best of my knowledge the class name “Shell_TrayWnd” is not a “documented” part of the Win32 system therefore it could change with any Windows release. However, I think it’s probably a safe bet to rely on it given the number of applications in the field that already do. Without further ado, some code to get the size of the task bar.

[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 
APPBARDATA appBar = new APPBARDATA();
 
appBar.hWnd = FindWindow("Shell_TrayWnd", "");
appBar.cbSize = Marshal.SizeOf(appBar);
 
System.IntPtr ret = SHAppBarMessage(ABMsg.ABM_GETTASKBARPOS, ref appBar);
 
Size s = new Size(appBar.rc.right - appBar.rc.left, appBar.rc.bottom - appBar.rc.top);

Simple right?

Modifying the Taskbar

Remember earlier I said the system taskbar is not quite like a normal appbar? Well it’s special in that you can’t really change any of its properties like its size or position. This makes sense as you wouldn’t just want any program you install to play with the users taskbar; it’s sort of like an invasion of privacy. I’ve seen claims around the Internet that this can be pulled off in application code, which may be true prior to Vista; however I’ve tried all kinds of tricks based on SHAppBarMessage and can’t change the taskbar properties under Vista. Do you know how this can be done or if it’s even possible? I have found that you can change the task bar state. That is, you can toggle between “autohide” mode and “always on top” mode.

Example Taskbar Code

So, here is a little class I’ve put together to wrap the SHAppBarMessage functionality. I really haven’t paid attention to error handling or anything with it so if you use this you would need to address that.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
 
namespace TaskbarInfoExample
{
    /// <summary>
    /// Provides methods for obtaining and modifying information for the system taskbar.
    /// </summary>
    class TaskBar
    {
        #region Native API
        // The native API functions/enums/structs needed to access taskbar info
        // consult MSDN for more detailed information about them
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        private struct APPBARDATA
        {
            public Int32 cbSize;
            public IntPtr hWnd;
            public Int32 uCallbackMessage;
            public ABEdge uEdge;
            public RECT rc;
            public IntPtr lParam;
        }
 
        private enum ABMsg
        {
            ABM_NEW = 0,
            ABM_REMOVE = 1,
            ABM_QUERYPOS = 2,
            ABM_SETPOS = 3,
            ABM_GETSTATE = 4,
            ABM_GETTASKBARPOS = 5,
            ABM_ACTIVATE = 6,
            ABM_GETAUTOHIDEBAR = 7,
            ABM_SETAUTOHIDEBAR = 8,
            ABM_WINDOWPOSCHANGED = 9,
            ABM_SETSTATE = 10
        }
 
        private enum ABEdge
        {
            ABE_LEFT = 0,
            ABE_TOP = 1,
            ABE_RIGHT = 2,
            ABE_BOTTOM = 3,
        }
 
        private enum ABState
        {
            ABS_MANUAL = 0,
            ABS_AUTOHIDE = 1,
            ABS_ALWAYSONTOP = 2,
            ABS_AUTOHIDEANDONTOP = 3
        }
 
        [DllImport("shell32.dll")]
        private static extern IntPtr SHAppBarMessage(ABMsg dwMessage, [In, Out] ref APPBARDATA pData);
 
        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        #endregion
 
        /// <summary>
        /// Represents the edge of the screen the task bar is docked to.
        /// </summary>
        public enum TaskBarEdge
        {
            Left = ABEdge.ABE_LEFT,
            Top = ABEdge.ABE_TOP,
            Right = ABEdge.ABE_RIGHT,
            Bottom = ABEdge.ABE_BOTTOM
        }
 
        /// <summary>
        /// The states the task bar can be in.
        /// </summary>
        [Flags]
        public enum TaskBarState
        {
            /// <summary>
            /// No autohide, not always top
            /// </summary>
            None = ABState.ABS_MANUAL,
 
            /// <summary>
            /// Hides task bar when mouse exits task bar region
            /// </summary>
            AutoHide = ABState.ABS_AUTOHIDE,
 
            /// <summary>
            /// Taskbar is always on top of other windows
            /// </summary>
            AlwaysTop = ABState.ABS_ALWAYSONTOP
        }
 
        /// <summary>
        /// Gets the location, in screen coordinates of the task bar.
        /// </summary>
        /// <returns>The taskbar location.</returns>
        public static Point GetTaskBarLocation()
        {
            APPBARDATA appBar = GetTaskBarData();
 
            return new Point(appBar.rc.left, appBar.rc.top);
        }
 
        /// <summary>
        /// Gets the size, in pixels of the task bar.
        /// </summary>
        /// <returns>The taskbar size.</returns>
        public static Size GetTaskBarSize()
        {
            APPBARDATA appBar = GetTaskBarData();
 
            return new Size(appBar.rc.right - appBar.rc.left, appBar.rc.bottom - appBar.rc.top);
        }
 
        /// <summary>
        /// Gets the edge of the screen that the task bar is docked to.
        /// </summary>
        /// <returns></returns>
        public static TaskBarEdge GetTaskBarEdge()
        {
            APPBARDATA appBar = GetTaskBarData();
 
            return (TaskBarEdge)appBar.uEdge;
        }
 
        /// <summary>
        /// Gets the current state of the taskbar.
        /// </summary>
        /// <returns></returns>
        public static TaskBarState GetTaskBarState()
        {
            APPBARDATA appBar = CreateAppBarData();
 
            return (TaskBarState)SHAppBarMessage(ABMsg.ABM_GETSTATE, ref appBar);
        }
 
        /// <summary>
        /// Sets the state of the task bar.
        /// </summary>
        /// <param name="state">The new state.</param>
        public static void SetTaskBarState(TaskBarState state)
        {
            APPBARDATA appBar = CreateAppBarData();
 
            appBar.lParam = (IntPtr)state;
 
            SHAppBarMessage(ABMsg.ABM_SETSTATE, ref appBar);
        }
 
        /// <summary>
        /// Gets an APPBARDATA struct with valid location,size,and edge of the taskbar.
        /// </summary>
        /// <returns></returns>
        private static APPBARDATA GetTaskBarData()
        {
            APPBARDATA appBar = CreateAppBarData();
 
            System.IntPtr ret = SHAppBarMessage(ABMsg.ABM_GETTASKBARPOS, ref appBar);
 
            return appBar;
        }
 
        /// <summary>
        /// Creats an APPBARDATA struct with its hWnd member set to the task bar window.
        /// </summary>
        /// <returns></returns>
        private static APPBARDATA CreateAppBarData()
        {
            APPBARDATA appBar = new APPBARDATA();
 
            appBar.hWnd = FindWindow("Shell_TrayWnd", "");
            appBar.cbSize = Marshal.SizeOf(appBar);
 
            return appBar;
        }
    }
}

That’s All!

That’s all I’ve got for now. I have included a little demo app you can download to demonstrate the class. You can find that here Basically it just allows you to modify the task bar state and shows you all of its properties.

Hope you found this useful and saved yourself some time!

May 10, 2009   Posted in: C#, Programming

6 Responses

  1. Bisytror - May 25, 2009

    Hi, nice posts there :-) hold responsible’s for the interesting advice

  2. maryaleh - June 8, 2009

    It is reserve, neither it is more, nor it is less

  3. rhodanac - June 17, 2009

    I consider, that you commit an error. Write to me in PM, we will talk.

  4. Kipp Woodard - January 28, 2010

    Awesome, taskbar code that works!!!

    Do you have code to set the taskbar to the top edge?

  5. Logan - April 25, 2010

    Very handy! Thanks for posting. :)

  6. SETH - July 5, 2010


    Pillspot.org. Canadian Health&Care.No prescription online pharmacy.Best quality drugs.Special Internet Prices. Online Pharmacy. Buy drugs online

    Buy:Petcam (Metacam) Oral Suspension.Nexium.Prevacid.Zyban.Synthroid.Prednisolone.Lumigan.Retin-A.Mega Hoodia.Actos.Zovirax.Human Growth Hormone.100% Pure Okinawan Coral Calcium.Valtrex.Accutane.Arimidex….

Leave a Reply