获取Windows正在运行的窗口进程
阅读原文时间:2023年07月09日阅读:1

主要是获取Alt+Tab中展示的窗口

原理主要是获取窗口的样式来判断是否会在Alt+Tab中显示

具体代码如下

///

/// Alt+Tab 应用 ///
///
///
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
}
///

/// 获取窗体句柄 ///
///
///
///
[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窗口

///

/// 全屏的UWP应用 ///
///
///
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;

然后通过枚举窗口的方式就可以获取到所有窗口了

///

/// 枚举窗体的回调 ///
///
///
///
public delegate bool EnumWindowsCallBack(IntPtr hwnd, IntPtr lParam);
/// /// 枚举出窗体 ///
///
///
///
[DllImport("user32")]
public static extern int EnumWindows(EnumWindowsCallBack x, IntPtr y);

///

/// 枚举子窗口 ///
///
///
///
///
[DllImport("user32")]
public static extern int EnumChildWindows(IntPtr hWndParent, EnumWindowsCallBack x, IntPtr y);
List> handles = new List>();
EnumWindows((hWnd, lPam) =>
{
if (!IsAltTabWindow(hWnd)) return true;//继续枚举
var title = GetWindowTitle(hWnd);
handles.Add(new KeyValuePair(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();
///

/// 获取窗体的名称 ///
///
///
///
///
[DllImport("user32.dll")]
public static extern int GetWindowTextW(IntPtr hWnd, IntPtr lpString, int nMaxCount);

///

/// 默认获取字符串的长度 ///
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;
}

以上代码需要做调整才能运行起来,有空我补上完整代码

参考:https://stackoverflow.com/questions/72069771/show-a-list-of-all-alttab-windows-even-full-screen-uwp-windows-and-retrieve