1

我的应用程序在被外部工具(通过 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 未运行时对其进行测试,而在它运行时(即使未加载此解决方案)它会在任何情况下将应用程序的行为更改为获得焦点。

4

2 回答 2

4

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

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

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

SPIF_SENDWININICHANGE + SPIF_UPDATEINIFILE

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

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

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

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

  3. 根据您的工具和应用程序的设计方式,您可以让外部工具启动应用程序。就像文档说的那样,如果一个进程由前台进程启动,则允许设置前台窗口。

于 2013-07-22T08:36:36.830 回答
0

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

于 2016-11-22T15:18:45.507 回答