獲取Windows正在運行的窗口進程
主要是獲取Alt+Tab中展示的窗口
原理主要是獲取窗口的樣式來判斷是否會在Alt+Tab中顯示
具體程式碼如下
/// <summary>
/// Alt+Tab 應用
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
public static bool IsAltTabWindow(IntPtr hWnd)
{
// The window must be visible
if (!IsWindowVisible(hWnd))
return false;
// The window must be a root owner
if (GetAncestor(hWnd, GA_ROOTOWNER) != hWnd)
return false;
// The window must not be cloaked by the shell
DwmGetWindowAttribute(hWnd, DwmWindowAttribute.DWMWA_CLOAKED, out int cloaked, sizeof(uint));
if (cloaked == DWM_CLOAKED_SHELL)
return false;
// The window must not have the extended style WS_EX_TOOLWINDOW
int style = Utils.Win32Api.GetWindowLong(hWnd, GWL_EXSTYLE);
if ((style & WS_EX_TOOLWINDOW) != 0)
return false;
return true;
}
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetAncestor(IntPtr hWnd, uint gaFlags);
[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(IntPtr hwnd, DwmWindowAttribute dwAttribute, out int attrValue, int cbAttribute);
const uint DWM_CLOAKED_SHELL = 0x00000002;
const uint GA_ROOTOWNER = 3;
const uint WS_EX_TOPMOST = 0x00000008;
[Flags]
public enum DwmWindowAttribute : uint
{
DWMWA_NCRENDERING_ENABLED = 1,
DWMWA_NCRENDERING_POLICY,
DWMWA_TRANSITIONS_FORCEDISABLED,
DWMWA_ALLOW_NCPAINT,
DWMWA_CAPTION_BUTTON_BOUNDS,
DWMWA_NONCLIENT_RTL_LAYOUT,
DWMWA_FORCE_ICONIC_REPRESENTATION,
DWMWA_FLIP3D_POLICY,
DWMWA_EXTENDED_FRAME_BOUNDS,
DWMWA_HAS_ICONIC_BITMAP,
DWMWA_DISALLOW_PEEK,
DWMWA_EXCLUDED_FROM_PEEK,
DWMWA_CLOAK,
DWMWA_CLOAKED,
DWMWA_FREEZE_REPRESENTATION,
DWMWA_LAST
}
/// <summary>
/// 獲取窗體句柄
/// </summary>
/// <param name="hwnd"></param>
/// <param name="nIndex"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
public static extern int GetWindowLong(IntPtr hwnd, int nIndex);
const int GWL_EXSTYLE = -20;//得到擴展的窗口風格
public const int WS_EX_TOOLWINDOW = 0x00000080;
以上方式對於全螢幕的UWP窗口時無法獲取得到的,因此需要引入以下方式獲取全螢幕UWP窗口
/// <summary> /// 全螢幕的UWP應用 /// </summary> /// <param name="hWnd"></param> /// <returns></returns> public static bool IsFullScreenUwpWindows(IntPtr hWnd) { // Get the extended style of the window var style = GetWindowLong(hWnd, GWL_EXSTYLE); // The window must have the extended style WS_EX_TOPMOST if ((style & WS_EX_TOPMOST) == 0) return false; // The window must not have the extended style WS_EX_NOACTIVATE if ((style & WS_EX_NOACTIVATE) != 0) return false; // The window must not have the extended style WS_EX_TOOLWINDOW if ((style & WS_EX_TOOLWINDOW) != 0) return false; return true; } public const int WS_EX_NOACTIVATE = 0x08000000;
然後通過枚舉窗口的方式就可以獲取到所有窗口了
/// <summary> /// 枚舉窗體的回調 /// </summary> /// <param name="hwnd"></param> /// <param name="lParam"></param> /// <returns></returns> public delegate bool EnumWindowsCallBack(IntPtr hwnd, IntPtr lParam); /// <summary> /// 枚舉出窗體 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> [DllImport("user32")] public static extern int EnumWindows(EnumWindowsCallBack x, IntPtr y); /// <summary> /// 枚舉子窗口 /// </summary> /// <param name="hWndParent"></param> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> [DllImport("user32")] public static extern int EnumChildWindows(IntPtr hWndParent, EnumWindowsCallBack x, IntPtr y); List<KeyValuePair<IntPtr, string>> handles = new List<KeyValuePair<IntPtr, string>>(); EnumWindows((hWnd, lPam) => { if (!IsAltTabWindow(hWnd)) return true;//繼續枚舉 var title = GetWindowTitle(hWnd); handles.Add(new KeyValuePair<IntPtr, string>(hWnd, title)); return true;//繼續枚舉 }, IntPtr.Zero); EnumChildWindows(GetDesktopWindow(), (hWnd, lPam) => { if (handles.Any(kv => kv.Key == hWnd)||!IsFullScreenUwpWindows(hWnd)) return true;//繼續枚舉 var title = GetWindowTitle(hWnd); handles.Add(new KeyValuePair<IntPtr, string>(hWnd, title)); return true;//繼續枚舉 }, IntPtr.Zero); [DllImport("user32.dll")] public static extern IntPtr GetDesktopWindow(); /// <summary> /// 獲取窗體的名稱 /// </summary> /// <param name="hWnd"></param> /// <param name="lpString"></param> /// <param name="nMaxCount"></param> /// <returns></returns> [DllImport("user32.dll")] public static extern int GetWindowTextW(IntPtr hWnd, IntPtr lpString, int nMaxCount); /// <summary> /// 默認獲取字元串的長度 /// </summary> private const int NumChars = 256; public static string GetWindowTitle(IntPtr hwnd) { IntPtr intPtr = Marshal.AllocHGlobal(NumChars); Utils.Win32Api.GetWindowTextW(hwnd, intPtr, 100); var s = Marshal.PtrToStringUni(intPtr); Marshal.FreeHGlobal(intPtr); return s; }
以上程式碼需要做調整才能運行起來,有空我補上完整程式碼
參考://stackoverflow.com/questions/72069771/show-a-list-of-all-alttab-windows-even-full-screen-uwp-windows-and-retrieve
