Click here to Skip to main content
16,018,797 members
Articles / Programming Languages / C#
Article

AppBar using C#

Rate me:
Please Sign up or sign in to vote.
3.29/5 (38 votes)
18 Apr 2004CPOL 240.9K   58   46
How to make AppBar for .NET

Using the Code

First we must declare the needed structures and constants.
(I combine constants in enums).

We declare the RECT WINAPI structure as follows:

C#
[StructLayout(LayoutKind.Sequential)]
struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

We declare the APPBARDATA SHELLAPI structure as follows:

C#
[StructLayout(LayoutKind.Sequential)]
struct APPBARDATA
{
    public int cbSize;
    public IntPtr hWnd;
    public int uCallbackMessage;
    public int uEdge;
    public RECT rc;
    public IntPtr lParam;
}

Then, we declare the AppBar related constants enums as follows:

C#
enum ABMsg : int
{
    ABM_NEW=0,
    ABM_REMOVE,
    ABM_QUERYPOS,
    ABM_SETPOS,
    ABM_GETSTATE,
    ABM_GETTASKBARPOS,
    ABM_ACTIVATE,
    ABM_GETAUTOHIDEBAR,
    ABM_SETAUTOHIDEBAR,
    ABM_WINDOWPOSCHANGED,
    ABM_SETSTATE
}
enum ABNotify : int
{
    ABN_STATECHANGE=0,
    ABN_POSCHANGED,
    ABN_FULLSCREENAPP,
    ABN_WINDOWARRANGE
}
enum ABEdge : int
{
    ABE_LEFT=0,
    ABE_TOP,
    ABE_RIGHT,
    ABE_BOTTOM
}

Next we declare the needed WIN32 and SHELL API functions import:

