Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What desktop does Metro stuff run in?

Just curious, from a standpoint of WinAPI developer, what desktop do Metro apps run in?

This stuff:

enter image description here

like image 451
c00000fd Avatar asked Apr 20 '14 02:04

c00000fd


2 Answers

I didn't know that it would be such a secret... so I had to do some investigating and here's what I found:

First off, to answer my original question -- the Metro (or Modern UI) stuff runs in the exact same desktop as the "desktop" apps (pardon the pun.) It is actually all very simple. The short answer -- all Microsoft approved Metro stuff runs in the Internet Explorer_Server container (which, in layman's terms, is the Internet Explorer); or in the DirectUIHWND container (which is Microsoft's proprietary class that renders their undocumented UI), all in windows with the WS_EX_TOPMOST style turned on, which makes them render on top of the other content. And that is it!

Here's a couple of examples:

Let's split the desktop and use Spy++ to see what's happening under the hood:

enter image description here

So if we look into the "Weather" app window, it is nothing more than the regular (Win32) window of the class "Internet Explorer_Server" that is housed in the window of the "Web Platform Embedding" class, which in turn sits in the "Windows.UI.Core.CoreWindow" container that has the WS_EX_TOPMOST and WS_EX_NOREDIRECTIONBITMAP styles on:

enter image description here

If you look even deeper, all Microsoft's Metro stuff seems to run from the WWAHOST.exe process, which in simple terms is the container to run JavaScript for the Metro apps.

Now let's look into the Start Screen itself. Since it completely covers the desktop we need to use a different tool and its Shift key snapshot capability to get to it:

enter image description here

From it we can get the Start Screen's window handle (or 0x10158 in my case) and look it up in the Spy++:

enter image description here

As you can see from both tools, the Start Screen has window class DirectUIHWND, that is housed inside a window of the ImmersiveLauncher class, that is the one with the WS_EX_TOPMOST and WS_EX_NOREDIRECTIONBITMAP styles that make it remain on top. And that is the only difference between it and any other window created by a "desktop" app.

What is also interesting is how the "desktop" itself is rendered in case of a split-window situation. I originally assumed that in this case the desktop is simply shifted (or moved) to one side and resized, but that is not what happens... In reality (or in my Windows 8.1) in case of a split between a desktop and a Metro app, the metro app simply covers over the desktop, but the desktop itself does not change its position or size. In that case, only the taskbar and the existing desktop windows are moved and resized to fit the split. This could be illustrated by this diagram:

enter image description here

As a side note, such moving and resizing can be quite annoying for a user, since original positions and sizes of the desktop windows are not restored when the split goes away.

And lastly, a somewhat unexpected finding. I decided to check how Google folks were able to implement their Chrome browser (running as a Metro app) and found this:

enter image description here

Chrome renders in the Windows.UI.Core.CoreWindow class window, belonging to the Google's own process: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe". So without going any deeper, it is evidently possible to encapsulate a Metro-style app in a non-Microsoft container, which is a good news for developers that don't care about AppStore XAML apps :)

EDIT: Forgot to mention, if you plan to show your own popup message from a Win32 process that is visible on top of a Metro app, you need to do the following:

  • Set UIAccess="true" in the process manifest. You can do so in the Visual Studio by going to Project Properties -> Linker -> Manifest Files and set UAC Bypass UI Protection to YES. (Note that you can keep UAC Execution Level as asInvoker, or not to require elevation of your process.)

  • Code-sign your process. It is important, since without a signature it won't work, and you'll see this error message: "A referral was returned from the server."

enter image description here

An alternative to signing (or for testing purposes on your development system) you can set the following registry key to 0. (I haven't tried it though, and I wouldn't recommend it due to obvious security concerns! But it seems to be another way to test it if a code-signing certificate is not available.)

HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\ValidateAdminCodeSignatures
  • Place the compiled executable file either into the %windir%\System32 folder, or more realistically into the %ProgramFiles%\Company\Product, or into the alternative %ProgramFiles(X86)%\Company\Product folder for your product's installation location.

Also you may consider reading Raymond Chen's article about this topic.

  • After that, when you set the WS_EX_TOPMOST style on your popup window, it will be displayed above any other windows, including the Metro apps, Start Screen, etc.

So in other words, doing this:

//You may also consider setting the WS_EX_NOACTIVATE style
::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0 , 0, 0, SWP_NOMOVE | SWP_NOSIZE);

Can achieve this:

enter image description here

like image 152
c00000fd Avatar answered Oct 21 '22 14:10

c00000fd


Since you say that your actual issue is knowing whether a Metro app is running, the answer is to call IAppVisibility::GetAppVisibilityOnMonitor. Pass the monitor you want to check. Note that this will give the correct answer regardless of what desktop the applications run in.

like image 7
Raymond Chen Avatar answered Oct 21 '22 14:10

Raymond Chen