windowswinapiuser32

How to find (virtual) desktop that a window resides on?


I use multiple desktops on Windows, and I am trying to determine which desktop a window resides on. I can retrieve the position of a window using GetWindowRect (from user32.dll), but this doesn't tell me which desktop the window is on (Desktop 1, Desktop 2, etc).

This is a fairly important part of the application I am writing, so I am open to any possible solution. I assume if this is feasible the functionality will be exposed somewhere in user32.dll, but I am open to more hacky approaches. If this is only possible with a kernel driver, then that would be good to know.

NOTE: By 'desktop' I don't mean 'monitor', this is a different thing, see Multiple desktops in Windows. It is really hard to search for information on 'windows desktops', as Google is convinced I mean 'the desktop', and refuses to consider any alternatives.


Solution

  • The feature you are referring to is more formally known as "Virtual Desktops". However, it is designed as a user-managed feature only, so application support for its is very limited:

    Virtual desktops are an end-user window management feature, not a programmatic one

    Virtual desktops are a window management feature, not a security feature or a performance feature. Furthermore, they are for end users to organize their windows, not for other programs to organize the windows.

    The purpose of the IVirtual­Desktop­Manager interface is to allow applications to take the virtual desktop state into account in a few application scenarios.

    That said, the IVirtualDesktopManager interface does have a GetWindowDesktopId() method:

    Gets the identifier for the virtual desktop hosting the provided top-level window.

    Pretty much the only official thing you can do with that id is move other windows to the same desktop by using IVirtualDesktopManager::MoveWindowToDesktop():

    Moves a window to the specified virtual desktop.

    As described in the above article:

    Another scenario that the IVirtual­Desktop­Manager interface is intended to cover is that of an application that consists of multiple windows that operate together, like a main window and a bunch of auxiliary windows. The virtual desktop manager already recognizes many types of auxiliary windows and automatically keeps them on the same virtual desktop as the main window. But an application may have an unusual window structure that eludes this automatic detection.

    For those cases, you can call IVirtual­Desktop­Manager::Get­Window­Desktop­Id for your main window to get an ID for its current virtual desktop, and then use IVirtual­Desktop­Manager::Move­WindowsTo­Desktop to move the auxiliary windows to that same virtual desktop.

    The purpose of Move­WindowsTo­Desktop is specifically not to let a program grab all of the user’s windows and scatter them across all their virtual desktops. Note, for example, that the only thing you can do is make one window join another window’s virtual desktop. You can bring windows together, but you can’t, say, split a window into a new virtual desktop.

    Because the point is to let you move your auxiliary windows so they follow the main window. It is not a general purpose interface for moving windows onto arbitrary virtual desktops. That’s for the user to do.

    That being said, there is an an undocumented IVirtualDesktopManagerInternal interface that can perform more actions, such as enumerating virtual desktops, creating/removing virtual desktops, switching between virtual desktops, etc, however you should avoid using that interface unless you absolutely need it.