Files
Hyperbar/Hyperbar.Windows.Interop/WindowSnapping.cs
T
TheXamlGuy 2f22c81384 WIP
2024-01-17 17:16:50 +00:00

111 lines
3.3 KiB
C#

using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Foundation;
namespace Hyperbar.Windows.Interop;
public class WindowSnapping
{
private readonly nint hwnd;
private uint callback;
public WindowSnapping(IntPtr hwnd)
{
this.hwnd = hwnd;
InitializeAppBarWindow();
}
private enum AppBarMsg : int
{
ABM_NEW = 0,
ABM_REMOVE,
ABM_QUERYPOS,
ABM_SETPOS,
ABM_GETSTATE,
ABM_GETTASKBARPOS,
ABM_ACTIVATE,
ABM_GETAUTOHIDEBAR,
ABM_SETAUTOHIDEBAR,
ABM_WINDOWPOSCHANGED,
ABM_SETSTATE
}
public static WindowSnapping Create(IntPtr hwnd)
{
return new WindowSnapping(hwnd);
}
public void Snap(AppBarWindowPlacement placement, int size)
{
uint dpi = PInvoke.GetDpiForWindow(new HWND(hwnd));
double scalingFactor = dpi / 96d;
int actualSize = (int)(size * scalingFactor);
Screen screen = Screen.FromHandle(hwnd);
APPBARDATA32 appBarData = new();
appBarData.cbSize = (uint)Marshal.SizeOf(appBarData);
appBarData.hWnd = new HWND(hwnd);
appBarData.uEdge = (uint)placement;
appBarData.rc = new RECT
{
left = (int)screen.Bounds.Left,
top = (int)screen.Bounds.Top,
right = (int)screen.Bounds.Right,
bottom = (int)screen.Bounds.Bottom
};
PInvoke.SHAppBarMessage((int)AppBarMsg.ABM_QUERYPOS, ref appBarData);
switch (placement)
{
case AppBarWindowPlacement.Top:
appBarData.rc.bottom = appBarData.rc.top + actualSize;
break;
case AppBarWindowPlacement.Bottom:
appBarData.rc.top = appBarData.rc.bottom - actualSize;
break;
case AppBarWindowPlacement.Left:
appBarData.rc.right = appBarData.rc.left + actualSize;
break;
case AppBarWindowPlacement.Right:
appBarData.rc.left = appBarData.rc.right - actualSize;
break;
default: throw new NotSupportedException();
}
PInvoke.SHAppBarMessage((int)AppBarMsg.ABM_SETPOS, ref appBarData);
PInvoke.SetWindowPos(new HWND(hwnd), new HWND(),
appBarData.rc.left,
appBarData.rc.top,
appBarData.rc.right - appBarData.rc.left,
appBarData.rc.bottom - appBarData.rc.top, 0);
}
private void InitializeAppBarWindow()
{
if (Environment.Is64BitProcess)
{
APPBARDATA64 appBarData = new();
appBarData.cbSize = (uint)Marshal.SizeOf(appBarData);
appBarData.hWnd = new HWND(hwnd);
callback = PInvoke.RegisterWindowMessage("AppBarMessage64");
appBarData.uCallbackMessage = callback;
_ = PInvoke.SHAppBarMessage(0, ref appBarData);
}
else
{
APPBARDATA32 appBarData = new();
appBarData.cbSize = (uint)Marshal.SizeOf(appBarData);
appBarData.hWnd = new HWND(hwnd);
callback = PInvoke.RegisterWindowMessage("AppBarMessage32");
appBarData.uCallbackMessage = callback;
_ = PInvoke.SHAppBarMessage(0, ref appBarData);
}
}
}