IPCamAppBar/AppBar.cs

192 lines
5.1 KiB
C#

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");
}
}
}
}