我有点难以完全理解AttachThreadInput.
我知道它在"连接"2个线程的消息队列,这样(我想要的)就允许我强制我的窗口(winforms)置于前台。
我可以用这种方法实现:
private void SetForegroundWindowEx(IntPtr hWnd)
{
uint SW_SHOW = 5;
uint appThread = GetCurrentThreadId();
uint foregroundThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
if (foregroundThread != appThread)
{
AttachThreadInput(foregroundThread, appThread, true);
BringWindowToTop(hWnd);
ShowWindow(hWnd, SW_SHOW);
AttachThreadInput(foregroundThread, appThread, false);
}
else
{
BringWindowToTop(hWnd);
ShowWindow(hWnd, SW_SHOW);
}
}
然而,当线程分离后,两个窗口都会立即失去焦点。
如果我等待消息队列被清空(Application.DoEvents()),并激活我的窗口(它现在在前台但没有获得焦点),它将重新获得焦点并保持焦点。
如果我在消息队列被清空之前这样做,它将再次失去焦点。
所以我猜想,某些东西的分离将焦点从我的窗口中取走了,但我不知道那是什么或者如何防止它。
这是我不太理解的第一件事。
我不理解的第二件事是,如果我不将我的窗口设置为前景窗口:
AttachThreadInput(foregroundThread, appThread, true);
AttachThreadInput(foregroundThread, appThread, false);
Application.DoEvents();
this.Activate();
等待消息队列为空,并激活我的窗口(此时它不在前台,而另一个窗口仍然拥有焦点),它实际上被激活了,尽管线程已经不再附加。
也许对 AttachThreadInput 有更好理解的人可以回答我这两个问题。
信息:
在这种情况下,我需要窃取焦点,因为我的应用程序通过 API 被调用。调用我的其他应用程序会等待我的反馈,在大多数情况下会冻结,直到它获得信息。
如果其他应用程序是全屏的,则很多用户没有注意到任务栏中的闪烁,认为其他应用程序崩溃并使用任务管理器杀死它。既然我不能控制其他应用程序,我就无法告诉它将焦点设置为我的窗口。
如果不是绝对必要,就不会调用此方法,在这种情况下,这种敌对行为既是我自己所需要的,也是用户所需要的。