358 lines
14 KiB
C#
358 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
|
|
namespace Win32Natives
|
|
{
|
|
/// <summary>
|
|
/// user32.dll 包装类
|
|
/// </summary>
|
|
public static class User32
|
|
{
|
|
public const int GWL_STYLE = -16;
|
|
public const int WS_OVERLAPPED = 0x00000000;
|
|
public const int WS_POPUP = unchecked((int)0x80000000);
|
|
public const int WS_CHILD = 0x40000000;
|
|
public const int WS_MINIMIZE = 0x20000000;
|
|
public const int WS_VISIBLE = 0x10000000;
|
|
public const int WS_DISABLED = 0x08000000;
|
|
public const int WS_CLIPSIBLINGS = 0x04000000;
|
|
public const int WS_CLIPCHILDREN = 0x02000000;
|
|
public const int WS_MAXIMIZE = 0x01000000;
|
|
public const int WS_BORDER = 0x00800000;
|
|
public const int WS_DLGFRAME = 0x00400000;
|
|
public const int WS_VSCROLL = 0x00200000;
|
|
public const int WS_HSCROLL = 0x00100000;
|
|
public const int WS_SYSMENU = 0x00080000;
|
|
public const int WS_THICKFRAME = 0x00040000;
|
|
public const int WS_GROUP = 0x00020000;
|
|
public const int WS_TABSTOP = 0x00010000;
|
|
public const int WS_MINIMIZEBOX = 0x00020000;
|
|
public const int WS_MAXIMIZEBOX = 0x00010000;
|
|
public const int WS_CHILDWINDOW = WS_CHILD;
|
|
public const int WS_CAPTION = WS_BORDER | WS_DLGFRAME;
|
|
public const int WS_TILED = WS_OVERLAPPED;
|
|
public const int WS_ICONIC = WS_MINIMIZE;
|
|
public const int WS_SIZEBOX = WS_THICKFRAME;
|
|
public const int WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW;
|
|
public const int WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
|
|
public const int WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU;
|
|
|
|
public const int GWL_EXSTYLE = -20;
|
|
public const int WS_EX_DLGMODALFRAME = 0x00000001;
|
|
public const int WS_EX_NOPARENTNOTIFY = 0x00000004;
|
|
public const int WS_EX_TOPMOST = 0x00000008;
|
|
public const int WS_EX_ACCEPTFILES = 0x00000010;
|
|
public const int WS_EX_TRANSPARENT = 0x00000020;
|
|
public const int WS_EX_MDICHILD = 0x00000040;
|
|
public const int WS_EX_TOOLWINDOW = 0x00000080;
|
|
public const int WS_EX_WINDOWEDGE = 0x00000100;
|
|
public const int WS_EX_CLIENTEDGE = 0x00000200;
|
|
public const int WS_EX_CONTEXTHELP = 0x00000400;
|
|
public const int WS_EX_RIGHT = 0x00001000;
|
|
public const int WS_EX_LEFT = 0x00000000;
|
|
public const int WS_EX_RTLREADING = 0x00002000;
|
|
public const int WS_EX_LTRREADING = 0x00000000;
|
|
public const int WS_EX_LEFTSCROLLBAR = 0x00004000;
|
|
public const int WS_EX_RIGHTSCROLLBAR = 0x00000000;
|
|
public const int WS_EX_CONTROLPARENT = 0x00010000;
|
|
public const int WS_EX_STATICEDGE = 0x00020000;
|
|
public const int WS_EX_APPWINDOW = 0x00040000;
|
|
public const int WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE;
|
|
public const int WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
|
|
public const int WS_EX_LAYERED = 0x00080000;
|
|
public const int WS_EX_NOINHERITLAYOUT = 0x00100000;
|
|
public const int WS_EX_LAYOUTRTL = 0x00400000;
|
|
public const int WS_EX_COMPOSITED = 0x02000000;
|
|
public const int WS_EX_NOACTIVATE = 0x08000000;
|
|
|
|
public const uint LWA_COLORKEY = 0x1;
|
|
public const uint LWA_ALPHA = 0x2;
|
|
|
|
public const byte AC_SRC_OVER = 0x00;
|
|
public const byte AC_SRC_ALPHA = 0x01;
|
|
|
|
public const int ULW_COLORKEY = 0x00000001;
|
|
public const int ULW_ALPHA = 0x00000002;
|
|
public const int ULW_OPAQUE = 0x00000004;
|
|
|
|
public const IntPtr HWND_TOPMOST = -1;
|
|
|
|
public const uint SWP_ASYNCWINDOWPOS = 0x4000;
|
|
public const uint SWP_DEFERERASE = 0x2000;
|
|
public const uint SWP_NOSENDCHANGING = 0x0400;
|
|
public const uint SWP_NOOWNERZORDER = 0x0200;
|
|
public const uint SWP_NOREPOSITION = 0x0200;
|
|
public const uint SWP_NOCOPYBITS = 0x0100;
|
|
public const uint SWP_HIDEWINDOW = 0x0080;
|
|
public const uint SWP_SHOWWINDOW = 0x0040;
|
|
public const uint SWP_DRAWFRAME = 0x0020;
|
|
public const uint SWP_FRAMECHANGED = 0x0020;
|
|
public const uint SWP_NOACTIVATE = 0x0010;
|
|
public const uint SWP_NOREDRAW = 0x0008;
|
|
public const uint SWP_NOZORDER = 0x0004;
|
|
public const uint SWP_NOMOVE = 0x0002;
|
|
public const uint SWP_NOSIZE = 0x0001;
|
|
|
|
public const int WM_SPAWN_WORKER = 0x052C; // 一个未公开的神秘消息
|
|
|
|
public const uint SMTO_NORMAL = 0x0000;
|
|
public const uint SMTO_BLOCK = 0x0001;
|
|
public const uint SMTO_ABORTIFHUNG = 0x0002;
|
|
public const uint SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;
|
|
|
|
public const uint GA_PARENT = 1;
|
|
|
|
public const uint GW_OWNER = 4;
|
|
|
|
public const int SW_HIDE = 0;
|
|
public const int SW_SHOWNORMAL = 1;
|
|
public const int SW_SHOWMINIMIZED = 2;
|
|
public const int SW_SHOWMAXIMIZED = 3;
|
|
public const int SW_SHOWNOACTIVATE = 4;
|
|
public const int SW_SHOW = 5;
|
|
public const int SW_MINIMIZE = 6;
|
|
public const int SW_SHOWMINNOACTIVE = 7;
|
|
public const int SW_SHOWNA = 8;
|
|
public const int SW_RESTORE = 9;
|
|
public const int SW_SHOWDEFAULT = 10;
|
|
|
|
public const uint MONITOR_DEFAULTTONULL = 0;
|
|
public const uint MONITOR_DEFAULTTOPRIMARY = 1;
|
|
public const uint MONITOR_DEFAULTTONEAREST = 2;
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct POINT
|
|
{
|
|
public int x;
|
|
public int y;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct SIZE
|
|
{
|
|
public int cx;
|
|
public int cy;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct BLENDFUNCTION
|
|
{
|
|
public byte BlendOp;
|
|
public byte BlendFlags;
|
|
public byte SourceConstantAlpha;
|
|
public byte AlphaFormat;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
private struct LASTINPUTINFO
|
|
{
|
|
public uint cbSize;
|
|
public uint dwTime;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct RECT
|
|
{
|
|
public int Left;
|
|
public int Top;
|
|
public int Right;
|
|
public int Bottom;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
private struct MONITORINFOEX
|
|
{
|
|
public uint cbSize;
|
|
public RECT rcMonitor;
|
|
public RECT rcWork;
|
|
public uint dwFlags;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
|
public string szDevice;
|
|
}
|
|
|
|
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr GetDC(IntPtr hWnd);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern bool GetLayeredWindowAttributes(IntPtr hWnd, ref uint crKey, ref byte bAlpha, ref uint dwFlags);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern bool SetLayeredWindowAttributes(IntPtr hWnd, uint pcrKey, byte pbAlpha, uint pdwFlags);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern bool UpdateLayeredWindow(IntPtr hWnd, IntPtr hdcDst, IntPtr pptDst, ref SIZE psize, IntPtr hdcSrc, ref POINT pptSrc, int crKey, ref BLENDFUNCTION pblend, int dwFlags);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern uint GetDoubleClickTime();
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, uint fuFlags, uint uTimeout, out IntPtr lpdwResult);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr GetParent(IntPtr hWnd);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr GetAncestor(IntPtr hWnd, uint gaFlags);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
|
|
|
|
[DllImport("User32.dll")]
|
|
public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool IsIconic(IntPtr hWnd);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern bool SetForegroundWindow(IntPtr hWnd);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
|
|
|
[DllImport("user32.dll")]
|
|
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
|
|
|
public static TimeSpan GetLastInputElapsedTime()
|
|
{
|
|
LASTINPUTINFO lastInputInfo = new();
|
|
lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
|
|
|
|
uint idleTimeMillis = 1000;
|
|
if (GetLastInputInfo(ref lastInputInfo))
|
|
{
|
|
uint tickCount = (uint)Environment.TickCount;
|
|
uint lastInputTick = lastInputInfo.dwTime;
|
|
idleTimeMillis = tickCount - lastInputTick;
|
|
}
|
|
return TimeSpan.FromMilliseconds(idleTimeMillis);
|
|
}
|
|
|
|
public static IntPtr GetWorkerW()
|
|
{
|
|
// NOTE: Codes borrowed from @rocksdanister/lively
|
|
|
|
var progman = FindWindow("Progman", null);
|
|
if (progman == IntPtr.Zero)
|
|
return IntPtr.Zero;
|
|
|
|
// Send 0x052C to Progman. This message directs Progman to spawn a
|
|
// WorkerW behind the desktop icons. If it is already there, nothing
|
|
// happens.
|
|
SendMessageTimeout(progman, WM_SPAWN_WORKER, 0, 0, SMTO_NORMAL, 1000, out _);
|
|
|
|
// Spy++ output
|
|
// .....
|
|
// 0x00010190 "" WorkerW
|
|
// ...
|
|
// 0x000100EE "" SHELLDLL_DefView
|
|
// 0x000100F0 "FolderView" SysListView32
|
|
// 0x00100B8A "" WorkerW <-- This is the WorkerW instance we are after!
|
|
// 0x000100EC "Program Manager" Progman
|
|
var workerw = IntPtr.Zero;
|
|
|
|
// We enumerate all Windows, until we find one, that has the SHELLDLL_DefView
|
|
// as a child.
|
|
// If we found that window, we take its next sibling and assign it to workerw.
|
|
EnumWindows(new EnumWindowsProc((tophandle, topparamhandle) =>
|
|
{
|
|
IntPtr p = FindWindowEx(tophandle, IntPtr.Zero, "SHELLDLL_DefView", null);
|
|
|
|
if (p != IntPtr.Zero)
|
|
{
|
|
// Gets the WorkerW Window after the current one.
|
|
workerw = FindWindowEx(IntPtr.Zero, tophandle, "WorkerW", null);
|
|
}
|
|
|
|
return true;
|
|
}), IntPtr.Zero);
|
|
|
|
// Some Windows 11 builds have a different Progman window layout.
|
|
// If the above code failed to find WorkerW, we should try this.
|
|
// Spy++ output
|
|
// 0x000100EC "Program Manager" Progman
|
|
// 0x000100EE "" SHELLDLL_DefView
|
|
// 0x000100F0 "FolderView" SysListView32
|
|
// 0x00100B8A "" WorkerW <-- This is the WorkerW instance we are after!
|
|
if (workerw == IntPtr.Zero)
|
|
{
|
|
workerw = FindWindowEx(progman, IntPtr.Zero, "WorkerW", null);
|
|
}
|
|
|
|
Debug.WriteLine($"HWND(WorkerW): {workerw:x8}");
|
|
return workerw;
|
|
}
|
|
|
|
public static bool GetScreenResolution(IntPtr hwnd, out uint width, out uint height)
|
|
{
|
|
IntPtr hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
|
|
var mi = new MONITORINFOEX { cbSize = (uint)Marshal.SizeOf<MONITORINFOEX>() };
|
|
if (GetMonitorInfo(hMon, ref mi))
|
|
{
|
|
int widthPx = mi.rcMonitor.Right - mi.rcMonitor.Left;
|
|
int heightPx = mi.rcMonitor.Bottom - mi.rcMonitor.Top;
|
|
width = (uint)widthPx;
|
|
height = (uint)heightPx;
|
|
return true;
|
|
}
|
|
width = height = 0;
|
|
return false;
|
|
}
|
|
|
|
public static bool GetPrimaryScreenResolution(out uint width, out uint height)
|
|
{
|
|
IntPtr hMon = MonitorFromWindow(IntPtr.Zero, MONITOR_DEFAULTTOPRIMARY);
|
|
|
|
var mi = new MONITORINFOEX { cbSize = (uint)Marshal.SizeOf<MONITORINFOEX>() };
|
|
if (GetMonitorInfo(hMon, ref mi))
|
|
{
|
|
int widthPx = mi.rcMonitor.Right - mi.rcMonitor.Left;
|
|
int heightPx = mi.rcMonitor.Bottom - mi.rcMonitor.Top;
|
|
width = (uint)widthPx;
|
|
height = (uint)heightPx;
|
|
return true;
|
|
}
|
|
width = height = 0;
|
|
return false;
|
|
}
|
|
}
|
|
}
|