locked
IsWindowVisible() fails to detect if Store app is visible RRS feed

  • Question

  • I'm using EnumWindows to get all windows from my desktop. 

    I did successfully filter out most non-visible windows by checking the windows state and visibility, etc.

    var shellWindow = GetShellWindow(); var windows = new List<DetectedWindow>(); //EnumWindows(delegate (IntPtr handle, int lParam) EnumDesktopWindows(IntPtr.Zero, delegate (IntPtr handle, int lParam) { if (handle == shellWindow) return true; if (!IsWindowVisible(handle)) return true; if (IsIconic(handle)) return true; var length = GetWindowTextLength(handle); if (length == 0) return true; var builder = new StringBuilder(length); GetWindowText(handle, builder, length + 1); GetWindowRect(handle, out Rect rect); var info = new WindowInfo(false); GetWindowInfo(handle, ref info); //If disabled, ignore. if (((long)info.dwStyle & (uint)WindowStyles.Disabled) == (uint)WindowStyles.Disabled) return true; var infoTile = new TitlebarInfo(false); GetTitleBarInfo(handle, ref infoTile); if ((infoTile.rgstate[0] & StateSystemInvisible) == StateSystemInvisible) return true; if ((infoTile.rgstate[0] & StateSystemUnavailable) == StateSystemUnavailable) return true; if ((infoTile.rgstate[0] & StateSystemOffscreen) == StateSystemOffscreen) return true;

                    var className = new StringBuilder(256);
                    GetClassName(handle, className, className.Capacity);

                    if (className.ToString() == "Windows.UI.Core.CoreWindow")
                        return true;

    windows.Add(new DetectedWindow(handle, rect.ToRect(), builder.ToString())); return true; }, IntPtr.Zero);


    This code works perfectly for desktop apps, but not for the Store apps. I'm constantly getting apps that are not visible, like Mail and Groove Music. What can I do to filter out (remove from my list)?




    Sunday, May 14, 2017 2:40 AM

Answers

  • With GetClassName()

    To check if a UWP window is visible, you can use DwmGetWindowAttribute() with DWMWA_CLOAKED flag.

    (when it is hidden, it returns for example DWM_CLOAKED_SHELL, from DWMWINDOWATTRIBUTE enumeration ; I tested on Windows 10,  I get 0 for visible apps like Microsoft Edge)

    Declarations :

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    	private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    	
    [DllImport("dwmapi.dll")]
    	private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out IntPtr pvAttribute, int cbAttribute);
    	
    enum DWMWINDOWATTRIBUTE
    {
        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             
    }

    • Marked as answer by NickeManarin Sunday, May 14, 2017 5:32 PM
    Sunday, May 14, 2017 3:25 PM

All replies

  • They can be skipped from the class name

    (!= "ApplicationFrameWindow" &&  != "Windows.UI.Core.CoreWindow")

    • Marked as answer by NickeManarin Sunday, May 14, 2017 3:15 PM
    • Unmarked as answer by NickeManarin Sunday, May 14, 2017 5:32 PM
    Sunday, May 14, 2017 6:17 AM
  • How exactly can I get the class name? Wouldn't that filter out UWP apps that are visible? (Since the IsWindowVisible() api does not filter out those windows)
    Sunday, May 14, 2017 1:36 PM
  • With GetClassName()

    To check if a UWP window is visible, you can use DwmGetWindowAttribute() with DWMWA_CLOAKED flag.

    (when it is hidden, it returns for example DWM_CLOAKED_SHELL, from DWMWINDOWATTRIBUTE enumeration ; I tested on Windows 10,  I get 0 for visible apps like Microsoft Edge)

    Declarations :

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    	private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
    	
    [DllImport("dwmapi.dll")]
    	private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out IntPtr pvAttribute, int cbAttribute);
    	
    enum DWMWINDOWATTRIBUTE
    {
        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             
    }

    • Marked as answer by NickeManarin Sunday, May 14, 2017 5:32 PM
    Sunday, May 14, 2017 3:25 PM
  • Thank you. It's working as expected. For some reason, just checking the class name stopped filtering the cloaked windows, but with this code, I'm getting the right amount.
    Sunday, May 14, 2017 5:32 PM