有没有一种可靠的方法来使用C#激活/设置焦点到窗口?

gta*_*rga 8 c# windows focus

我正在尝试使用C#找到一种可靠的方法来激活/设置焦点到外部应用程序的窗口.目前我正在尝试使用以下Windows API调用来实现此目的:

SetActiveWindow(handle);
SwitchToThisWindow(handle, true);
Run Code Online (Sandbox Code Playgroud)

以前我也在ShowWindow(handle, SW_SHOWMAXIMIZED);其他2之前执行过,但是因为它导致了奇怪的行为而删除了它.

我当前实现的问题是偶尔会无法正确设置焦点.窗口将变为可见,但其顶部仍显示为灰色,就好像它没有聚焦一样.

有没有办法可靠地做到这一点,100%的时间工作,或不一致的行为是我无法逃避的副作用?如果您有任何建议或实施始终有效,请告诉我.

Log*_*ldo 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);
     }
Run Code Online (Sandbox Code Playgroud)

targetHwndHWND你想要设置焦点的窗口的.我假设您已经可以使用P/Invoke签名,因为您已经在使用本机API.


Gui*_*ssé 5

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);
Run Code Online (Sandbox Code Playgroud)

这对我有用