C++ Metro stuff运行在什么桌面上?

C++ Metro stuff运行在什么桌面上?,c++,c,winapi,microsoft-metro,win32gui,C++,C,Winapi,Microsoft Metro,Win32gui,只是好奇,从WinAPI开发者的角度来看,Metro应用程序运行在什么环境中 这些东西: 我不知道这会是一个如此秘密。。。所以我必须做一些调查,以下是我的发现: 首先,回答我最初的问题——Metro(或现代UI)的运行方式与“桌面”应用程序完全相同(请原谅这个双关语)。实际上,这一切都非常简单。简而言之,所有微软批准的Metro产品都运行在InternetExplorer\u服务器容器中(用外行的话说就是InternetExplorer);或者在容器(这是Microsoft的专有类,用于呈现其未

只是好奇,从WinAPI开发者的角度来看,Metro应用程序运行在什么环境中

这些东西:


我不知道这会是一个如此秘密。。。所以我必须做一些调查,以下是我的发现:

首先,回答我最初的问题——Metro(或现代UI)的运行方式与“桌面”应用程序完全相同(请原谅这个双关语)。实际上,这一切都非常简单。简而言之,所有微软批准的Metro产品都运行在
InternetExplorer\u服务器
容器中(用外行的话说就是InternetExplorer);或者在容器(这是Microsoft的专有类,用于呈现其未记录的UI)中,都在windows中,且样式已打开,这使它们呈现在其他内容之上。就这样

这里有几个例子:

让我们拆分桌面并使用
Spy++
查看引擎盖下发生的事情:

因此,如果我们查看“天气”应用程序窗口,它只不过是类“
internetexplorer\u Server
”的常规(Win32)窗口,该类位于“
webplatformembedding
”类的窗口中,而该类又位于“
Windows.UI.Core.corefown
”中在以下位置上具有
WS\u EX\u最顶部
WS\u EX\u NOREDIRECTIONBITMAP
样式的容器:

如果你看得更深入一些,所有微软的Metro东西似乎都是从这个过程中运行的,简单来说,这个过程就是为Metro应用程序运行JavaScript的容器

现在让我们来看看这个问题本身。由于它完全覆盖了桌面,我们需要使用不同的工具及其Shift键快照功能来访问它:

通过它,我们可以获得开始屏幕的窗口句柄(或者在我的例子中是
0x10158
),并在Spy++中查找它:

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

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

顺便说一句,这种移动和调整大小对于用户来说是非常烦人的,因为当拆分消失时,桌面窗口的原始位置和大小不会恢复

最后,一个有点出乎意料的发现。我决定检查一下Google人员是如何实现他们的Chrome浏览器(作为Metro应用程序运行)的,并发现:

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

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

  • 在流程清单中设置
    UIAccess=“true”
    。您可以在Visual Studio中执行此操作,方法是转到
    项目属性
    ->
    链接器
    ->
    清单文件
    ,然后将
    UAC旁路UI保护设置为是。(请注意,您可以将
    UAC执行级别保持为
    asInvoker
    ,也可以不要求提升流程。)

  • 对流程进行代码签名。这很重要,因为如果没有签名,它将无法工作,您将看到以下错误消息:“从服务器返回了一个引用。”

除了签名(或为了在开发系统上进行测试),您还可以将以下值设置为0。(虽然我还没有尝试过,但出于明显的安全考虑,我不推荐使用它!但如果代码签名证书不可用,这似乎是另一种测试方法。)

  • 将编译后的可执行文件放入
    %windir%\System32
    文件夹,或者更实际地放入
    %ProgramFiles%\Company\Product
    文件夹,或者放入产品安装位置的备选
    %ProgramFiles(X86)%\Company\Product
    文件夹
也可以考虑阅读这个话题。

  • 之后,当您在弹出窗口上设置
    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
。通过要检查的监视器。请注意,无论应用程序在哪个桌面上运行,这都将给出正确答案。

这是一个实施细节,可能会发生更改。你的实际编程问题是什么?@RaymondChen:知识。除此之外,如果Metro应用程序正在运行,我可能需要显示一个弹出通知。已经有一个,但显然没有人知道。尽管如此,我还是想知道,除了技术基础之外,这种以全屏模式运行应用程序的疯狂决定是如何实现的
//You may also consider setting the WS_EX_NOACTIVATE style
::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0 , 0, 0, SWP_NOMOVE | SWP_NOSIZE);