111 lines
3.3 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|