Click here to Skip to main content
15,860,972 members
Articles / Programming Languages / C#
Article

AppBar using C#

Rate me:
Please Sign up or sign in to vote.
3.23/5 (37 votes)
18 Apr 2004CPOL 234.5K   58   45
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

 
GeneralThanks... Pin
puneetdhawan200019-Nov-10 23:28
puneetdhawan200019-Nov-10 23:28 
GeneralThanks, Exactly what I was looking for! Pin
jg00714-Jun-09 9:49
jg00714-Jun-09 9:49 
Questionshould not be able to minimise AppBar when docked! Pin
Webermania8-Sep-08 3:01
Webermania8-Sep-08 3:01 
AnswerRe: should not be able to minimise AppBar when docked! Pin
Relair16-Feb-10 23:52
Relair16-Feb-10 23:52 
AnswerRe: should not be able to minimise AppBar when docked! Pin
Stephen Done15-Jan-23 12:36
Stephen Done15-Jan-23 12:36 
GeneralExceptions encountered with .Net 2.0! Pin
irrdev23-Oct-07 0:55
irrdev23-Oct-07 0:55 
GeneralRe: Exceptions encountered with .Net 2.0! Pin
Yaroslav Trofimov22-Apr-08 3:03
Yaroslav Trofimov22-Apr-08 3:03 
GeneralThanks for the article Pin
rayazax25-Apr-07 0:31
rayazax25-Apr-07 0:31 
It helped.
I have one problem.
I have a from that sometimes need to be a task bar and sometimes floating bar, according to what user chooses.
We need to define ExStyle as WS_EX_TOOLWINDOW in order this stuff make working, but then when my form is floating I can not do minimize to it and I don't see it at task bar.
What can I do in order to fix it?
Thanks
QuestionNot working with .NET Frame 2.0 ? Pin
Haggy21-Mar-06 0:56
Haggy21-Mar-06 0:56 
AnswerRe: Not working with .NET Frame 2.0 ? Pin
Neno123413-Jan-07 22:27
Neno123413-Jan-07 22:27 
QuestionWindows bug? Pin
growse31-Oct-05 4:32
growse31-Oct-05 4:32 
Generalgrumpf Pin
mofin16-Sep-05 3:27
mofin16-Sep-05 3:27 
GeneralGreat Pin
iglb19-Oct-04 23:25
iglb19-Oct-04 23:25 
GeneralRe: Great Pin
Marcio Castilho25-Jan-05 18:52
Marcio Castilho25-Jan-05 18:52 
GeneralRe: Great Pin
Keith Farmer27-Nov-05 10:47
Keith Farmer27-Nov-05 10:47 
GeneralHmm.... Pin
mirano19-Apr-04 4:37
mirano19-Apr-04 4:37 
GeneralRe: Hmm.... Pin
Anonymous19-Apr-04 7:32
Anonymous19-Apr-04 7:32 
GeneralRe: Hmm.... Pin
Ellery_Familia19-Apr-04 17:58
Ellery_Familia19-Apr-04 17:58 
GeneralRe: Hmm.... Pin
Mad__19-Apr-04 21:12
Mad__19-Apr-04 21:12 
GeneralRe: Hmm.... Pin
Frederic Vaillancourt20-Apr-04 10:39
Frederic Vaillancourt20-Apr-04 10:39 
GeneralRe: Hmm.... Pin
Igor Velikorossov22-Apr-04 16:06
Igor Velikorossov22-Apr-04 16:06 
GeneralRe: Hmm.... Pin
zm10xn2931-Jul-06 19:02
zm10xn2931-Jul-06 19:02 

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.