我正在尝试使用C#找到一种可靠的方法来激活/设置焦点到外部应用程序的窗口。目前,我正在尝试使用以下Windows API调用实现此目的:
SetActiveWindow(handle);
SwitchToThisWindow(handle, true);
以前我也有ShowWindow(handle, SW_SHOWMAXIMIZED);
在另外2个之前执行,但删除了它,因为它导致了奇怪的行为。
我当前实现的问题是偶尔会无法正确设置焦点。窗口将变为可见,但它的顶部仍然显示为灰色,就好像它没有聚焦一样。
有没有办法可靠地做到这一点,100%的时间都在工作,或者是不一致的行为是我无法逃避的副作用?如果您有任何始终有效的建议或实施,请告诉我。
答案 0 :(得分:8)
您需要使用AttachThreadInput
在不同线程中创建的Windows通常彼此独立地处理输入。也就是说,它们有自己的输入状态(焦点,活动,捕获窗口,键状态,队列状态等),并且它们与其他线程的输入处理不同步。通过使用AttachThreadInput函数,线程可以将其输入处理附加到另一个线程。这也允许线程共享它们的输入状态,因此它们可以调用SetFocus函数将键盘焦点设置为不同线程的窗口。这也允许线程获取密钥状态信息。这些功能通常是不可能的。
我不确定从(可能)Windows窗体使用此API的后果。也就是说,我在C ++中使用它来获得这种效果。代码如下所示:
DWORD currentThreadId = GetCurrentThreadId();
DWORD otherThreadId = GetWindowThreadProcessId(targetHwnd, NULL);
if( otherThreadId == 0 ) return 1;
if( otherThreadId != currentThreadId )
{
AttachThreadInput(currentThreadId, otherThreadId, TRUE);
}
SetActiveWindow(targetHwnd);
if( otherThreadId != currentThreadId )
{
AttachThreadInput(currentThreadId, otherThreadId, FALSE);
}
targetHwnd
是您要设置焦点的窗口的HWND
。我假设您已经可以使用P / Invoke签名,因为您已经在使用本机API。
答案 1 :(得分:3)
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
这个对我有用
答案 2 :(得分:1)
如果它在您的应用程序中都是内部的,那么您可以获取父窗口或该窗口,并以这种方式激活它(对不起):
Public Class Form1 : Inherits Form
Protected Overrides Sub OnLoad(e As EventArgs)
Dim form2 As New Form2
form2.Show()
End Sub
End Class
Class Form2 : Inherits Form
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
Me.Owner.Activate()
End Sub
End Class
答案 3 :(得分:0)
hwnd_WhoRecvFocus.ShowWindow( SW_MINIMIZE )
hwnd_WhoRecvFocus.ShowWindow( SW_RESTORE )