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
{
///
/// user32.dll 包装类
///
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): 0x{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() };
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() };
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;
}
}
}