C#
[DllImport("SHELL32", CallingConvention=CallingConvention.StdCall)]
static extern uint SHAppBarMessage(int dwMessage, ref APPBARDATA pData);
[DllImport("USER32")]
static extern int GetSystemMetrics(int Index);
[DllImport("User32.dll", ExactSpelling=true, 
    CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private static extern bool MoveWindow
    (IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("User32.dll", CharSet=CharSet.Auto)]
private static extern int RegisterWindowMessage(string msg);

The next step is creating a function to register AppBar:

C#
private void RegisterBar()
{
    APPBARDATA abd = new APPBARDATA();
    abd.cbSize = Marshal.SizeOf(abd);
    abd.hWnd = this.Handle;
    if (!fBarRegistered)
    {
        uCallBack = RegisterWindowMessage("AppBarMessage");
        abd.uCallbackMessage = uCallBack;

        uint ret = SHAppBarMessage((int)ABMsg.ABM_NEW, ref abd);
    fBarRegistered = true;

    ABSetPos();
    }
    else
    {
    SHAppBarMessage((int)ABMsg.ABM_REMOVE, ref abd);
    fBarRegistered = false;
    }
}

The last step is to create a function to position AppBar:

C#
private void ABSetPos()
{
    APPBARDATA abd = new APPBARDATA();
    abd.cbSize = Marshal.SizeOf(abd);
    abd.hWnd = this.Handle;
    abd.uEdge = (int)ABEdge.ABE_TOP;

    if (abd.uEdge == (int)ABEdge.ABE_LEFT || abd.uEdge == (int)ABEdge.ABE_RIGHT) 
    {
    abd.rc.top = 0;
    abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height;
    if (abd.uEdge == (int)ABEdge.ABE_LEFT) 
    {
        abd.rc.left = 0;
        abd.rc.right = Size.Width;
    }
    else 
    {
        abd.rc.right = SystemInformation.PrimaryMonitorSize.Width;
        abd.rc.left = abd.rc.right - Size.Width;
    }

    }
    else 
    {
    abd.rc.left = 0;
    abd.rc.right = SystemInformation.PrimaryMonitorSize.Width;
    if (abd.uEdge == (int)ABEdge.ABE_TOP) 
    {
        abd.rc.top = 0;
        abd.rc.bottom = Size.Height;
    }
    else 
    {
        abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height;
        abd.rc.top = abd.rc.bottom - Size.Height;
    }
    }

    SHAppBarMessage((int)ABMsg.ABM_QUERYPOS, ref abd); 

    switch (abd.uEdge) 
    { 
    case (int)ABEdge.ABE_LEFT: 
        abd.rc.right = abd.rc.left + Size.Width;
        break; 
    case (int)ABEdge.ABE_RIGHT: 
        abd.rc.left= abd.rc.right - Size.Width;
        break; 
    case (int)ABEdge.ABE_TOP: 
        abd.rc.bottom = abd.rc.top + Size.Height;
        break; 
    case (int)ABEdge.ABE_BOTTOM: 
        abd.rc.top = abd.rc.bottom - Size.Height;
        break; 
    }

    SHAppBarMessage((int)ABMsg.ABM_SETPOS, ref abd); 
    MoveWindow(abd.hWnd, abd.rc.left, abd.rc.top, 
            abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, true); 
}

This is a full listing of a sample AppBar form class:

C#
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

namespace Sample.AppBar
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class MainForm : System.Windows.Forms.Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public MainForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            // 
            // MainForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(960, 50);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
            this.Name = "MainForm";
            this.Text = "AppBar";
            this.Closing += new System.ComponentModel.CancelEventHandler(this.OnClosing);
            this.Load += new System.EventHandler(this.OnLoad);
        }
        #endregion

        #region APPBAR

        [StructLayout(LayoutKind.Sequential)]
        struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        struct APPBARDATA
        {
            public int cbSize;
            public IntPtr hWnd;
            public int uCallbackMessage;
            public int uEdge;
            public RECT rc;
            public IntPtr lParam;
        }

        enum ABMsg : int
        {
            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
        }

        enum ABNotify : int
        {
            ABN_STATECHANGE=0,
            ABN_POSCHANGED,
            ABN_FULLSCREENAPP,
            ABN_WINDOWARRANGE
        }

        enum ABEdge : int
        {
            ABE_LEFT=0,
            ABE_TOP,
            ABE_RIGHT,
            ABE_BOTTOM
        }

        private bool fBarRegistered = false;

        [DllImport("SHELL32", CallingConvention=CallingConvention.StdCall)]
        static extern uint SHAppBarMessage(int dwMessage, ref APPBARDATA pData);
        [DllImport("USER32")]
        static extern int GetSystemMetrics(int Index);
        [DllImport("User32.dll", ExactSpelling=true, 
            CharSet=System.Runtime.InteropServices.CharSet.Auto)]
        private static extern bool MoveWindow
            (IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
        [DllImport("User32.dll", CharSet=CharSet.Auto)]
        private static extern int RegisterWindowMessage(string msg);
        private int uCallBack;

        private void RegisterBar()
        {
            APPBARDATA abd = new APPBARDATA();
            abd.cbSize = Marshal.SizeOf(abd);
            abd.hWnd = this.Handle;
            if (!fBarRegistered)
            {
                uCallBack = RegisterWindowMessage("AppBarMessage");
                abd.uCallbackMessage = uCallBack;

                uint ret = SHAppBarMessage((int)ABMsg.ABM_NEW, ref abd);
                fBarRegistered = true;

                ABSetPos();
            }
            else
            {
                SHAppBarMessage((int)ABMsg.ABM_REMOVE, ref abd);
                fBarRegistered = false;
            }
        }

        private void ABSetPos()
        {
            APPBARDATA abd = new APPBARDATA();
            abd.cbSize = Marshal.SizeOf(abd);
            abd.hWnd = this.Handle;
            abd.uEdge = (int)ABEdge.ABE_TOP;

            if (abd.uEdge == (int)ABEdge.ABE_LEFT || abd.uEdge == (int)ABEdge.ABE_RIGHT) 
            {
                abd.rc.top = 0;
                abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height;
                if (abd.uEdge == (int)ABEdge.ABE_LEFT) 
                {
                    abd.rc.left = 0;
                    abd.rc.right = Size.Width;
                }
                else 
                {
                    abd.rc.right = SystemInformation.PrimaryMonitorSize.Width;
                    abd.rc.left = abd.rc.right - Size.Width;
                }

            }
            else 
            {
                abd.rc.left = 0;
                abd.rc.right = SystemInformation.PrimaryMonitorSize.Width;
                if (abd.uEdge == (int)ABEdge.ABE_TOP) 
                {
                    abd.rc.top = 0;
                    abd.rc.bottom = Size.Height;
                }
                else 
                {
                    abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height;
                    abd.rc.top = abd.rc.bottom - Size.Height;
                }
            }

            // Query the system for an approved size and position. 
            SHAppBarMessage((int)ABMsg.ABM_QUERYPOS, ref abd); 

            // Adjust the rectangle, depending on the edge to which the 
            // appbar is anchored. 
            switch (abd.uEdge) 
            { 
                case (int)ABEdge.ABE_LEFT: 
                    abd.rc.right = abd.rc.left + Size.Width;
                    break; 
                case (int)ABEdge.ABE_RIGHT: 
                    abd.rc.left= abd.rc.right - Size.Width;
                    break; 
                case (int)ABEdge.ABE_TOP: 
                    abd.rc.bottom = abd.rc.top + Size.Height;
                    break; 
                case (int)ABEdge.ABE_BOTTOM: 
                    abd.rc.top = abd.rc.bottom - Size.Height;
                    break; 
            }

            // Pass the final bounding rectangle to the system. 
            SHAppBarMessage((int)ABMsg.ABM_SETPOS, ref abd); 

            // Move and size the appbar so that it conforms to the 
            // bounding rectangle passed to the system. 
            MoveWindow(abd.hWnd, abd.rc.left, abd.rc.top, 
                abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, true); 
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == uCallBack)
            {
                switch(m.WParam.ToInt32())
                {
                    case (int)ABNotify.ABN_POSCHANGED:
                        ABSetPos();
                        break;
                }
            }

            base.WndProc(ref m);
        }

        protected override System.Windows.Forms.CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.Style &= (~0x00C00000); // WS_CAPTION
                cp.Style &= (~0x00800000); // WS_BORDER
                cp.ExStyle = 0x00000080 | 0x00000008; // WS_EX_TOOLWINDOW | WS_EX_TOPMOST
                return cp;
            }
        }

        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new MainForm());
        }

        private void OnLoad(object sender, System.EventArgs e)
        {
            RegisterBar();
        }

        private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            RegisterBar();
        }
    }
}

