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_TOPMOST
和WS_EX_NOREDIRECTIONBITMAP
样式:
如果你看起来更深入,所有微软的Metro 东西似乎都来自WWAHOST.exe
进程,简单来说就是为Metro应用程序运行JavaScript的容器。
现在让我们看一下Start Screen本身。 由于它完全覆盖桌面,我们需要使用不同的工具及其Shift键快照function来实现:
从中我们可以获得Start Screen的窗口句柄(或者在我的情况下为0x10158
)并在Spy ++中查找:
正如您从两个工具中看到的那样,“开始屏幕”具有窗口类DirectUIHWND
,它位于ImmersiveLauncher
类的窗口内,该窗口具有WS_EX_TOPMOST
和WS_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
。 通过要检查的显示器。 请注意,无论应用程序运行的桌面是什么,这都将给出正确的答案。