Metro的东西在什么桌面上运行?

只是好奇,从WinAPI开发人员的角度来看,Metro应用程序运行的桌面是什么?

这个东西:

在此处输入图像描述

我不知道这将是一个秘密…所以我不得不做一些调查,这是我发现的:

首先,回答我原来的问题 – Metro(或现代用户界面)的东西在与“桌面”应用程序完全相同的桌面上运行(请原谅双关语。)实际上这一切都非常简单。 简短的回答 – 所有微软认可的 Metro东西都在Internet Explorer_Server容器中运行(以外行人的名义,就是Internet Explorer); 或者在DirectUIHWND容器(这是Microsoft的专有类,呈现其未记录的UI)中,所有这些都在打开WS_EX_TOPMOST样式的窗口中,这使得它们在其他内容之上呈现。 就是这样!

这里有几个例子:

让我们拆分桌面并使用Spy++来查看幕后发生的事情:

在此处输入图像描述

因此,如果我们查看“天气”应用程序窗口,它只不过是“ Internet Explorer_Server ”类的常规 (Win32)窗口,该窗口位于“ Web Platform Embedding ”类的窗口中,而该窗口又位于“ Windows.UI.Core.CoreWindow ”容器,其中包含WS_EX_TOPMOSTWS_EX_NOREDIRECTIONBITMAP样式:

在此处输入图像描述

如果你看起来更深入,所有微软的Metro 东西似乎都来自WWAHOST.exe进程,简单来说就是为Metro应用程序运行JavaScript的容器。

现在让我们看一下Start Screen本身。 由于它完全覆盖桌面,我们需要使用不同的工具及其Shift键快照function来实现:

在此处输入图像描述

从中我们可以获得Start Screen的窗口句柄(或者在我的情况下为0x10158 )并在Spy ++中查找:

在此处输入图像描述

正如您从两个工具中看到的那样,“开始屏幕”具有窗口类DirectUIHWND ,它位于ImmersiveLauncher类的窗口内,该窗口具有WS_EX_TOPMOSTWS_EX_NOREDIRECTIONBITMAP样式,使其保持在顶部。 这是与“桌面”应用程序创建的任何其他窗口之间的唯一区别。

有趣的是,如果出现分窗情况,“桌面”本身是如何呈现的。 我最初假设在这种情况下,桌面只是简单地移动(或移动)到一侧并resize,但事实并非如此…实际上(或在我的Windows 8.1中)如果桌面和桌面之间存在分离Metro应用程序,地铁应用程序只是覆盖桌面,但桌面本身不会改变其位置或大小。 在这种情况下,仅移动任务栏和现有桌面窗口并调整其大小以适合拆分。 这可以通过以下图表来说明:

在此处输入图像描述

作为旁注,这种移动和resize对于用户来说可能是非常烦人的,因为当分割消失时,桌面窗口的原始位置和大小不会被恢复。

最后,一个意外的发现。 我决定查看Google用户如何实施他们的Chrome浏览器(作为Metro应用程序运行)并发现:

在此处输入图像描述

Chrome在Windows.UI.Core.CoreWindow类窗口中呈现,属于Google自己的进程:“ C:\Program Files (x86)\Google\Chrome\Application\chrome.exe ”。 因此,没有更深入,显然可以将Metro风格的应用程序封装在非Microsoft容器中,这对于不关心AppStore XAML应用程序的开发人员来说是一个好消息:)

编辑:忘记提及,如果您计划在Metro应用程序顶部显示的Win32进程中显示您自己的弹出消息,则需要执行以下操作:

  • 在流程清单中设置UIAccess="true" 。 您可以在Visual Studio中执行此操作,方法是转到“ Project Properties – >“ Linker – > Manifest Files并将“ UAC Bypass UI Protection ”设置为“是”。 (请注意,您可以将UAC Execution Level保持为asInvoker ,或者不要求提升您的流程。)

  • 对您的流程进行代码签名。 这很重要,因为没有签名就行不通,你会看到这个错误信息:“ 从服务器返回了一个推荐。

在此处输入图像描述

签名(或用于开发系统上的测试目的)的替代方法,您可以将以下注册表项设置为0.(我没有尝试过,但由于明显的安全问题,我不建议它 !但它似乎如果代码签名证书不可用,则测试它是另一种方法。)

 HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\ValidateAdminCodeSignatures 
  • 将已编译的可执行文件放入%windir%\System32文件夹中,或更实际地放入%ProgramFiles%\Company\Product ,或放入产品安装位置的备用%ProgramFiles(X86)%\Company\Product文件夹中。

您也可以考虑阅读Raymond Chen关于此主题的文章 。

  • 之后,当您在弹出窗口中设置WS_EX_TOPMOST样式时,它将显示在任何其他窗口上方,包括Metro应用程序,开始屏幕等。

换句话说,这样做:

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

可以做到这一点:

在此处输入图像描述

既然您说您的实际问题是知道Metro应用程序是否正在运行,那么答案就是调用IAppVisibility::GetAppVisibilityOnMonitor 。 通过要检查的显示器。 请注意,无论应用程序运行的桌面是什么,这都将给​​出正确的答案。