For more information about creating AppBars, refer to the MSDN.

P.S.

Post in comments and questions about code parts. I plan to update the article descriptions based on your questions.

License

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


Written By
Web Developer
Ukraine Ukraine
Developing software for Civilian aviation and Meteorogical offices.

Comments and Discussions

 
PraiseWork very well Pin
srfox31-May-24 2:20
professionalsrfox31-May-24 2:20 
QuestionApp doesn't exit Pin
Member 1590395224-Jan-23 13:27
Member 1590395224-Jan-23 13:27 
QuestionABSetPos Question Pin
Michael Schiessl23-May-21 11:24
Michael Schiessl23-May-21 11:24 
BugWPF APP BAR windows 10 Exception Pin
Member 1182122320-Nov-18 21:12
Member 1182122320-Nov-18 21:12 
Questionhow can use in vb.net Pin
BlackQueen626-Feb-18 3:40
BlackQueen626-Feb-18 3:40 
AnswerRe: how can use in vb.net Pin
Member 97026137-May-18 9:23
Member 97026137-May-18 9:23 
QuestionThanks Pin
Muhammad Adnan Sohail21-Feb-16 3:24
professionalMuhammad Adnan Sohail21-Feb-16 3:24 
QuestionMultiscreen Pin
Member 1041995220-Aug-15 23:35
Member 1041995220-Aug-15 23:35 
QuestionProblem with Context Menu Strip Pin
Member 109013179-Aug-15 19:32
Member 109013179-Aug-15 19:32 
QuestionNice code but I have a problem Pin
Member 1100107622-Sep-14 11:55
Member 1100107622-Sep-14 11:55 
AnswerRe: Nice code but I have a problem Pin
Member 1100107622-Sep-14 12:03
Member 1100107622-Sep-14 12:03 
QuestionProblem width on left/right Pin
Member 876327324-May-14 2:52
Member 876327324-May-14 2:52 
QuestionDPI Setting Pin
S. Ryan24-Jan-14 5:38
S. Ryan24-Jan-14 5:38 
QuestionRe: DPI Setting Pin
Tailslide3-Jun-14 6:29
Tailslide3-Jun-14 6:29 
AnswerRe: DPI Setting Pin
Nino Stella19-Jun-14 3:24
Nino Stella19-Jun-14 3:24 
GeneralRe: DPI Setting Pin
Member 108047428-Jul-14 8:29
Member 108047428-Jul-14 8:29 
QuestionRe: DPI Setting Pin
James MacGilp20-Jan-15 5:05
James MacGilp20-Jan-15 5:05 
AnswerRe: DPI Setting Pin
James MacGilp20-Jan-15 22:25
James MacGilp20-Jan-15 22:25 
GeneralRe: DPI Setting Pin
Tailslide19-Jul-15 0:22
Tailslide19-Jul-15 0:22 
Thanks for the suggestion this worked for me on the main monitor, but if I try to dock on my second monitor placed to the left it seems to lose it's mind and no amount of twiddling seems to make it behave (my app is set to DPI aware)

Nevermind.. figured out if I set it to 'per monitor' DPI aware then everything starts working.

modified 19-Jul-15 6:47am.

QuestionSize variable Pin
Member 1031492413-Oct-13 6:35
Member 1031492413-Oct-13 6:35 
QuestionWhat is tha Best way to store data in mobile application.In Windows phone,android and nokia Mobiles Pin
aamitsengar25-Apr-13 22:00
aamitsengar25-Apr-13 22:00 
QuestionHow to make it Autohide? Pin
kilkenny9920-Dec-12 4:22
kilkenny9920-Dec-12 4:22 
GeneralWill this work without having explorer shelled? Pin
q2418130103p2-May-11 8:21
q2418130103p2-May-11 8:21 
GeneralRe: Will this work without having explorer shelled? Pin
Veldrik2-May-12 18:04
Veldrik2-May-12 18:04 
GeneralThanks... Pin
puneetdhawan200019-Nov-10 23:28
puneetdhawan200019-Nov-10 23:28 

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.