Ok, 
I ran across this AppBar class that works extremely well.  Unfortunately, I am having a difficult time trying to figure out how to make things happen the way I'd like.  
My goal is to place a toolbar control on the AppBar form and have the orientation of the toolbar changed based on the horizontal / vertical screen alignment of the AppBar.  It doesn't seem like this should be that difficult but I have been unable to figure it out as of yet.  I have spent many hours on MSDN reading through the APPBAR docs and still have had no luck.
How can I note which edge of the screen the appbar successfully docs to and then perform some action?  The action I perform I can take care.  My issue up to this point has been with following exactly where the code goes and determining how to trigger based on this event.  (event = which edge did the appbar just doc to?)
The code I found is listed below.. (long)
------------------------------------------------------------------------------------------------------------
// Contributed by Dean Cleaver - [
[email protected]]
// a base class for implementing a dockable Windows App-Bar
// Much of the code ported from a C/C++ implementation by Jeffrey Richter
#region Copyright © 2002-2004 The Genghis Group
/*
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the authors be held liable for any damages arising from the
 * use of this software.
 * 
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, subject to the following restrictions:
 * 
 * 1. The origin of this software must not be misrepresented; you must not claim
 * that you wrote the original software. If you use this software in a product,
 * an acknowledgment in the product documentation is IsRequired, as shown here:
 * 
 * Portions Copyright © 2002-2004 The Genghis Group (http://www.genghisgroup.com/).
 * 
 * 2. No substantial portion of the source code of this library may be redistributed
 * without the express written permission of the copyright holders, where
 * "substantial" is defined as enough code to be recognizably from this library. 
*/
#endregion
#region History
// 4/15/2003 - Initial Version
#endregion
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace Genghis.Windows.Forms
{
    /// 
    /// Summary description for AppBar.
    /// 
	public class AppBarForm : System.Windows.Forms.Form
	{
		// The header from the original cpp file this was generated from.
		// Most of the credit belongs to Jeffrey Richter
		/******************************************************************************
		Module name: AppBar.cpp
		Written by: Jeffrey Richter
		Purpose: AppBar base class implementation file.
		******************************************************************************/
		#region Private Structures
		[StructLayout(LayoutKind.Sequential)]
			private struct POINT 
		{ 
			public int X; 
			public int Y; 
			public POINT(int X, int Y)
			{
				this.X = X;
				this.Y = Y;
			}
			public POINT(int pos)
			{
				this.X = pos & 0xFFFF;
				this.Y = (pos >> 16) & 0xFFFF;
			}
		} 
		[StructLayout(LayoutKind.Sequential)]
			private struct RECT
		{
			public int left;
			public int top;
			public int right;
			public int bottom;
			public RECT(int left,
				int top,
				int right,
				int bottom)
			{
				this.left = left;
				this.right = right;
				this.top = top;
				this.bottom = bottom;
			}
			public int Width
			{
				get {return right - left;}
			}
			public int Height
			{
				get {return bottom - top;}
			}
			public static bool operator != (RECT o1, RECT o2)
			{
				if (o1.left != o2.left)
					return true;
				if (o1.right != o2.right)
					return true;
				if (o1.top != o2.top)
					return true;
				if (o1.bottom != o2.bottom)
					return true;
				return false;
			}
			public static bool operator == (RECT o1, RECT o2)
			{
				if (o1.left != o2.left)
					return false;
				if (o1.right != o2.right)
					return false;
				if (o1.top != o2.top)
					return false;
				if (o1.bottom != o2.bottom)
					return false;
				return false;
			}
			public override bool Equals(object o)
			{
				try
				{
					RECT o2 = (RECT) o;
					return this == o2;
				}
				catch
				{
					return false;
				}
			}
			public override int GetHashCode()
			{
				return base.GetHashCode();
			}
		}
		[StructLayout(LayoutKind.Sequential)]
			private struct APPBARSTATE
		{
			public int size; // Size of this structure
			public int state; // ABE_UNKNOWN, ABE_FLOAT, or ABE_edge
			public bool autoHide; // Should AppBar be auto-hidden when docked?
			public bool alwaysOnTop; // Should AppBar always be on top?
			public int dockSizeHorizontal;
			public int dockSizeVertical;
			public RECT floatRect; // Floating rectangle (in screen coordinates)
			public int taskBarState;
			public int dockFlags; // See the ABF_* flags above
			public SIZE sizeInc; // Descrete width/height size increments
			public int proposedState;
			public bool fullScreenAppOpen;
			public bool autoHideIsVisible;
		} 
		[StructLayout(LayoutKind.Sequential)]
			private struct APPBARDATA
		{
			public int size;
			public int hWnd;
			public int callbackMessage;
			public int edge;
			public RECT position;
			public int lParam; // message specific
		}
		[StructLayout(LayoutKind.Sequential)]
			private struct SIZE
		{
			public int cx;
			public int cy;
			public SIZE(int cx, int cy)
			{
				this.cx = cx;
				this.cy = cy;
			}
		}
		#endregion
		#region Private Constants
		private const int ABE_LEFT = 0;
		private const int ABE_TOP = 1;
		private const int ABE_RIGHT = 2;
		private const int ABE_BOTTOM = 3;
		private const int ABE_UNKNOWN = 4;
		private const int ABE_FLOAT = 5;
		private const int ABF_ALLOWLEFT = 0x00000001;
		private const int ABF_ALLOWRIGHT = 0x00000004;
		private const int ABF_ALLOWTOP = 0x00000002;
		private const int ABF_ALLOWBOTTOM = 0x00000008;
		private const int ABF_ALLOWFLOAT = 0x00000010;
		private const int ABF_ALLOWLEFTRIGHT = (ABF_ALLOWLEFT | ABF_ALLOWRIGHT);
		private const int ABF_ALLOWTOPBOTTOM = (ABF_ALLOWTOP | ABF_ALLOWBOTTOM);
		private const int ABF_ALLOWANYEDGE = (ABF_ALLOWLEFTRIGHT | ABF_ALLOWTOPBOTTOM);
		private const int ABF_ALLOWANYWHERE = (ABF_ALLOWANYEDGE | ABF_ALLOWFLOAT);
		private const int ABF_MIMICTASKBARAUTOHIDE = 0x00000020;
		private const int ABF_MIMICTASKBARALWAYSONTOP = 0x00000040;
		private const int ABM_NEW = 0x00000000;
		private const int ABM_REMOVE = 0x00000001;
		private const int ABM_QUERYPOS = 0x00000002;
		private const int ABM_SETPOS = 0x00000003;
		private const int ABM_GETSTATE = 0x00000004;
		private const int ABM_GETTASKBARPOS = 0x00000005;
		private const int ABM_ACTIVATE = 0x00000006;
		private const int ABM_GETAUTOHIDEBAR = 0x00000007;
		private const int ABM_SETAUTOHIDEBAR = 0x00000008;
		private const int ABM_WINDOWPOSCHANGED = 0x00000009;
		private const int ABN_FULLSCREENAPP = 0x2;
		private const int ABN_POSCHANGED = 0x1;
		private const int ABN_STATECHANGE = 0x0;
		private const int ABN_WINDOWARRANGE = 0x3; // lParam == TRUE means hide
		private const int ABS_AUTOHIDE = 0x0000001;
		private const int ABS_ALWAYSONTOP = 0x0000002;
        
		private const int AUTOHIDETIMERINTERVAL = 400;
		private const int AUTOHIDETIMERID = 1;
		private const short GWL_STYLE = (-16);
		private const short GWL_EXSTYLE = (-20);
		private const int HTBORDER = 18;
		private const int HTBOTTOM = 15;
		private const int HTBOTTOMLEFT = 16;
		private const int HTBOTTOMRIGHT = 17;
		private const int HTCAPTION = 2;
		private const int HTCLIENT = 1;
		private const int HTERROR = (-2);
		private const int HTGROWBOX = 4;
		private const int HTHSCROLL = 6;
		private const int HTLEFT = 10;
		private const int HTMAXBUTTON = 9;
		private const int HTMENU = 5;
		private const int HTMINBUTTON = 8;
		private const int HTNOWHERE = 0;
		private const int HTREDUCE = HTMINBUTTON;
		private const int HTRIGHT = 11;
		private const int HTSIZE = HTGROWBOX;
		private const int HTSIZEFIRST = HTLEFT;
		private const int HTSIZELAST = HTBOTTOMRIGHT;
		private const int HTSYSMENU = 3;
		private const int HTTOP = 12;
		private const int HTTOPLEFT = 13;
		private const int HTTOPRIGHT = 14;
		private const int HTTRANSPARENT = (-1);
		private const int HTVSCROLL = 7;
		private const int HTZOOM = HTMAXBUTTON;
		private const int HWND_TOP = 0;
		private const int HWND_BOTTOM = 1;
		private const int HWND_TOPMOST = -1;
		private const int HWND_NOTOPMOST = -2;
		private const int SM_SWAPBUTTON = 23;
		private const int SM_CXDOUBLECLK = 36;
		private const int SM_CYDOUBLECLK = 37;
		private const int SM_CXVSCROLL = 2;
		private const int SM_CXHSCROLL = 21;
		private const int SM_CYHSCROLL = 3;
		private const int SM_CXSCREEN = 0;
		private const int SM_CYSCREEN = 1;
		private const int SM_CXBORDER = 5;
		private const int SM_CYBORDER = 6;
		private const int SPI_GETDRAGFULLWINDOWS = 38;
		private const int SPI_GETWORKAREA = 48;
		private const int SWP_NOSIZE = 0x0001;
		private const int SWP_NOMOVE = 0x0002;
		private const int SWP_NOZORDER = 0x0004;
		private const int SWP_NOREDRAW = 0x0008;
		private const int SWP_NOACTIVATE = 0x0010;
		private const int SWP_FRAMECHANGED =0x0020;
		private const int SWP_DRAWFRAME = SWP_FRAMECHANGED;
		private const int VK_CONTROL = 0x11;
		private const int VK_RBUTTON = 0x2;
		private const int VK_LBUTTON = 0x1;
		private const int WA_INACTIVE = 0;
		private const int WMSZ_LEFT = 1;
		private const int WMSZ_RIGHT = 2;
		private const int WMSZ_TOP = 3;
		private const int WMSZ_TOPLEFT = 4;
		private const int WMSZ_TOPRIGHT = 5;
		private const int WMSZ_BOTTOM = 6;
		private const int WMSZ_BOTTOMLEFT = 7;
		private const int WMSZ_BOTTOMRIGHT = 8;
		private const int WM_NULL = 0x0000;
		private const int WM_CREATE = 0x0001;
		private const int WM_DESTROY = 0x0002;
		private const int WM_MOVE = 0x0003;
		private const int WM_SIZE = 0x0005;
		private const int WM_ACTIVATE = 0x0006;
		private const int WM_SETFOCUS = 0x0007;
		private const int WM_KILLFOCUS = 0x0008;
		private const int WM_ENABLE = 0x000A;
		private const int WM_SETREDRAW = 0x000B;
		private const int WM_SETTEXT = 0x000C;
		private const int WM_GETTEXT = 0x000D;
		private const int WM_GETTEXTLENGTH = 0x000E;
		private const int WM_PAINT = 0x000F;
		private const int WM_CLOSE = 0x0010;
		private const int WM_QUERYENDSESSION = 0x0011;
		private const int WM_QUIT = 0x0012;
		private const int WM_QUERYOPEN = 0x0013;
		private const int WM_ERASEBKGND = 0x0014;
		private const int WM_SYSCOLORCHANGE = 0x0015;
		private const int WM_ENDSESSION = 0x0016;
		private const int WM_SHOWWINDOW = 0x0018;
		private const int WM_CTLCOLOR = 0x0019;
		private const int WM_WININICHANGE = 0x001A;
		private const int WM_SETTINGCHANGE = 0x001A;
		private const int WM_DEVMODECHANGE = 0x001B;
		private const int WM_ACTIVATEAPP = 0x001C;
		private const int WM_FONTCHANGE = 0x001D;
		private const int WM_TIMECHANGE = 0x001E;
		private const int WM_CANCELMODE = 0x001F;
		private const int WM_SETCURSOR = 0x0020;
		private const int WM_MOUSEACTIVATE = 0x0021;
		private const int WM_CHILDACTIVATE = 0x0022;
		private const int WM_QUEUESYNC = 0x0023;
		private const int WM_GETMINMAXINFO = 0x0024;
		private const int WM_PAINTICON = 0x0026;
		private const int WM_ICONERASEBKGND = 0x0027;
		private const int WM_NEXTDLGCTL = 0x0028;
		private const int WM_SPOOLERSTATUS = 0x002A;
		private const int WM_DRAWITEM = 0x002B;
		private const int WM_MEASUREITEM = 0x002C;
		private const int WM_DELETEITEM = 0x002D;
		private const int WM_VKEYTOITEM = 0x002E;
		private const int WM_CHARTOITEM = 0x002F;
		private const int WM_SETFONT = 0x0030;
		private const int WM_GETFONT = 0x0031;
		private const int WM_SETHOTKEY = 0x0032;
		private const int WM_GETHOTKEY = 0x0033;
		private const int WM_QUERYDRAGICON = 0x0037;
		private const int WM_COMPAREITEM = 0x0039;
		private const int WM_GETOBJECT = 0x003D;
		private const int WM_COMPACTING = 0x0041;
		private const int WM_COMMNOTIFY = 0x0044 ;
		private const int WM_WINDOWPOSCHANGING = 0x0046;
		private const int WM_WINDOWPOSCHANGED = 0x0047;
		private const int WM_POWER = 0x0048;
		private const int WM_COPYDATA = 0x004A;
		private const int WM_CANCELJOURNAL = 0x004B;
		private const int WM_NOTIFY = 0x004E;
		private const int WM_INPUTLANGCHANGEREQUEST = 0x0050;
		private const int WM_INPUTLANGCHANGE = 0x0051;
		private const int WM_TCARD = 0x0052;
		private const int WM_HELP = 0x0053;
		private const int WM_USERCHANGED = 0x0054;
		private const int WM_NOTIFYFORMAT = 0x0055;
		private const int WM_CONTEXTMENU = 0x007B;
		private const int WM_STYLECHANGING = 0x007C;
		private const int WM_STYLECHANGED = 0x007D;
		private const int WM_DISPLAYCHANGE = 0x007E;
		private const int WM_GETICON = 0x007F;
		private const int WM_SETICON = 0x0080;
		private const int WM_NCCREATE = 0x0081;
		private const int WM_NCDESTROY = 0x0082;
		private const int WM_NCCALCSIZE = 0x0083;
		private const int WM_NCHITTEST = 0x0084;
		private const int WM_NCPAINT = 0x0085;
		private const int WM_NCACTIVATE = 0x0086;
		private const int WM_GETDLGCODE = 0x0087;
		private const int WM_SYNCPAINT = 0x0088;
		private const int WM_NCMOUSEMOVE = 0x00A0;
		private const int WM_NCLBUTTONDOWN = 0x00A1;
		private const int WM_NCLBUTTONUP = 0x00A2;
		private const int WM_NCLBUTTONDBLCLK = 0x00A3;
		private const int WM_NCRBUTTONDOWN = 0x00A4;
		private const int WM_NCRBUTTONUP = 0x00A5;
		private const int WM_NCRBUTTONDBLCLK = 0x00A6;
		private const int WM_NCMBUTTONDOWN = 0x00A7;
		private const int WM_NCMBUTTONUP = 0x00A8;
		private const int WM_NCMBUTTONDBLCLK = 0x00A9;
		private const int WM_KEYDOWN = 0x0100;
		private const int WM_KEYUP = 0x0101;
		private const int WM_CHAR = 0x0102;
		private const int WM_DEADCHAR = 0x0103;
		private const int WM_SYSKEYDOWN = 0x0104;
		private const int WM_SYSKEYUP = 0x0105;
		private const int WM_SYSCHAR = 0x0106;
		private const int WM_SYSDEADCHAR = 0x0107;
		private const int WM_KEYLAST = 0x0108;
		private const int WM_IME_STARTCOMPOSITION = 0x010D;
		private const int WM_IME_ENDCOMPOSITION = 0x010E;
		private const int WM_IME_COMPOSITION = 0x010F;
		private const int WM_IME_KEYLAST = 0x010F;
		private const int WM_INITDIALOG = 0x0110;
		private const int WM_COMMAND = 0x0111;
		private const int WM_SYSCOMMAND = 0x0112;
		private const int WM_TIMER = 0x0113;
		private const int WM_HSCROLL = 0x0114;
		private const int WM_VSCROLL = 0x0115;
		private const int WM_INITMENU = 0x0116;
		private const int WM_INITMENUPOPUP = 0x0117;
		private const int WM_MENUSELECT = 0x011F;
		private const int WM_MENUCHAR = 0x0120;
		private const int WM_ENTERIDLE = 0x0121;
		private const int WM_MENURBUTTONUP = 0x0122;
		private const int WM_MENUDRAG = 0x0123;
		private const int WM_MENUGETOBJECT = 0x0124;
		private const int WM_UNINITMENUPOPUP = 0x0125;
		private const int WM_MENUCOMMAND = 0x0126;
		private const int WM_CTLCOLORMSGBOX = 0x0132;
		private const int WM_CTLCOLOREDIT = 0x0133;
		private const int WM_CTLCOLORLISTBOX = 0x0134;
		private const int WM_CTLCOLORBTN = 0x0135;
		private const int WM_CTLCOLORDLG = 0x0136;
		private const int WM_CTLCOLORSCROLLBAR = 0x0137;
		private const int WM_CTLCOLORSTATIC = 0x0138;
		private const int WM_MOUSEMOVE = 0x0200;
		private const int WM_LBUTTONDOWN = 0x0201;
		private const int WM_LBUTTONUP = 0x0202;
		private const int WM_LBUTTONDBLCLK = 0x0203;
		private const int WM_RBUTTONDOWN = 0x0204;
		private const int WM_RBUTTONUP = 0x0205;
		private const int WM_RBUTTONDBLCLK = 0x0206;
		private const int WM_MBUTTONDOWN = 0x0207;
		private const int WM_MBUTTONUP = 0x0208;
		private const int WM_MBUTTONDBLCLK = 0x0209;
		private const int WM_MOUSEWHEEL = 0x020A;
		private const int WM_PARENTNOTIFY = 0x0210;
		private const int WM_ENTERMENULOOP = 0x0211;
		private const int WM_EXITMENULOOP = 0x0212;
		private const int WM_NEXTMENU = 0x0213;
		private const int WM_SIZING = 0x0214;
		private const int WM_CAPTURECHANGED = 0x0215;
		private const int WM_MOVING = 0x0216;
		private const int WM_DEVICECHANGE = 0x0219;
		private const int WM_MDICREATE = 0x0220;
		private const int WM_MDIDESTROY = 0x0221;
		private const int WM_MDIACTIVATE = 0x0222;
		private const int WM_MDIRESTORE = 0x0223;
		private const int WM_MDINEXT = 0x0224;
		private const int WM_MDIMAXIMIZE = 0x0225;
		private const int WM_MDITILE = 0x0226;
		private const int WM_MDICASCADE = 0x0227;
		private const int WM_MDIICONARRANGE = 0x0228;
		private const int WM_MDIGETACTIVE = 0x0229;
		private const int WM_MDISETMENU = 0x0230;
		private const int WM_ENTERSIZEMOVE = 0x0231;
		private const int WM_EXITSIZEMOVE = 0x0232;
		private const int WM_DROPFILES = 0x0233;
		private const int WM_MDIREFRESHMENU = 0x0234;
		private const int WM_IME_SETCONTEXT = 0x0281;
		private const int WM_IME_NOTIFY = 0x0282;
		private const int WM_IME_CONTROL = 0x0283;
		private const int WM_IME_COMPOSITIONFULL = 0x0284;
		private const int WM_IME_SELECT = 0x0285;
		private const int WM_IME_CHAR = 0x0286;
		private const int WM_IME_REQUEST = 0x0288;
		private const int WM_IME_KEYDOWN = 0x0290;
		private const int WM_IME_KEYUP = 0x0291;
		private const int WM_MOUSEHOVER = 0x02A1;
		private const int WM_MOUSELEAVE = 0x02A3;
		private const int WM_CUT = 0x0300;
		private const int WM_COPY = 0x0301;
		private const int WM_PASTE = 0x0302;
		private const int WM_CLEAR = 0x0303;
		private const int WM_UNDO = 0x0304;
		private const int WM_RENDERFORMAT = 0x0305;
		private const int WM_RENDERALLFORMATS = 0x0306;
		private const int WM_DESTROYCLIPBOARD = 0x0307;
		private const int WM_DRAWCLIPBOARD = 0x0308;
		private const int WM_PAINTCLIPBOARD = 0x0309;
		private const int WM_VSCROLLCLIPBOARD = 0x030A;
		private const int WM_SIZECLIPBOARD = 0x030B;
		private const int WM_ASKCBFORMATNAME = 0x030C;
		private const int WM_CHANGECBCHAIN = 0x030D;
		private const int WM_HSCROLLCLIPBOARD = 0x030E;
		private const int WM_QUERYNEWPALETTE = 0x030F;
		private const int WM_PALETTEISCHANGING = 0x0310;
		private const int WM_PALETTECHANGED = 0x0311;
		private const int WM_HOTKEY = 0x0312;
		private const int WM_PRINT = 0x0317;
		private const int WM_PRINTCLIENT = 0x0318;
		private const int WM_HANDHELDFIRST = 0x0358;
		private const int WM_HANDHELDLAST = 0x035F;
		private const int WM_AFXFIRST = 0x0360;
		private const int WM_AFXLAST = 0x037F;
		private const int WM_PENWINFIRST = 0x0380;
		private const int WM_PENWINLAST = 0x038F;
		private const int WM_APP = 0x8000;
		private const int WM_USER = 0x0400;
		private const int WM_REFLECT = WM_USER + 0x1c00;
		private const int WM_APPBARNOTIFY = WM_USER + 100;
		private const int WS_CAPTION = 0x00C00000;
		private const int WS_SYSMENU = 0x00080000;
		#endregion
		#region Private API Functions
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int AdjustWindowRectEx(ref RECT lpRect, int dsStyle, int bMenu, int dwEsStyle);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int ClientToScreen(IntPtr hwnd, ref POINT lpPoint);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern Int16 GetAsyncKeyState(int vKey);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int GetClientRect(IntPtr hwnd, ref RECT rect);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int GetKeyState(Int16 nVirtKey);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int GetMessagePos();
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int GetSystemMetrics(int nIndex);
		[DllImport("kernel32.dll", SetLastError=true)]
		private static extern int GetTickCount();
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int GetWindowLong(IntPtr hwnd, Int16 nIndex);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int GetWindowRect(IntPtr hwnd, ref RECT rect);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int InflateRect(ref RECT rect, int x, int y);
		[DllImport("User32.dll", SetLastError=true)]
		private static extern int KillTimer(IntPtr hwnd, int nIDEvent);
		[DllImport("User32.dll", CharSet=CharSet.Auto)]
		private static extern bool ReleaseCapture();
		[DllImport("Kernel32.dll", SetLastError=true)]
		private static extern void RtlMoveMemory(ref RECT Destination, IntPtr Source, int Length);
		[DllImport("Kernel32.dll", SetLastError=true)]
		private static extern void RtlMoveMemory(IntPtr Destination, ref RECT Source, int Length);
		[DllImport("user32.dll", CharSet=CharSet.Auto)]
		private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int SetTimer(IntPtr hWnd, int nIDEvent, int uElapse, int lpTimerFunc);
		[DllImport("User32.dll", CharSet=CharSet.Auto)]
		private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, int flags);
		[DllImport("shell32.dll", SetLastError=true)]
		private static extern int SHAppBarMessage(int message, ref APPBARDATA pData);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int SystemParametersInfoA(int uAction, int uParam, ref bool lpvParam, int fuWinIni);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int SystemParametersInfoA(int uAction, int uParam, ref RECT lpvParam, int fuWinIni);
		[DllImport("user32.dll", SetLastError=true)]
		private static extern int UpdateWindow(IntPtr hwnd);
		#endregion
		#region Public Enumerations
		/// 
		/// Enumeration for the edge that the AppBar attaches to
		/// 
		public enum AppBarEdge
		{
			Left = ABE_LEFT, 
			Top = ABE_TOP, 
			Right = ABE_RIGHT, 
			Bottom = ABE_BOTTOM, 
			Unknown = ABE_UNKNOWN, 
			Float = ABE_FLOAT
		}
		/// 
		/// Enumerations for the docking options
		/// 
		[FlagsAttribute()]
			public enum DockFlags 
		{
			AllowLeft = ABF_ALLOWLEFT, 
			AllowTop = ABF_ALLOWTOP, 
			AllowRight = ABF_ALLOWRIGHT, 
			AllowBottom = ABF_ALLOWBOTTOM, 
			AllowFloat = ABF_ALLOWFLOAT
		}
		#endregion
		#region Public Properties
		/// 
		/// The edges the app bar can attach to
		/// 
		[TypeConverterAttribute(typeof(DockFlagConverter)), 
		Editor(typeof(DockFlagEditor), typeof(UITypeEditor)), 
		Category("AppBar"), 
		DefaultValue(DockFlags.AllowFloat), 
		Description("The edges the app bar can attach to")]
		public DockFlags DockOptions 
		{
			get {return (DockFlags) this.appBarState.dockFlags;}
			set {this.appBarState.dockFlags = (int) value;}
		}
		/// 
		/// The increments by which the AppBar can be resized horizontally
		/// 
		[Category("AppBar"), 
		DefaultValue(0), 
		Description("The increments by which the AppBar can be resized horizontally")]
		public int HorzSizeInc 
		{
			get {return this.appBarState.sizeInc.cx;}
			set {this.appBarState.sizeInc.cx = value;}
		}
        
		/// 
		/// The increments by which the AppBar can be resized vertically
		/// 
		[Category("AppBar"), 
		DefaultValue(0), 
		Description("The increments by which the AppBar can be resized vertically")]
		public int VertSizeInc 
		{
			get {return this.appBarState.sizeInc.cy;}
			set {this.appBarState.sizeInc.cy = value;}
		}
        
		/// 
		/// The default starting position of the AppBar
		/// 
		[Category("AppBar"), 
		DefaultValue(AppBarEdge.Float), 
		Description("The default starting position of the AppBar")]
		public AppBarEdge Edge 
		{
			get {return (AppBarEdge) this.appBarState.state;}
			set {this.appBarState.state = (int) value;}
		}
		/// 
		/// Whether or not the AppBar hides and then slides out from the edge
		/// 
		[Category("AppBar"), 
		DefaultValue(false), 
		Description("Whether or not the AppBar hides and then slides out from the edge")]
		public bool AutoHide 
		{
			get {return this.appBarState.autoHide;}
			set {this.appBarState.autoHide = value;}
		}
		/// 
		/// Whether the AppBar is always on top
		/// 
		[Category("AppBar"), 
		DefaultValue(false), 
		Description("Whether the AppBar is always on top")]
		public bool AlwaysOnTop 
		{
			get {return this.appBarState.alwaysOnTop;}
			set {this.appBarState.alwaysOnTop = value;}
		}
		/// 
		/// The width of the AppBar when docked on the side
		/// 
		[Category("AppBar"), 
		DefaultValue(0), 
		Description("The width of the AppBar when docked on the side")]
		public int HorzDockSize 
		{
			get {return this.appBarState.dockSizeHorizontal;}
			set {this.appBarState.dockSizeHorizontal = value;}
		}
		/// 
		/// The height of the AppBar when docked on the top or bottom
		/// 
		[Category("AppBar"), 
		DefaultValue(0), 
		Description("The height of the AppBar when docked on the top or bottom")]
		public int VertDockSize 
		{
			get {return this.appBarState.dockSizeVertical;}
			set {this.appBarState.dockSizeVertical = value;}
		}
		#endregion
		#region Private Variables
		private APPBARSTATE appBarState;
		private bool initializing = false;
		private bool moving = false;
		private System.ComponentModel.IContainer components;
		#endregion
		#region Constructors
		public AppBarForm()
		{
			this.initializing = true;
			components = null;
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
			//
			// TODO: Add any constructor code after InitializeComponent call
			//
			// Force the shell to update its list of AppBars and the workarea.
			// This is a precaution and is very useful when debugging. If you create
			// an AppBar and then just terminate the application, the shell still 
			// thinks that the AppBar exists and the user's workarea is smaller than
			// it should be. When a new AppBar is created, calling this function 
			// fixes the user's workarea.
			// Set default state of AppBar to docked on bottom with no width & height
			this.appBarState = new APPBARSTATE();
			this.appBarState.size = Marshal.SizeOf(this.appBarState);
			//if (this.DesignMode)
			this.appBarState.state = ABE_FLOAT;
			this.appBarState.autoHide = false;
			this.appBarState.alwaysOnTop = false;
			this.appBarState.dockSizeHorizontal = 30;
			this.appBarState.dockSizeVertical = 30;
			this.appBarState.taskBarState = AppBarMessage(ABM_GETSTATE);
			this.appBarState.dockFlags = ABF_ALLOWANYWHERE;
			this.appBarState.sizeInc = new SIZE(0, 0); // Don't allow re-sizing
			this.appBarState.proposedState = ABE_UNKNOWN;
			this.appBarState.fullScreenAppOpen = false;
			this.appBarState.autoHideIsVisible = false;
			this.appBarState.floatRect = new RECT(this.Left, this.Top, this.Left + this.Width, this.Top + this.Height); 
			this.initializing = false;
		}
		/// 
		/// Clean up any resources being used.
		/// 
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		#endregion
		#region Windows Form Designer generated code
		/// 
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// 
		private void InitializeComponent()
		{
			// 
			// AppBarForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(400, 270);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
			this.Location = new System.Drawing.Point(500, 500);
			this.Name = "AppBarForm";
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.AppBar_MouseDown);
			this.Load += new System.EventHandler(this.AppBarForm_Load);
			this.LocationChanged += new System.EventHandler(this.AppBarForm_LocationChanged);
		}
		#endregion
		#region Private Functions
		private int GetAutohideEdge() 
		{
			for (int edge = ABE_LEFT; edge <= ABE_BOTTOM; edge++) 
			{
				if (this.Handle.ToInt32() == AppBarMessage(ABM_GETAUTOHIDEBAR, edge)) 
				{
					// We are an auto-hide AppBar and we found our edge.
					return edge;
				}
			}
			// NOTE: If AppBar is docked but not auto-hidden, we return ABE_UNKNOWN
			return ABE_UNKNOWN; 
		}
		private bool ModifyStyle(Int16 styleOffset, int remove, int add, int flags)
		{
			int style = GetWindowLong(this.Handle, styleOffset);
			int newStyle = (style & (~ remove)) | add;
			if (style == newStyle)
				return false;
			SetWindowLong(this.Handle, styleOffset, newStyle);
			if (flags != 0)
				SetWindowPos(this.Handle, new IntPtr(0), 0, 0, 0, 0, ((SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE) | flags));
			return true;
		}
        
		private void MimicState (int stateChangedMask, int state) 
		{
			bool anyChange = false; // Assume that nothing changes
			// If the autohide state changed AND our style allows 
			// us to mimic the Autohide state
			if (((stateChangedMask & ABS_AUTOHIDE) != 0) && 
				((this.appBarState.dockFlags & ABF_MIMICTASKBARAUTOHIDE) != 0)) 
			{
				bool autoHide = (ABS_AUTOHIDE & state) != 0;
				// If our state doesn't match, change our state
				if (this.appBarState.autoHide != autoHide) 
				{
					this.appBarState.autoHide = autoHide;
					anyChange = true;
				}
			}
			// If the AlwaysOnTop state changed AND our style allows 
			// us to mimic the AlwaysOnTop state/
			if (((stateChangedMask & ABS_ALWAYSONTOP) != 0) && 
				((this.appBarState.dockFlags & ABF_MIMICTASKBARALWAYSONTOP) != 0)) 
			{
				// If our state doesn't match, change our state
				this.appBarState.alwaysOnTop = (ABS_ALWAYSONTOP & state) != 0;
				anyChange = true;
			}
			if (anyChange) 
			{
				SetState();
				ShowHiddenAppBar(false);
			}
		}
		private void SetState(int state) 
		{
			if (this.DesignMode)
				return;
			// If the AppBar is registered as auto-hide, unregister it.
			int edge = GetAutohideEdge();
			RECT currentRect;
			RECT position = new RECT();
			if (edge != ABE_UNKNOWN) 
			{
				// Our AppBar is auto-hidden, unregister it.
				AppBarMessage(ABM_SETAUTOHIDEBAR, edge, 0);
			}
			// Save the new requested state
			this.appBarState.state = state;
			switch (state) 
			{
				case ABE_UNKNOWN:
					// We are being completely unregisterred.
					// Probably, the AppBar window is being destroyed.
					// If the AppBar is registered as NOT auto-hide, unregister it.
					AppBarMessage(ABM_REMOVE);
					break;
				case ABE_FLOAT:
					// We are floating and therefore are just a regular window.
					// Tell the shell that the docked AppBar should be of 0x0 dimensions
					// so that the workspace is not affected by the AppBar.
					currentRect = new RECT(0, 0, 0, 0);
					AppBarMessage(ABM_SETPOS, state, 0, ref currentRect);
					SetWindowPos(this.Handle, IntPtr.Zero, this.appBarState.floatRect.left, this.appBarState.floatRect.top, 
						this.appBarState.floatRect.Width, this.appBarState.floatRect.Height, 
						SWP_NOZORDER | SWP_NOACTIVATE);
					break;
				default:
					if (this.appBarState.autoHide & !(Convert.ToBoolean(AppBarMessage(ABM_SETAUTOHIDEBAR, GetState(), 1), CultureInfo.InvariantCulture)))
					{
						// We couldn't set the AppBar on a new edge, let's dock it instead.
						this.appBarState.autoHide = false;
						// Call a virtual function to let derived classes know that the AppBar
						// changed from auto-hide to docked.
						OnAppBarForcedToDocked();
					}
					GetRect(GetState(), ref position);
					if (this.appBarState.autoHide) 
					{
						currentRect = new RECT(0,0,0,0);
						AppBarMessage(ABM_SETPOS, ABE_LEFT, 0, ref currentRect);
					} 
					else 
					{
						// Tell the shell where the AppBar is.
						AppBarMessage(ABM_SETPOS, state, 0, ref position);
					}
					AdjustLocationForAutohide(this.appBarState.autoHideIsVisible, ref position);
					// Slide window in from or out to the edge
					SlideWindow(position);
					break;
			}
			// Set the AppBar's z-order appropriately
			IntPtr pwnd = new IntPtr(HWND_NOTOPMOST);        // Assume normal Z-Order
			if (this.appBarState.alwaysOnTop) 
			{    
				// If we are supposed to be always-on-top, put us there.
				pwnd = new IntPtr(HWND_TOPMOST);
				if (this.appBarState.fullScreenAppOpen) 
				{
					// But, if a full-screen window is opened, put ourself at the bottom
					// of the z-order so that we don't cover the full-screen window
					pwnd = new IntPtr(HWND_BOTTOM);
				}
			}
			SetWindowPos(this.Handle, pwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
			// Make sure that any auto-hide appabrs stay on top of us after we move
			// even though our activation state has not changed.
			AppBarMessage(ABM_ACTIVATE);
			// Tell our derived class that there is a state change
			AppBarStateChange(false, state);
		}
		private void SetState() 
		{
			SetState(GetState());
		}
		private int AppBarMessage (int message, int edge /*= ABE_FLOAT*/, 
			int lParam /*= 0*/, ref RECT position /*= null*/) 
		{
			// Initialize an APPBARDATA structure.
			APPBARDATA abd = new APPBARDATA();
			abd.size = Marshal.SizeOf(abd);
			abd.hWnd = this.Handle.ToInt32();
			abd.callbackMessage = WM_APPBARNOTIFY;
			abd.edge = edge;
			abd.position = position;
			abd.lParam = lParam;
			int result = SHAppBarMessage(message, ref abd);
			// If the caller passed a rectangle, return the updated rectangle.
			position = abd.position;
			return result;
		}
		private int AppBarMessage (int message, int edge /*= ABE_FLOAT*/, 
			int lParam /*= 0*/)
		{
			// Initialize an APPBARDATA structure.
			APPBARDATA abd = new APPBARDATA();
			abd.size = Marshal.SizeOf(abd);
			abd.hWnd = this.Handle.ToInt32();
			abd.callbackMessage = WM_APPBARNOTIFY;
			abd.edge = edge;
			abd.position = new RECT(0, 0, 0, 0);
			abd.lParam = lParam;
			int result = SHAppBarMessage(message, ref abd);
			// If the caller passed a rectangle, return the updated rectangle.
			return result;
		}
		private int AppBarMessage(int message)
		{
			return AppBarMessage(message, ABE_FLOAT, 0);
		}
		private int AppBarMessage(int message, int edge)
		{
			return AppBarMessage(message, edge, 0);
		}
		private int CalcProposedState (POINT point) 
		{
			// Force the AppBar to float if the user is holding down the Ctrl key
			// and the AppBar's style allows floating.
			bool fForceFloat = ((GetKeyState(VK_CONTROL) & 0x8000) != 0) 
				&& ((this.appBarState.dockFlags & ABF_ALLOWFLOAT) != 0);
			return (fForceFloat ? ABE_FLOAT : GetEdgeFromPoint(this.appBarState.dockFlags, point));
		}
		private void GetRect (int stateProposed, ref RECT rectProposed) 
		{
			// This function finds the x, y, cx, cy of the AppBar window
			if (ABE_FLOAT == stateProposed) 
			{
				// The AppBar is floating, the proposed rectangle is correct
			} 
			else 
			{
				// The AppBar is docked or auto-hide
				// Set dimensions to full screen.
				rectProposed = new RECT(0, 0, 
					GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
				// Subtract off what we want from the full screen dimensions
				if (!this.appBarState.autoHide) 
				{
					// Ask the shell where we can dock.
					AppBarMessage(ABM_QUERYPOS, stateProposed, 0, ref rectProposed);
				}
				switch (stateProposed) 
				{
					case ABE_LEFT: 
						rectProposed.right = 
							rectProposed.left + this.appBarState.dockSizeHorizontal;
						break;
					case ABE_TOP:
						rectProposed.bottom = 
							rectProposed.top + this.appBarState.dockSizeVertical;
						break;
					case ABE_RIGHT: 
						rectProposed.left = 
							rectProposed.right - this.appBarState.dockSizeHorizontal;
						break;
					case ABE_BOTTOM: 
						rectProposed.top = 
							rectProposed.bottom - this.appBarState.dockSizeVertical;
						break;
				}
			}
		}
		private bool AdjustLocationForAutohide (bool show, ref RECT rect) 
		{
			if ((GetState() == ABE_UNKNOWN) || (GetState() == ABE_FLOAT) || 
				!this.appBarState.autoHide) 
			{
				// If we are not docked on an edge OR we are not auto-hidden, there is
				// nothing for us to do; just return.
				return false;
			}
			// Showing/hiding doesn't change our size; only our position.
			int x = 0;
			int y = 0; // Assume a position of (0, 0)
			if (show) 
			{
				// If we are on the right or bottom, calculate our visible position
				switch (GetState()) 
				{
					case ABE_RIGHT:
						x = GetSystemMetrics(SM_CXSCREEN) - rect.Width;
						break;
					case ABE_BOTTOM:
						y = GetSystemMetrics(SM_CYSCREEN) - rect.Height;
						break;
				}
			} 
			else 
			{
				// Keep a part of the AppBar visible at all times
				int cxVisibleBorder = 2 * GetSystemMetrics(SM_CXBORDER);
				int cyVisibleBorder = 2 * GetSystemMetrics(SM_CYBORDER);
				// Calculate our x or y coordinate so that only the border is visible
				switch (GetState()) 
				{
					case ABE_LEFT: 
						x = -(rect.Width - cxVisibleBorder); 
						break;
					case ABE_RIGHT: 
						x = GetSystemMetrics(SM_CXSCREEN) - cxVisibleBorder; 
						break;
					case ABE_TOP:
						y = -(rect.Height - cyVisibleBorder); 
						break;
					case ABE_BOTTOM:
						y = GetSystemMetrics(SM_CYSCREEN) - cyVisibleBorder; 
						break;
				}
			}
			rect = new RECT(x, y, x + rect.Width, y + rect.Height);
			return true;
		}
		private void ShowHiddenAppBar (bool show /*= true*/) 
		{
			// Get our window location in screen coordinates.
			RECT position = new RECT();
			GetWindowRect(this.Handle, ref position);
			this.appBarState.autoHideIsVisible = true; // Assume that we are visible
			if (AdjustLocationForAutohide(show, ref position)) 
			{
				// the rectangle was adjusted, we are an autohide bar
				// Rememebr whether we are visible or not.
				this.appBarState.autoHideIsVisible = show;
				// Slide window in from or out to the edge
				SlideWindow(position);
			}
			if (show)
				// Associate a timer with the AppBar. The timer is used to determine
				// when a visible, inactive, auto-hide AppBar should be re-hidden.
				SetTimer(this.Handle, AUTOHIDETIMERID, AUTOHIDETIMERINTERVAL, 0);
			else
			{
				// Must have just hidden it, so don't bother with the timer for a while
				KillTimer(this.Handle, AUTOHIDETIMERID);
			}
		}
		private void SlideWindow(RECT rectEnd) 
		{
			bool fullDragOn = false;
			// Only slide the window if the user has FullDrag turned on
			SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, ref fullDragOn, 0);
			// Get the current window position
			RECT rectStart = new RECT();
			GetWindowRect(this.Handle, ref rectStart); 
			if (fullDragOn && (rectStart != rectEnd)) 
			{
				// Get our starting and ending time.
				int timeStart = GetTickCount();
				int timeEnd = timeStart + AUTOHIDETIMERINTERVAL;
				int time;
				while ((time = GetTickCount()) < timeEnd) 
				{
					// While we are still sliding, calculate our new position
					int x = rectStart.left - (rectStart.left - rectEnd.left) 
						* (time - timeStart) / AUTOHIDETIMERINTERVAL;
					int y = rectStart.top - (rectStart.top - rectEnd.top) 
						* (time - timeStart) / AUTOHIDETIMERINTERVAL;
					int nWidth = rectStart.Width - (rectStart.Width - rectEnd.Width) 
						* (time - timeStart) / AUTOHIDETIMERINTERVAL;
					int nHeight = rectStart.Height - (rectStart.Height - rectEnd.Height) 
						* (time - timeStart) / AUTOHIDETIMERINTERVAL;
					// Show the window at its changed position
					SetWindowPos(this.Handle, IntPtr.Zero, x, y, nWidth, nHeight, 
						SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME);
					UpdateWindow(this.Handle);
				}
			}
			// Make sure that the window is at its final position
			SetWindowPos(this.Handle, IntPtr.Zero, rectEnd.left, rectEnd.top, rectEnd.Width, rectEnd.Height,
				SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME);
			UpdateWindow(this.Handle);
			}
		private static int GetEdgeFromPoint (int flags, POINT point) 
		{
			int state = ABE_FLOAT; // Assume that the AppBar is floating
			// Let's get floating out of the way first
			if ((flags & ABF_ALLOWFLOAT) != 0) 
			{
				// Get the rectangle that bounds the size of the screen
				// minus any docked (but not-autohidden) AppBars.
				RECT position = new RECT();
				SystemParametersInfoA(SPI_GETWORKAREA, 0, ref position, 0);
				// Leave a 1/2 width/height-of-a-scrollbar gutter around the workarea
				InflateRect(ref position, -GetSystemMetrics(SM_CXVSCROLL), -GetSystemMetrics(SM_CYHSCROLL));
				if (PtInRect(position, point) || ((flags & ABF_ALLOWANYEDGE) == 0)) 
				{
					// If the point is in the adjusted workarea
					// OR no edges are allowed.
					return state; // The AppBar should float
				}
			}
			// If we get here, the AppBar should be docked; determine the proper edge
			// Get the dimensions of the screen
			int cxScreen = GetSystemMetrics(SM_CXSCREEN);
			int cyScreen = GetSystemMetrics(SM_CYSCREEN);
			// Find the center of the screen
			POINT pointCenter = new POINT(cxScreen / 2, cyScreen / 2);
			// Find the distance from the point to the center
			POINT pointOffset = new POINT(point.X - pointCenter.X, point.Y - pointCenter.Y);
			// Determine if the point is farther from the left/right or top/bottom
			bool isLeftOrRight = (Math.Abs(pointOffset.Y) * cxScreen) <=
				(Math.Abs(pointOffset.X) * cyScreen);
			// If (it should be left/right, AND we allow left/right) 
			// OR we don't allow top/bottom
			if ((isLeftOrRight && ((flags & ABF_ALLOWLEFTRIGHT) != 0)) ||
				((flags & ABF_ALLOWTOPBOTTOM) == 0)) 
			{
				state = (0 <= pointOffset.X) ? ABE_RIGHT : ABE_LEFT;
			} 
			else 
			{
				state = (0 <= pointOffset.Y) ? ABE_BOTTOM : ABE_TOP;
			}
 
			return state; // Return calculated edge
		}
		private int GetState () 
		{ 
			return ((this.appBarState.proposedState != ABE_UNKNOWN) 
				? this.appBarState.proposedState : this.appBarState.state); 
		}
		private bool IsEdgeLeftOrRight (int edge) 
		{ 
			return ((edge == ABE_LEFT) || (edge == ABE_RIGHT)); 
		}
		private void ClientToScreen(IntPtr hwnd, ref RECT rect)
		{
			POINT point = new POINT();
			point.X = rect.left;
			point.Y = rect.top;
			ClientToScreen(hwnd, ref point);
			rect.left = point.X;
			rect.top = point.Y;
			point.X = rect.right;
			point.Y = rect.bottom;
			ClientToScreen(hwnd, ref point);
			rect.right = point.X;
			rect.bottom = point.Y;
		}
        
		private int GetStyle()
		{
			return GetWindowLong(this.Handle, GWL_STYLE);
		}
        
		private int GetExStyle()
		{
			return GetWindowLong(this.Handle, GWL_EXSTYLE);
		}
        
		private static bool PtInRect (RECT rect, POINT point)
		{
			if (point.X < rect.left | point.X > rect.right)
				return false;
			if (point.Y < rect.top | point.Y > rect.bottom)
				return false;
			return true;
		}
		private void AppBarStateChange (bool proposed, int stateProposed) 
		{
			bool fullDragOn = false;
			// Find out if (the user has FullDrag turned on
			SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, ref fullDragOn, 0);
			// If FullDrag is turned on OR the appbar has changed position
			if ((fullDragOn | ! proposed) & !(stateProposed == ABE_UNKNOWN))
			{
				if (stateProposed == ABE_FLOAT)
					// Show the window adornments
					ModifyStyle((short) GWL_STYLE, 0, (WS_CAPTION | WS_SYSMENU), (SWP_DRAWFRAME));
				else
					// Hide the window adornments
					ModifyStyle((short) GWL_STYLE, (WS_CAPTION | WS_SYSMENU), 0, (SWP_DRAWFRAME));
			}
			OnAppBarStateChange(proposed, stateProposed);
		}
		private void ABNFullScreenApp (bool open) 
		{
			// This function is called when a FullScreen window is openning or 
			// closing. A FullScreen window is a top-level window that has its caption 
			// above the top of the screen allowing the entire screen to be occupied 
			// by the window's client area. 
 
			// If the AppBar is a topmost window when a FullScreen windiw is activated, 
			// we need to change our window to a non-topmost window so that the AppBar 
			// doesn't cover the FullScreen window's client area.
			// If the FullScreen window is closing, we need to set the AppBar's 
			// Z-Order back to when the user wants it to be.
			if (this.appBarState.fullScreenAppOpen != open)
			{
				this.appBarState.fullScreenAppOpen = open;
				SetState();
			}
			OnAbnFullScreenApp(open);
		}
		private void ABNPosChanged () 
		{
			// The TaskBar or another AppBar has changed its size or position. 
			if ((GetState() != ABE_FLOAT) && !this.appBarState.autoHide) 
			{
				// If we're not floating and we're not auto-hidden, we have to 
				// reposition our window.
				SetState();
			}
			OnAbnPosChanged();
		}
        
		private void ABNWindowArrange(bool beginning)
		{
			OnAbnWindowArrange(beginning);
		}
		private void ABNStateChange (int stateChangedMask, int state) 
		{
			// Make our state mimic the taskbar's state.
			MimicState(stateChangedMask, state);
			OnAbnStateChange(stateChangedMask, state);
		}
		#endregion
		#region Protected Functions
		protected void OnMouseDown()
		{
			ReleaseCapture();
			SendMessage(this.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
		}
		protected virtual void OnAppBarStateChange(bool proposed, int proposedState)
		{
			// This function intentionally left blank.
		}
		protected virtual void OnAppBarForcedToDocked() 
		{
			// Display the ppBar's caption text as the message box caption text.
			string sz = "AppBar";
			//GetWindowText(this.Handle, sz);
			MessageBox.Show(null, 
				"There is already an auto hidden window on this edge.\r\nOnly one auto hidden window is allowed on each edge.",
				sz,MessageBoxButtons.OK, MessageBoxIcon.Stop);
		}
		protected virtual void OnAbnWindowArrange (bool beginning) 
		{
			// This function intentionally left blank.
		}
		protected virtual void OnAbnStateChange (int stateChangedMask, int state) 
		{
			// This function intentionally left blank.
		}
		protected virtual void OnAbnFullScreenApp (bool open) 
		{
			// This function intentionally left blank.
		}
		private void OnAbnPosChanged () 
		{
			// This function intentionally left blank.
		}
		#endregion
		#region Message Processors
		[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
		protected override void WndProc(ref System.Windows.Forms.Message m)
		{
			switch (m.Msg)
			{
				case WM_APPBARNOTIFY:
					OnAppBarCallbackMsg(ref m);
					break;
				case WM_CREATE:
					OnCreate(ref m);
					return;
				case WM_DESTROY:
					OnDestroy(ref m);
					return;
				case WM_TIMER:
					OnTimer(ref m);
					return;
				case WM_NCHITTEST:
					OnNcHitTest(ref m);
					return;
				case WM_ENTERSIZEMOVE:
					this.moving = true;
					OnEnterSizeMove(ref m);
					Debug.WriteLine("OnEnterSizeMove");
					break;
				case WM_EXITSIZEMOVE:
					OnExitSizeMove(ref m);
					this.moving = false;
					Debug.WriteLine("OnExitSizeMove");
					break;
				case WM_NCMOUSEMOVE:
					OnNcMouseMove(ref m);
					return;
				case WM_WINDOWPOSCHANGED:
					OnWindowPosChanged(ref m);
					Debug.WriteLine("OnWindowPosChanged");
					return;
				case WM_MOVING:
					OnMoving(ref m);
					Debug.WriteLine("OnMoving");
					break;
				case WM_ACTIVATE:
					OnActivate(ref m);
					return;
				case WM_SIZING:
					OnSizing(ref m);
					Debug.WriteLine("OnSizing");
					break;
			}
			base.WndProc(ref m);
		}
		// Called when the AppBar recieves a WM_APPBARNOTIFY window message
		private void OnAppBarCallbackMsg (ref Message message) 
		{
			switch (message.WParam.ToInt32()) 
			{
				case ABN_FULLSCREENAPP: 
					ABNFullScreenApp(Convert.ToBoolean(message.WParam.ToInt32(), CultureInfo.InvariantCulture)); 
					break;
				case ABN_POSCHANGED:
					ABNPosChanged(); 
					break;
				case ABN_WINDOWARRANGE:
					ABNWindowArrange(Convert.ToBoolean(message.WParam.ToInt32(), CultureInfo.InvariantCulture)); 
					break;
				case ABN_STATECHANGE:
					// The shell sends ABN_STATECHANGE notifications at inappropriate 
					// times. So, we remember the TaskBar's current state and set
					// a mask indicating which states have actually changed. This mask
					// and the state information is passed to the derived class.
					// Get the state of the Taskbar
					int taskBarState = AppBarMessage(ABM_GETSTATE);
					// Prepare a mask indicating which states have changed. The code in
					// the derived class should only act on the states that have changed.
					int stateChangedMask = 0;
					if ((taskBarState & ABS_ALWAYSONTOP) != 
						(this.appBarState.taskBarState & ABS_ALWAYSONTOP)) 
					{
						stateChangedMask |= ABS_ALWAYSONTOP;
					}
					if ((taskBarState & ABS_AUTOHIDE) != 
						(this.appBarState.taskBarState & ABS_AUTOHIDE)) 
					{
						stateChangedMask |= ABS_AUTOHIDE;
					}
					// Call the derived class
					ABNStateChange(stateChangedMask, taskBarState);
					// Save the TaskBar's state so that we can see exactly which states
					// change the next time be get an ABN_STATECHANGE notification.
					this.appBarState.taskBarState = taskBarState;
					break;
			}
			message.Result = new IntPtr(0);
		}
		private void OnCreate(ref Message message) 
		{
        
			//if (CDialog::OnCreate(lpCreateStruct) == -1)
			// return(-1);
			base.WndProc(ref message);
        
			// Register our AppBar window with the Shell
			AppBarMessage(ABM_NEW);
        
			// Force the AppBar to mimic the state of the TaskBar
			// Assume that all states have changed
			MimicState(ABS_ALWAYSONTOP | ABS_AUTOHIDE, this.appBarState.taskBarState);
        
			message.Result = new IntPtr(0);
		}
		private void OnDestroy(ref Message message) 
		{
			//// CDialog::OnDestroy();
			base.WndProc(ref message);
			// Kill the Autohide timer 
			KillTimer(this.Handle, AUTOHIDETIMERID);
			// Unregister our AppBar window with the Shell
			SetState(ABE_UNKNOWN);
		}
		private void OnWindowPosChanged(ref Message message) 
		{
			// CDialog::OnWindowPosChanged(lpwndpos);
			base.WndProc(ref message);
			// When our window changes position, tell the Shell so that any 
			// auto-hidden AppBar on our edge stays on top of our window making it 
			// always accessible to the user.
			AppBarMessage(ABM_WINDOWPOSCHANGED);
		}
		private void OnActivate(ref Message message) 
		{
			//// CDialog::OnActivate(nState, pWndOther, bMinimized);
			base.WndProc(ref message);
			if ((message.WParam.ToInt32() & 0xFFFF) == WA_INACTIVE)
			{
				// Hide the AppBar if we are docked and auto-hidden
				ShowHiddenAppBar(false);
			}
			// When our window changes position, tell the Shell so that any 
			// auto-hidden AppBar on our edge stays on top of our window making it 
			// always accessible to the user.
			AppBarMessage(ABM_ACTIVATE);
		}
		private void OnTimer(ref Message message) 
		{
			// Get the position of the mouse and the AppBar's position
			// Everything must be in screen coordinates.
			POINT point = new POINT(GetMessagePos());
			RECT position = new RECT();
			GetWindowRect(this.Handle, ref position);
            
			// Add a little margin around the AppBar
			InflateRect(ref position, 2 * GetSystemMetrics(SM_CXDOUBLECLK), 
				2 * GetSystemMetrics(SM_CYDOUBLECLK));
			if (!PtInRect(position, point)) 
			{
				// If the mouse is NOT over the AppBar, hide the AppBar
				ShowHiddenAppBar(false);
			}
		}
		private void OnNcMouseMove(ref Message message) 
		{
			// If we are a docked, auto-hidden AppBar, shown us
			// when the user moves over our non-client area
			ShowHiddenAppBar(true);
			//// CDialog::OnNcMouseMove(nHitTest, point);
			base.WndProc(ref message);
		}
		private void OnNcHitTest(ref Message message) 
		{
			// Find out what the system thinks is the hit test code
			//// int hitResult = CDialog::OnNcHitTest(point);
			base.WndProc(ref message);
			int hitResult = message.Result.ToInt32();
			// NOTE: If the user presses the secondary mouse button, pretend that the
			// user clicked on the client area so that we get WM_CONTEXTMENU messages
			bool primaryMouseBtnDown = Convert.ToBoolean((GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) != 0 
				? VK_RBUTTON : VK_LBUTTON) & 0x8000) != 0, CultureInfo.InvariantCulture);
			if ((hitResult == HTCLIENT) && primaryMouseBtnDown) 
			{
				// User clicked in client area, allow AppBar to move. We get this 
				// behavior by pretending that the user clicked on the caption area.
				hitResult = HTCAPTION;
			}
			// When the AppBar is docked, the user can resize only one edge.
			// This next section determines which edge the user can resize.
			// To allow resizing, the AppBar window must have the WS_THICKFRAME style.
			// If the AppBar is docked and the hittest code is a resize code...
			if ((GetState() != ABE_FLOAT) && (GetState() != ABE_UNKNOWN) && 
				(HTSIZEFIRST <= hitResult) && (hitResult <= HTSIZELAST)) 
			{
				if (0 == (IsEdgeLeftOrRight(GetState()) ? 
					this.appBarState.sizeInc.cx : this.appBarState.sizeInc.cy)) 
				{
					// If the width/height size increment is zero, then resizing is NOT 
					// allowed for the edge that the AppBar is docked on.
					hitResult = HTBORDER; // Pretend that the mouse is not on a resize border
				} 
				else 
				{
					// Resizing IS allowed for the edge that the AppBar is docked on.
					// Get the location of the appbar's client area in screen coordinates.
					RECT rect = new RECT();
					GetClientRect(this.Handle, ref rect);
					ClientToScreen(this.Handle, ref rect);
					hitResult = HTBORDER; // Assume that we can't resize
					POINT point = new POINT(message.LParam.ToInt32());
					switch (GetState()) 
					{
						case ABE_LEFT:
							if (point.X > rect.right) hitResult = HTRIGHT;
							break;
						case ABE_TOP:
							if (point.Y > rect.bottom) hitResult = HTBOTTOM;
							break;
						case ABE_RIGHT:
							if (point.X < rect.left) hitResult = HTLEFT;
							break;
						case ABE_BOTTOM:
							if (point.Y < rect.top) hitResult = HTTOP;
							break;
					}
				}
			}
            
			message.Result = new IntPtr(hitResult); // Return the hittest code
		}
		private void OnEnterSizeMove(ref Message message) 
		{
			// The user started moving/resizing the AppBar, save its current state.
			this.appBarState.proposedState = GetState();
			message.Result = new IntPtr(0);
		}
		private void OnExitSizeMove(ref Message message) 
		{
			// The user stopped moving/resizing the AppBar, set the new state.
			// Save the new proposed state of the AppBar.
			int proposedState = this.appBarState.proposedState;
			// Set the proposed state back to unknown. This causes GetState
			// to return the current state rather than the proposed state.
			this.appBarState.proposedState = ABE_UNKNOWN;
			// Get the location of the window in screen coordinates
			RECT position = new RECT();
			GetWindowRect(this.Handle, ref position);
			// If the AppBar's state has changed...
			if (GetState() == proposedState) 
			{
				switch (GetState()) 
				{
					case ABE_UNKNOWN:
						break;
					case ABE_LEFT: 
					case ABE_RIGHT:
						// Save the new width of the docked AppBar
						this.appBarState.dockSizeHorizontal = position.Width; 
						break;
					case ABE_TOP: 
					case ABE_BOTTOM:
						this.appBarState.dockSizeVertical = position.Height; 
						break;
				}
			}
			// Always save the new position of the floating AppBar
			if (proposedState == ABE_FLOAT)
			{
				position.right = position.left + this.appBarState.floatRect.Width;
				position.bottom = position.top + this.appBarState.floatRect.Height;
				this.appBarState.floatRect = position; 
			}
			// After setting the dimensions, set the AppBar to the proposed state
			SetState(proposedState);
			if (this.moving)
				this.Visible = true;
			message.Result = new IntPtr(0);
		}
		private void OnMoving(ref Message message) 
		{
			// We control the moving of the AppBar. For example, if the mouse moves 
			// close to an edge, we want to dock the AppBar.
			// The lParam contains the window's position proposed by the system
			RECT rect = new RECT();
			RtlMoveMemory(ref rect, message.LParam, Marshal.SizeOf(rect));
			// Get the location of the mouse cursor
			POINT point = new POINT(GetMessagePos());
			// Where should the AppBar be based on the mouse position?
			int stateProposed = CalcProposedState(point);
			if ((this.appBarState.proposedState != ABE_FLOAT) && (stateProposed == ABE_FLOAT)) 
			{
				// While moving, the user took us from a docked/autohidden state to 
				// the float state. We have to calculate a rectangle location so that
				// the mouse cursor stays inside the window.
				rect = this.appBarState.floatRect;
				rect = new RECT(point.X - rect.Width / 2, point.Y, 
					(point.X - rect.Width / 2) + rect.Width, point.Y + rect.Height);
			}
			// Remember the most-recently proposed state
			this.appBarState.proposedState = stateProposed;
			// Tell the system where to move the window based on the proposed state
			GetRect(stateProposed, ref rect);
			// Tell our derived class that there is a proposed state change
			AppBarStateChange(true, stateProposed);
			RtlMoveMemory(message.LParam, ref rect, Marshal.SizeOf(rect));
			message.Result = new IntPtr(0);
		}
		private void OnSizing(ref Message message) 
		{
			// We control the sizing of the AppBar. For example, if the user re-sizes 
			// an edge, we want to change the size in descrete increments.
			// The lParam contains the window's position proposed by the system
			RECT rect = new RECT();
			RtlMoveMemory(ref rect, message.LParam, Marshal.SizeOf(rect));
			// Get the minimum size of the window assuming it has no client area.
			// This is the width/height of the window that must always be present
			RECT rectBorder = new RECT(0, 0, 0, 0);
			AdjustWindowRectEx(ref rectBorder, GetStyle(), 0, GetExStyle());
			// We force the window to resize in discrete units set by the this.appBarState.sizeInc 
			// member. From the new, proposed window dimensions passed to us, round 
			// the width/height to the nearest discrete unit.
			int newWidth;
			int newHeight;
			if (this.appBarState.sizeInc.cx != 0)
				newWidth = ((rect.Width - rectBorder.Width) + this.appBarState.sizeInc.cx / 2) / 
					this.appBarState.sizeInc.cx * this.appBarState.sizeInc.cx + rectBorder.Width;
			else
				newWidth = rect.right - rect.left;
            
			if (this.appBarState.sizeInc.cy != 0)
				newHeight = ((rect.Height - rectBorder.Height) + this.appBarState.sizeInc.cy / 2) / 
					this.appBarState.sizeInc.cy * this.appBarState.sizeInc.cy + rectBorder.Height;
			else
				newHeight = rect.bottom - rect.top;
			// Adjust the rectangle's dimensions
			switch (message.WParam.ToInt32()) 
			{
				case WMSZ_LEFT: 
					rect.left = rect.right - newWidth; 
					break;
				case WMSZ_TOP: 
					rect.top = rect.bottom - newHeight; 
					break;
				case WMSZ_RIGHT: 
					rect.right = rect.left + newWidth; 
					break;
				case WMSZ_BOTTOM: 
					rect.bottom = rect.top + newHeight; 
					break;
				case WMSZ_BOTTOMLEFT:
					rect.bottom = rect.top + newHeight; 
					rect.left = rect.right - newWidth; 
					break;
				case WMSZ_BOTTOMRIGHT:
					rect.bottom = rect.top + newHeight; 
					rect.right = rect.left + newWidth; 
					break;
				case WMSZ_TOPLEFT:
					rect.left = rect.right - newWidth;
					rect.top = rect.bottom - newHeight;
					break;
				case WMSZ_TOPRIGHT:
					rect.top = rect.bottom - newHeight;
					rect.right = rect.left + newWidth; 
					break;
			}
			RtlMoveMemory(message.LParam, ref rect, Marshal.SizeOf(rect));
			message.Result = new IntPtr(0);
		}
		#endregion
		#region Event Handlers
		private void AppBar_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			// Trap the mousedown to allow moving the form by clicking on the client area.
			OnMouseDown();
		}
        
		private void AppBarForm_LocationChanged(object sender, System.EventArgs e)
		{
			// Trap when the forms location is set from the inheriting forms properties.
			// Basically, this event fires once for the AppBar class, but initializing will be true
			// It fires again when the inheriting form sets it's location. At this time, we record
			// the location and size of the form, and then disable this event from firing again
			if (!this.initializing)
			{
				this.appBarState.floatRect.left = this.Left;
				this.appBarState.floatRect.top = this.Top;
				this.appBarState.floatRect.right = this.Right;
				this.appBarState.floatRect.bottom = this.Bottom;
				this.LocationChanged -= new System.EventHandler(this.AppBarForm_LocationChanged);
			}
		}
		private void AppBarForm_Load(object sender, System.EventArgs e)
		{
			if (!this.DesignMode)
				SetState(this.appBarState.state);
		}
		#endregion
		#region Custom Editor
		/// 
		/// This code is courtesy of Jose Castanedo of Janus Systems
		/// www.janusys.com
		/// Provides a custom editor for the Docking Flags which displays as a drop down list with check
		/// boxes allowing the user to select one or more options
		/// 
		[Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced)]
			public class DockFlagConverter : TypeConverter
		{
			/// 
			/// Constructor takes no arguments
			/// 
			public DockFlagConverter()
			{
			}
			public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context,Type type)
			{
				if (type == typeof(string))
				{
					return true;
				}
				else
				{
					return base.CanConvertTo(type);
				}
			}
			public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context,System.Globalization.CultureInfo culture,object value,Type destinationType)
			{
				if (value == null)
				{
					return string.Empty;
				}
				else
				{
					Type type = value.GetType();
					string strValue = string.Empty;
					Array values = Enum.GetValues(type);
					if (type == typeof(DockFlags))
					{
						for(int i = 0; i
 0) strValue += ", ";
										strValue += values.GetValue(i).ToString();
									}
								}
							}
						}
					}
					return strValue;
				}
			}
		}
		[Browsable(false),     EditorBrowsable(EditorBrowsableState.Advanced)]
			public class DockFlagEditor : System.Drawing.Design.UITypeEditor
		{
			private IWindowsFormsEditorService edSvc = null;
			public DockFlagEditor()
			{
			}
			protected virtual void SetEditorProps(object value,System.Windows.Forms.CheckedListBox editor) 
			{
				Type type = value.GetType();
				Array values = Enum.GetValues(type);
				for (int i = 0; i < values.Length; i++)
				{
					editor.Items.Add(values.GetValue(i));
					if ((int) values.GetValue(i) != 0)
					{
						if (((int) value & (int) values.GetValue(i)) == (int) values.GetValue(i))
						{
							editor.SetItemChecked(i, true);
						}
					}
					else
					{
						if ((int) value == 0)
						{
							editor.SetItemChecked(i, true);
						}
					}
				}
				editor.BorderStyle = System.Windows.Forms.BorderStyle.None;
			}
			public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 
			{
				if (context != null    && context.Instance != null    && provider != null) 
				{
					edSvc = (IWindowsFormsEditorService) provider.GetService(typeof(IWindowsFormsEditorService));
					if (edSvc != null) 
					{
						System.Windows.Forms.CheckedListBox listBox = new System.Windows.Forms.CheckedListBox();
						listBox.CheckOnClick = true;
						this.SetEditorProps(value, listBox);
						edSvc.DropDownControl(listBox);
						if (value.GetType() == typeof(DockFlags))
						{
							DockFlags proposedValue = DockFlags.AllowFloat;
							for(int i=0; i