了解SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT

时间:2013-07-22 08:05:35

标签: windows winforms winapi focus

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

2 个答案:

答案 0 :(得分:4)

这不是每个应用程序设置,而是全局系统设置。没有办法只为你的应用程序设置它,所以当你为最后一个参数调用SystemParametersInfo时,没有任何反应。

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

除此之外,这段代码错了:

SPIF_SENDWININICHANGE + SPIF_UPDATEINIFILE

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

此问题的真正解决方案不需要涉及操纵全局设置(因为您肯定不希望在客户端计算机上执行此操作,即使您自己也可以使用它)。您需要使用系统工作,而不是试图对付它。在系统的模型中,当前具有焦点的过程是具有设置/改变焦点的特权的过程。所以基本上有三种选择:

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

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

  3. 根据您的工具和应用程序的设计方式,您可以使用外部工具启动应用程序。与the documentation类似,如果前台进程启动进程,则允许设置前台窗口。

答案 1 :(得分:0)

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