【问题标题】:Understanding SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT了解 SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT
【发布时间】:2013-07-22 08:05:34
【问题描述】:

当我的应用程序被外部工具(通过 API)调用时,它需要获得焦点,我知道默认设置是,它应该只在任务栏中闪烁,但在这种情况下,这绝对不是行为我想要的。在这种情况下,我尝试通过“this.Activate()”(C#)获得焦点。

这就是 ForeGroundLockTimeOut 发挥作用的地方。 但是,我在理解 SystemParameterInfo SPI_SETFOREGROUNDLOCKTIMEOUT 时遇到了一点问题。

我知道它用于设置 ForeGroundLockTimeOut,它定义了您的应用必须等待多长时间才能获得所需的焦点。

(有关更多信息,变量“val”是一个设置为 0 的 IntPtr)

SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,val,SPIF_SENDWININICHANGE + SPIF_UPDATEINIFILE);

这将更改处理超时的注册表项 (HKEY_CURRENT_USER\Control Panel\Desktop\ForeGroundLockTimout) 由于这会改变所有应用程序的行为,因此它确实是最后的手段。

现在我想如果我不更新注册表项会怎样。所以我尝试了这个:

SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, val, 0);

但是它不会以任何方式改变我的应用程序的行为,但是

SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,0,val,SPIF_SENDWININICHANGE);

会。

我不明白为什么这只适用于我的应用程序,这绝对是我想要的,但我不明白。为什么我必须广播一个只适用于我的应用程序的更改,当有没有对任何注册表项或任何内容进行任何更改,为什么这仅适用于我的应用程序。

注意:如果您想测试此行为,请在 Visual Studio 未运行时对其进行测试,而在它运行时(即使未加载此解决方案)它会在任何情况下将应用程序的行为更改为获得焦点。

【问题讨论】:

  • 它在任何情况下都会改变应用程序的行为以获取焦点。你甚至 read the fine manual 吗? 系统限制哪些进程可以设置前台窗口。只有满足以下条件之一时,进程才能设置前台窗口: ... 正在调试前台进程。 你正在尝试做的事情让我想起了this
  • 也让我想起了this
  • 是的,我读过它,不,我不会尝试将我的窗口设置在最上面,它大部分时间都在后台运行,我希望它在通过 api 调用时获得焦点(会将其添加到问题中)但即使它有焦点也不应该是最重要的。
  • 是的,它让我想起了this,但我确实想窃取焦点,而不是让其他应用程序给我,因为我并不总是能够修改外部工具的代码

标签: windows winforms winapi focus


【解决方案1】:

这不是针对每个应用的设置,而是全局系统设置。无法仅为您的应用程序设置它,所以当您调用 SystemParametersInfo 并为最后一个参数设置 0 时,什么也不会发生。

另一方面,当您使用SPIF_SENDWININICHANGE 时,新设置会以WM_SETTINGCHANGE 消息的形式广播。 (这就是为什么手动编辑注册表是错误的做法;始终调用记录在案的 API。)

除此之外,这段代码是错误的:

SPIF_SENDWININICHANGE + SPIF_UPDATEINIFILE

要连接两个标志,您必须使用布尔 OR 运算符 (|),而不是加法运算符 (+)。在这种特殊情况下,因为 0x1 + 0x20x1 | 0x2 都等于 3,所以它似乎可以工作,但这只是一个意外。

这个问题的真正解决方案不需要涉及操纵全局设置(因为您肯定不想在客户端计算机上这样做,即使您自己也可以)。您需要系统一起工作,而不是试图对抗它。在系统模型中,当前具有焦点的进程是具有设置/更改焦点权限的进程。所以基本上有三种选择:

  1. 只需让外部工具调用SetForegroundWindow 本身并将应用程序的窗口作为参数传递。这完全避免了您的应用必须自行激活。

  2. 使用AllowSetForegroundWindow 函数将外部工具的前台窗口设置权限委派给您的应用程序。它应该调用此函数,并将应用进程的 ID 作为参数传递。这样,当您的应用调用SetForegroundWindow 时,它将按预期工作。

  3. 根据您的工具和应用程序的设计方式,您可以只使用外部工具启动应用程序。正如the documentation所说,如果一个进程是由前台进程启动的,则允许设置前台窗口。

【讨论】:

  • 嗯,我不确定这是否完全正确。当我用 SPIF_SENDWININICHANGE 调用它时,只有我的应用程序的行为会发生变化,而不是其他人的行为
  • 考虑到你真正的解决方案,这里的问题是我不一定能够改变外部工具的代码
  • 那是因为只有你的应用知道这种行为。其他应用程序均未收到通知。尝试重新启动、注销并重新打开,甚至重新启动其中一个应用程序。如果您无法更改外部工具,那么您就不走运了。它如何知道如何与您的应用交互?
  • 它通过 api 进行交互,但重新启动其他应用程序没有任何区别,它们仍然表现“正常”,在任务栏中闪烁,重新启动和重新登录也不会改变任何东西,因为我没有修改注册表项。 (第二次和第三次尝试)
  • 好的,然后注册表项被缓存,他们正在从缓存中检索它。你必须重新启动。编辑注册表不是进行这些更改的方式。
【解决方案2】:

SPIF_UPDATEINIFILE--将新的系统范围参数设置写入用户配置文件。 SPIF_SENDCHANGE--更新用户配置文件后广播 WM_SETTINGCHANGE 消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    相关资源
    最近更新 更多