212 lines
6.9 KiB
C#
212 lines
6.9 KiB
C#
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace MpvNet.Windows.Native;
|
|
|
|
public static class WinApi
|
|
{
|
|
public static Version WindowsTen1607 { get; } = new Version(10, 0, 14393); // Windows 10 1607
|
|
|
|
[DllImport("kernel32.dll")]
|
|
public static extern bool AttachConsole(int dwProcessId);
|
|
|
|
[DllImport("kernel32.dll")]
|
|
public static extern bool FreeConsole();
|
|
|
|
[DllImport("kernel32.dll")]
|
|
public static extern IntPtr LoadLibrary(string path);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern uint ActivateKeyboardLayout(IntPtr hkl, uint flags);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
public static extern IntPtr FindWindowEx(
|
|
IntPtr parentHandle, IntPtr childAfter, string lclassName, string? windowTitle);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, ref CopyDataStruct lParam);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
public static extern IntPtr PostMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
|
|
public static extern int RegisterWindowMessage(string id);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool AllowSetForegroundWindow(int dwProcessId);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern void ReleaseCapture();
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern int GetDpiForWindow(IntPtr hwnd);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool AdjustWindowRect(ref Rect lpRect, uint dwStyle, bool bMenu);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool AdjustWindowRectExForDpi(
|
|
ref Rect lpRect, uint dwStyle, bool bMenu, uint dwExStyle, uint dpi);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool SetWindowPos(
|
|
IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
|
|
|
|
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
|
|
static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
|
|
|
|
public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
|
|
{
|
|
if (IntPtr.Size == 8)
|
|
return GetWindowLongPtr(hWnd, nIndex);
|
|
else
|
|
return GetWindowLong32(hWnd, nIndex);
|
|
}
|
|
|
|
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
|
|
public static extern IntPtr SetWindowLong32(IntPtr hWnd, int nIndex, uint dwNewLong);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, uint dwNewLong);
|
|
|
|
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong)
|
|
{
|
|
if (IntPtr.Size == 8)
|
|
return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
|
|
else
|
|
return SetWindowLong32(hWnd, nIndex, dwNewLong);
|
|
}
|
|
|
|
[DllImport("gdi32.dll")]
|
|
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
|
|
|
[DllImport("dwmapi.dll")]
|
|
public static extern int DwmGetWindowAttribute(
|
|
IntPtr hwnd, uint dwAttribute, out Rect pvAttribute, uint cbAttribute);
|
|
|
|
public static bool GetDwmWindowRect(IntPtr handle, out Rect rect)
|
|
{
|
|
const uint DWMWA_EXTENDED_FRAME_BOUNDS = 9;
|
|
|
|
return 0 == DwmGetWindowAttribute(handle, DWMWA_EXTENDED_FRAME_BOUNDS,
|
|
out rect, (uint)Marshal.SizeOf<Rect>());
|
|
}
|
|
|
|
public static Rectangle GetWorkingArea(IntPtr handle, Rectangle workingArea)
|
|
{
|
|
if (handle != IntPtr.Zero && GetDwmWindowRect(handle, out Rect dwmRect) &&
|
|
GetWindowRect(handle, out Rect rect))
|
|
{
|
|
int left = workingArea.Left;
|
|
int top = workingArea.Top;
|
|
int right = workingArea.Right;
|
|
int bottom = workingArea.Bottom;
|
|
|
|
left += rect.Left - dwmRect.Left;
|
|
top -= rect.Top - dwmRect.Top;
|
|
right -= dwmRect.Right - rect.Right;
|
|
bottom -= dwmRect.Bottom - rect.Bottom;
|
|
|
|
return new Rectangle(left, top, right - left, bottom - top);
|
|
}
|
|
|
|
return workingArea;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct Rect
|
|
{
|
|
public int Left;
|
|
public int Top;
|
|
public int Right;
|
|
public int Bottom;
|
|
|
|
public Rect(Rectangle r)
|
|
{
|
|
Left = r.Left;
|
|
Top = r.Top;
|
|
Right = r.Right;
|
|
Bottom = r.Bottom;
|
|
}
|
|
|
|
public Rect(int left, int top, int right, int bottom)
|
|
{
|
|
Left = left;
|
|
Top = top;
|
|
Right = right;
|
|
Bottom = bottom;
|
|
}
|
|
|
|
public Rectangle ToRectangle() => Rectangle.FromLTRB(Left, Top, Right, Bottom);
|
|
public Size Size => new Size(Right - Left, Bottom - Top);
|
|
public int Width => Right - Left;
|
|
public int Height => Bottom - Top;
|
|
|
|
public static Rect FromRectangle(Rectangle rect)
|
|
{
|
|
return new Rect(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return "{Left=" + Left + ",Top=" + Top + ",Right=" + Right + ",Bottom=" + Bottom + "}";
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct CopyDataStruct
|
|
{
|
|
public IntPtr dwData;
|
|
public int cbData;
|
|
[MarshalAs(UnmanagedType.LPTStr)]
|
|
public string lpData;
|
|
}
|
|
|
|
public static int GetResizeBorder(int v)
|
|
{
|
|
switch (v)
|
|
{
|
|
case 1 /* WMSZ_LEFT */ : return 3;
|
|
case 3 /* WMSZ_TOP */ : return 2;
|
|
case 2 /* WMSZ_RIGHT */ : return 3;
|
|
case 6 /* WMSZ_BOTTOM */ : return 2;
|
|
case 4 /* WMSZ_TOPLEFT */ : return 1;
|
|
case 5 /* WMSZ_TOPRIGHT */ : return 1;
|
|
case 7 /* WMSZ_BOTTOMLEFT */ : return 3;
|
|
case 8 /* WMSZ_BOTTOMRIGHT */ : return 3;
|
|
default: return -1;
|
|
}
|
|
}
|
|
|
|
public static void SubtractWindowBorders(IntPtr hwnd, ref Rect rc, int dpi)
|
|
{
|
|
Rect r = new Rect(0, 0, 0, 0);
|
|
AddWindowBorders(hwnd, ref r, dpi);
|
|
rc.Left -= r.Left;
|
|
rc.Top -= r.Top;
|
|
rc.Right -= r.Right;
|
|
rc.Bottom -= r.Bottom;
|
|
}
|
|
|
|
public static void AddWindowBorders(IntPtr hwnd, ref Rect rc, int dpi)
|
|
{
|
|
uint windowStyle = (uint)GetWindowLong(hwnd, -16); // GWL_STYLE
|
|
uint windowStyleEx = (uint)GetWindowLong(hwnd, -20); // GWL_EXSTYLE
|
|
|
|
if (Environment.OSVersion.Version >= WindowsTen1607)
|
|
AdjustWindowRectExForDpi(ref rc, windowStyle, false, windowStyleEx, (uint)dpi);
|
|
else
|
|
AdjustWindowRect(ref rc, windowStyle, false);
|
|
}
|
|
}
|