我的应用程序需要在被外部工具(通过 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 未运行时对其进行测试,而在它运行时(即使未加载此解决方案)它会将应用程序的行为更改为在任何情况下都获得焦点。
最佳答案
这不是针对每个应用的设置,而是全局系统设置。无法只为您的应用程序设置它,因此当您调用 SystemParametersInfo
并将最后一个参数设为 0 时,什么也不会发生。
另一方面,当您使用 SPIF_SENDWININICHANGE
时,新设置会以 WM_SETTINGCHANGE
消息的形式广播。 (这就是为什么手动编辑注册表是错误的做法;始终调用记录的 API。)
除此之外,这段代码是错误的:
SPIF_SENDWININICHANGE + SPIF_UPDATEINIFILE
要连接两个标志,您必须使用 bool 运算符 OR (|
),而不是加法运算符 (+
)。在这种特殊情况下,因为 0x1 + 0x2
和 0x1 | 0x2
都等于 3,这似乎有效,但这只是一个意外。
这个问题的真正解决方案不需要涉及操纵全局设置(因为您肯定不想在客户端机器上这样做,即使您自己可以接受)。您需要与系统一起工作,而不是试图与它作对。在系统模型中,当前拥有焦点的进程是具有设置/更改焦点特权的进程。所以基本上有三种选择:
只需让外部工具调用
SetForegroundWindow
本身并将应用程序的窗口作为参数传递。这完全避免了您的应用必须自行激活。使用
AllowSetForegroundWindow
函数将外部工具的前景窗口设置权限委托(delegate)给您的应用程序。它应该调用此函数,将您的应用进程的 ID 作为参数传递。这样,当您的应用调用SetForegroundWindow
时,它将按预期工作。根据您的工具和应用程序的设计方式,您可以只使用外部工具启动应用程序。喜欢the documentation表示,如果一个进程由前台进程启动,则允许设置前台窗口。
关于windows - 了解 SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17782622/