1

我有一个隐藏进程等待非标准硬件按钮消息并运行应用程序(使用 CreateProcess)。用户打扰没问题,这是用户自己认可的动作。一切都很好,当它是显示任务栏的通常布局以及多个有标题和无标题的窗口时。但在 XP 和 7 中情况有所不同,此时当前应用程序是全屏的。在这种情况下,全屏应用程序是没有边框的窗口,具有与屏幕完全相同的尺寸。Windows 会隐藏此类应用程序的任务栏,即使它始终处于打开状态。

在 Xp 中,没关系,在这种情况下显示任务栏和应用程序(例如计算器),全屏应用程序在启动的应用程序和任务栏以外的区域仍然可见。但在 Windows 7 中,没有任何视觉反应,全屏应用程序仍然打开,如果我切换到任务栏,执行的应用程序就在那里。我尝试使用 SetForegroundWindow、BringWindowToTop 甚至 AllowSetForegroundWindow(GetCurrentProcessId()) 调用使用 CreateProcess-WaitForIntputIdle-EnumThreadWindows 找到的窗口句柄来解决它,没有任何变化。那么,自从 XP 与官方记录的全屏窗口相关以来,有什么变化吗?

谢谢,

最大限度

4

3 回答 3

1

Vista 引入了桌面组合功能。简而言之,所有窗口都绘制到内存位图,然后桌面窗口管理器组合这些位图并在全屏 Direct3D 表面上绘制。全屏窗口不参与桌面组成,直接在屏幕上绘图(主要是因为大多数全屏应用都是需要实时屏幕更新的游戏)。

特别是,这意味着当全屏应用程序启动并运行时,它覆盖了 DWM 合成图像,用户需要切换到 DWM 管理的窗口,以便 DWM 开始在全屏应用程序之上绘图。

不幸的是,我没有很好的解决您的问题的方法。解决它的一种方法是将 WS_CAPTION 样式添加到您的应用程序中,然后WM_NCPAINT//自己处理WM_NCCALCSIZEWM_NCHITTEST这将允许您向 DWM 谎称您是一个常规的窗口应用程序,但在视觉上改变您的 NC 区域,使您看起来没有标题。但是,这确实需要一定数量的额外代码,并且可能需要您投入更多的精力。

您可以尝试解决问题的另一种方法是在启动新进程时显式最小化全屏应用程序窗口。但是,您将不得不解决何时再次将其最大化的问题。

顺便说一句,您可能会发现Raymond Chen对这篇文章的评论很有趣。

于 2010-06-30T09:05:08.450 回答
1

我可以想象,如果您有自己的硬件设备,那么会有一些 API 用于生成“真实”用户输入。显然,传统的键盘和鼠标,以及现在的 USB HID 驱动程序(我认为其中许多是用户模式?)都可以访问 API 来执行此操作。

例如 Synergy+ 可以在连接的 PC 上生成假的键盘和鼠标事件,假输入的结果是正常的窗口切换激活。

所以,我最初的想法是让你的用户模式“设备”应用程序合成实际的键盘消息——SendInput 似乎很可能是“可以“伪造”真实用户输入事件的 API 的候选者。

然后,在您的“UI”应用程序中使用类似 RegisterHotKey 的 API 来响应您的设备应用程序生成的热键组合。

现在,(假设 SendInput 正在生成正确级别的用户输入事件),您应该(从您的 UI 应用程序中的 WM_HOTKEY 处理程序中)有权(因为一切都是“用户启动”)更改前台窗口(对您自己) .

于 2010-06-30T10:28:22.133 回答
0

Windows 支持多个桌面,我的猜测是全屏显示使用的桌面与默认桌面不同(您的应用程序将在其中显示)。Windows 中的桌面对象是“一个逻辑显示表面,包含用户界面对象,例如窗口、菜单和挂钩”。例如,屏幕保护程序通常在单独的桌面上启动。

您可以使用 Process Explorer 找出应用程序正在哪个桌面上运行:

  • 将 Process Explorer 设置为替换任务管理器并始终在顶部运行。
  • 显示全屏时,按 Ctrl + Shift + Esc 启动 Process Explorer
  • 在 Process Explorer 中,选择全屏进程并按 Ctrl + H 以显示该进程的句柄
  • 查看列表中桌面项的值。通常这将设置为默认值

如果您知道此应用程序在哪个桌面上运行,您可以在同一个桌面上启动您的进程,方法是首先调用OpenDesktop获取该桌面的句柄,然后将其传递给STARTUPINFO您的CreateProcess调用。

于 2010-06-30T08:55:08.583 回答