March 2nd, 2020

How can I detect that my window has been suppressed from the screen by the shell?

Some programs enumerate all windows in order to understand what is on the screen. For example, a “window picker” for a screen capture program, or a screen snipping tool, wants to find all the windows on the screen that are visible to the user so they can present them for selection.

The obvious test is Is­Window­Visible(), which checks whether the window and all its parents have the WS_VISIBLE window style. If a window is not visible, then it doesn’t appear on the list.

But that will still find things like windows that belong to non-current virtual desktops, or bits of the shell that are currently not visible, or some UWP apps. What’s up with that?

The shell has a concept called cloaking, in which a window is given all the trappings of visibility, without actually being presented to the user. As far as the app can tell, it seems to be visible: It still has the WS_VISIBLE window style, its coordinates are still within the bounds of the monitor, it still gets WM_PAINT messages, it has a non-empty clipping region, all the ways a traditional Win32 app has of detecting whether it is on screen say, “Yup, you’re on screen. Everything is just fine!”

If Windows didn’t play this trick, it would have to make apps no longer WS_VISIBLE or move them off-screen or assign them an empty region or some other thing to keep them from appearing on the screen.

But the apps would be able to detect those things.

Some apps would get confused: “Well, the only time I make this window hidden is when the user is printing, and I notice that the window is now visible, so I must be printing!” Now the app thinks that it’s printing when it really isn’t, and it might crash because it goes to the printing component to get the name of the target printer, and the printing component says, “What are you talking about? I’m not printing!”

Some apps would notice that they had become hidden and respond by trying to get themselves visible again. “Oh no, I was moved off screen. Let me move back on screen!” Or “Oh no, I’m not visible. Let me force myself visible!”

Inventing a brand new concept (cloaking) ensures that all old apps won’t be able to detect when they were cloaked, since the concept didn’t exist at the time they were written.

But it means that if your program wants to understand all the windows that are visible to the user, you may need to incorporate cloaking into your logic.

BOOL IsWindowCloaked(HWND hwnd)
{
 BOOL isCloaked = FALSE;
 return (SUCCEEDED(DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED,
     &isCloaked, sizeof(isCloaked))) && isCloaked;
}

BOOL IsWindowVisibleOnScreen(HWND hwnd)
{
  return IsWindowVisible(hwnd) &&
         !IsWindowCloaked(hwnd);
}

 

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

19 comments

Discussion is closed. Login to edit/delete existing comments.

  • Paul Jackson

    “and I notice that the window is now visible, so I must be printing”
    You probably meant to say “hidden” instead of “visible”?

  • Pierre Baillargeon

    Begun, has the window visibility war.

    Or rather, the escalation with ill-behaved app continues.

    - I wish to complain about this window what I created not half an hour ago from this very desktop.
    - What's wrong with it?
    - I'll tell you what's wrong with it, my lad. 'E's not visible, that's what's wrong with it!
    - No, no, 'e's uh,...he's painting.
    - Look, matey, I know an invisible window when I don't see one, and...

    Read more
    • David Streeter

      XD

  • smf

    >Inventing a brand new concept (cloaking) ensures that all old apps won’t be able to detect when they were cloaked,
    >since the concept didn’t exist at the time they were written.

    What about new apps?

  • Robin Krom

    Thanks for sharing this with us, your use-case hits the nail on the head for me... I work on Greenshot, which in fact does EXACTLY what you describe in the first paragraph.

    We have some reported issues from people who are not being able to select certain windows as Greenshot thinks that another is in front, but it's not visible. We could not explain this until now... I hope, let's see if this fixes the issue....

    Read more
    • David Streeter

      Greenshot is great! I’ve encountered that issue with Greenshot too, on occasion. Glad it will be fixed now!

    • Yukkuri Reimu

      Greenshot is great, cheers to you!

      • Robin Krom

        Thank you, and thanks to Chen it will be even better. 🙂

    • Robin Krom

      This seems to fix the issue, thanks for reporting it!
      If windows are on a different virtual desktop, they are cloaked. But somehow there are also other windows, I believe the search is one, which are cloaked.

      Btw. I started building an OSS library to make the Greenshot development a bit easier.
      It's for .NET Framework and dotnet core and handles a lot of Win32 complexity, it gives a more modern API for some older concepts:...

      Read more
      • irongut

        Another thanks for the excellent Greenshot! I’ll have to check your library out at some point too. 🙂

  • David Streeter

    “But the plans were on display…”
    “On display? I eventually had to go down to the cellar to find them.”
    “That’s the display department.”
    “With a flashlight.”
    “Ah, well, the lights had probably gone.”
    “So had the stairs.”
    “But look, you found the notice, didn’t you?”
    “Yes,” said Arthur, “yes I did. It was on display in the bottom of a locked filing cabinet stuck in a disused lavatory with a sign on the door...

    Read more
  • Daniel Smith

    I thought cloaking technology was prohibited by the Treaty of Algeron?

  • Alexey Badalov

    Ah, so that’s what I have to check now to know if I’m printing.

    • Wil Wilder Apaza Bustamante

      this comment has been deleted.

  • MGetz

    Honestly I can’t find a reason when this would be useful unless an app does CPU/GPU potentially intensive things while getting WM_PAINT messages and wants to be nice when it’s not actually visible. In most other cases the app should probably take the “Blissfully unaware” tactic and just let the OS do its thing.

    • Raymond ChenMicrosoft employee Author

      I gave an example in the opening paragraph. Consider a teleconferencing app that has an “app sharing” feature, and it says “Click on the app you want to share”, and you click on Excel, but the teleconferencing app mistakenly believes that you clicked on the WoW game on your “gaming” virtual desktop.

    • Brian Beck

      Many apps do. For instance, video apps such as Windows Media Player stop rendering video when invisible.

  • Joshua Hudson

    And that’s why MS was able to get it working well when nobody else could. It isn’t shell functionality. It’s window manager functionality.

    • GL

      I remember under the previous version of https://devblogs.microsoft.com/oldnewthing/20180501-00/?p=98645 (or another), someone said only MS can hide a window in some undocumented way without removing WM_VISIBLE, and Raymond replied that it was done in a documented way, by cloaking.