using System; using System.Runtime.InteropServices; using System.Windows.Forms; // ReSharper disable InconsistentNaming namespace IPCamAppBar { [StructLayout(LayoutKind.Sequential)] internal struct RECT { public int left; public int top; public int right; public int bottom; } [StructLayout(LayoutKind.Sequential)] internal struct APPBARDATA { public int cbSize; public IntPtr hWnd; public int uCallbackMessage; public int uEdge; public RECT rc; public IntPtr lParam; } internal enum ABMsg { ABM_NEW = 0, ABM_REMOVE, ABM_QUERYPOS, ABM_SETPOS, ABM_GETSTATE, ABM_GETTASKBARPOS, ABM_ACTIVATE, ABM_GETAUTOHIDEBAR, ABM_SETAUTOHIDEBAR, ABM_WINDOWPOSCHANGED, ABM_SETSTATE } internal enum ABNotify { ABN_STATECHANGE = 0, ABN_POSCHANGED, ABN_FULLSCREENAPP, ABN_WINDOWARRANGE } internal enum ABEdge { ABE_LEFT = 0, ABE_TOP, ABE_RIGHT, ABE_BOTTOM } public enum AppBarPosition { Top, Left, Bottom, Right } public class AppBar : IDisposable { [DllImport("SHELL32", CallingConvention = CallingConvention.StdCall)] private static extern uint SHAppBarMessage(int dwMessage, ref APPBARDATA pData); [DllImport("User32.dll", ExactSpelling = true, CharSet = 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 class PositionParameters { public Screen Monitor { get; set; } public AppBarPosition Position { get; set; } public int Size { get; set; } } private bool disposed; private APPBARDATA appBarData; private PositionParameters lastPosition; public AppBar(IntPtr windowHandle) { appBarData.cbSize = Marshal.SizeOf(appBarData); appBarData.hWnd = windowHandle; appBarData.uCallbackMessage = RegisterWindowMessage("AppBarMessage"); SHAppBarMessage((int)ABMsg.ABM_NEW, ref appBarData); } public void Dispose() { if (disposed) throw new ObjectDisposedException(GetType().Name); SHAppBarMessage((int)ABMsg.ABM_REMOVE, ref appBarData); disposed = true; } public void SetPosition(Screen monitor, AppBarPosition position, int size) { appBarData.rc.top = monitor.Bounds.Top; appBarData.rc.left = monitor.Bounds.Left; appBarData.rc.bottom = monitor.Bounds.Bottom; appBarData.rc.right= monitor.Bounds.Right; ApplyPosition(position, size); SHAppBarMessage((int)ABMsg.ABM_QUERYPOS, ref appBarData); ApplyPosition(position, size); SHAppBarMessage((int)ABMsg.ABM_SETPOS, ref appBarData); MoveWindow( appBarData.hWnd, appBarData.rc.left, appBarData.rc.top, appBarData.rc.right - appBarData.rc.left, appBarData.rc.bottom - appBarData.rc.top, true); lastPosition = new PositionParameters { Monitor = monitor, Position = position, Size = size }; } public void HandleMessage(Message m) { if (m.Msg == appBarData.uCallbackMessage && m.WParam.ToInt32() == (int)ABNotify.ABN_POSCHANGED) UpdatePosition(); } private void UpdatePosition() { if (lastPosition == null) return; SetPosition(lastPosition.Monitor, lastPosition.Position, lastPosition.Size); } private void ApplyPosition(AppBarPosition position, int size) { switch (position) { case AppBarPosition.Top: appBarData.uEdge = (int)ABEdge.ABE_TOP; appBarData.rc.bottom = appBarData.rc.top + size; break; case AppBarPosition.Left: appBarData.uEdge = (int)ABEdge.ABE_LEFT; appBarData.rc.right = appBarData.rc.left + size; break; case AppBarPosition.Bottom: appBarData.uEdge = (int)ABEdge.ABE_BOTTOM; appBarData.rc.top = appBarData.rc.bottom - size; break; case AppBarPosition.Right: appBarData.uEdge = (int)ABEdge.ABE_RIGHT; appBarData.rc.left = appBarData.rc.right - size; break; default: throw new ArgumentOutOfRangeException(nameof(position), position, @"Invalid position value"); } } } }