我完全理解了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有更好了解的人可以回答我这2个问题。
信息:
我需要在这种情况下窃取焦点,因为我的应用程序是通过API调用的。另一个叫我的应用程序,等待我的应用程序的反馈,并且大多数时候会冻结,直到获得信息。
如果其他应用程序是全屏,许多用户不会注意到任务栏中的闪烁,并认为其他应用程序崩溃并使用Taskmamanger将其终止。由于我不一定能控制其他应用程序,我无法告诉它将焦点设置到我的窗口。
如果不是绝对必要的话,这个方法就不会被调用,在这种情况下,这种行为是敌对的,我知道,我自己和用户一样。
答案 0 :(得分:10)
这是我用于同一目的的一段c#代码。我想指出有可能需要这样的合法案例。在我们的情况下,它是MS Word自动化。每当用户点击我们的应用程序内的工具栏按钮时,我们应立即引起用户注意Word窗口。
public static void ForceWindowIntoForeground(IntPtr window)
{
uint currentThread = Win32.GetCurrentThreadId();
IntPtr activeWindow = Win32.GetForegroundWindow();
uint activeProcess;
uint activeThread = Win32.GetWindowThreadProcessId(activeWindow, out activeProcess);
uint windowProcess;
uint windowThread = Win32.GetWindowThreadProcessId(window, out windowProcess);
if (currentThread != activeThread)
Win32.AttachThreadInput(currentThread, activeThread, true);
if (windowThread != currentThread)
Win32.AttachThreadInput(windowThread, currentThread, true);
uint oldTimeout = 0, newTimeout = 0;
Win32.SystemParametersInfo(Win32.SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);
Win32.SystemParametersInfo(Win32.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref newTimeout, 0);
Win32.LockSetForegroundWindow(LSFW_UNLOCK);
Win32.AllowSetForegroundWindow(Win32.ASFW_ANY);
Win32.SetForegroundWindow(window);
Win32.ShowWindow(window, Win32.SW_RESTORE);
Win32.SystemParametersInfo(Win32.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);
if (currentThread != activeThread)
Win32.AttachThreadInput(currentThread, activeThread, false);
if (windowThread != currentThread)
Win32.AttachThreadInput(windowThread, currentThread, false);
}