151 lines
5.6 KiB
C#
151 lines
5.6 KiB
C#
using System.Runtime.InteropServices;
|
|
using CursorLang.Core.Interop;
|
|
|
|
namespace CursorLang.Agent.Interop;
|
|
|
|
/// <summary>
|
|
/// The Win32 pieces a window needs when there is no framework to make one:
|
|
/// the class, the window itself, the message loop.
|
|
/// </summary>
|
|
internal static class WindowNative
|
|
{
|
|
/// <summary>The window procedure. Windows keeps the only reference to it.</summary>
|
|
internal delegate IntPtr WindowProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam);
|
|
|
|
internal const int WS_POPUP = unchecked((int)0x80000000);
|
|
internal const int WS_DISABLED = 0x08000000;
|
|
|
|
internal const int WS_EX_LAYERED = 0x00080000;
|
|
internal const int WS_EX_TOOLWINDOW = 0x00000080;
|
|
internal const int WS_EX_NOACTIVATE = 0x08000000;
|
|
internal const int WS_EX_TRANSPARENT = 0x00000020;
|
|
internal const int WS_EX_TOPMOST = 0x00000008;
|
|
|
|
internal const int SW_HIDE = 0;
|
|
internal const int SW_SHOWNOACTIVATE = 4;
|
|
|
|
internal const uint WM_DESTROY = 0x0002;
|
|
internal const uint WM_PAINT = 0x000F;
|
|
internal const uint WM_CLOSE = 0x0010;
|
|
internal const uint WM_QUIT = 0x0012;
|
|
internal const uint WM_NULL = 0x0000;
|
|
internal const uint WM_DISPLAYCHANGE = 0x007E;
|
|
internal const uint WM_DPICHANGED = 0x02E0;
|
|
internal const uint WM_ENDSESSION = 0x0016;
|
|
|
|
/// <summary>WM_APP and up belong to the application; the tray takes WM_APP + 1.</summary>
|
|
internal const uint WM_APP = 0x8000;
|
|
|
|
private const uint LWA_ALPHA = 0x00000002;
|
|
|
|
/// <summary>
|
|
/// Registers a window class. A class already there is not an error: the name is
|
|
/// unique per window kind, and a second agent in the same process would meet its
|
|
/// own registration.
|
|
/// </summary>
|
|
internal static void RegisterClass(string className, WindowProc windowProc)
|
|
{
|
|
var description = new WindowClass
|
|
{
|
|
cbSize = Marshal.SizeOf<WindowClass>(),
|
|
lpfnWndProc = windowProc,
|
|
hInstance = GetModuleHandle(null),
|
|
lpszClassName = className,
|
|
};
|
|
|
|
if (RegisterClassEx(ref description) == 0 &&
|
|
Marshal.GetLastWin32Error() != ErrorClassAlreadyExists)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"RegisterClassExW failed for '{className}': {Marshal.GetLastWin32Error()}");
|
|
}
|
|
}
|
|
|
|
private const int ErrorClassAlreadyExists = 1410;
|
|
|
|
/// <summary>Creates a window of a registered class. It is not shown.</summary>
|
|
internal static IntPtr CreateWindow(string className, string title, int style, int exStyle)
|
|
{
|
|
IntPtr window = CreateWindowEx(
|
|
exStyle, className, title, style,
|
|
0, 0, 0, 0,
|
|
IntPtr.Zero, IntPtr.Zero, GetModuleHandle(null), IntPtr.Zero);
|
|
|
|
if (window == IntPtr.Zero)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"CreateWindowExW failed for '{className}': {Marshal.GetLastWin32Error()}");
|
|
}
|
|
|
|
return window;
|
|
}
|
|
|
|
/// <summary>The whole opacity of a layered window, 0 to 255.</summary>
|
|
internal static void SetAlpha(IntPtr window, byte alpha) =>
|
|
SetLayeredWindowAttributes(window, 0, alpha, LWA_ALPHA);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
private static extern ushort RegisterClassEx(ref WindowClass lpwcx);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CreateWindowExW")]
|
|
private static extern IntPtr CreateWindowEx(int dwExStyle, string lpClassName, string lpWindowName,
|
|
int dwStyle, int x, int y, int nWidth, int nHeight,
|
|
IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "DefWindowProcW")]
|
|
internal static extern IntPtr DefWindowProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern bool DestroyWindow(IntPtr hWnd);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern bool IsWindowVisible(IntPtr hWnd);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern bool InvalidateRect(IntPtr hWnd, IntPtr lpRect, bool bErase);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern bool UpdateWindow(IntPtr hWnd);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern bool SetWindowRgn(IntPtr hWnd, IntPtr hRgn, bool bRedraw);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern bool GetClientRect(IntPtr hWnd, out PopupWindowNative.Rect lpRect);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "PostMessageW")]
|
|
internal static extern bool PostMessage(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam);
|
|
|
|
[DllImport("user32.dll")]
|
|
internal static extern void PostQuitMessage(int nExitCode);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern bool SetLayeredWindowAttributes(IntPtr hWnd, uint crKey, byte bAlpha, uint dwFlags);
|
|
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
|
|
private static extern IntPtr GetModuleHandle(string? lpModuleName);
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
|
private struct WindowClass
|
|
{
|
|
public int cbSize;
|
|
public uint style;
|
|
|
|
[MarshalAs(UnmanagedType.FunctionPtr)]
|
|
public WindowProc lpfnWndProc;
|
|
|
|
public int cbClsExtra;
|
|
public int cbWndExtra;
|
|
public IntPtr hInstance;
|
|
public IntPtr hIcon;
|
|
public IntPtr hCursor;
|
|
public IntPtr hbrBackground;
|
|
public string? lpszMenuName;
|
|
public string lpszClassName;
|
|
public IntPtr hIconSm;
|
|
}
|
|
}
|