Есть ли надежный способ активировать / установить фокус на окно с помощью C #? - PullRequest
7 голосов
/ 20 апреля 2010

Я пытаюсь найти надежный способ активировать / установить фокус на окно внешнего приложения, используя C #. В настоящее время я пытаюсь добиться этого с помощью следующих вызовов Windows API:

SetActiveWindow(handle);
SwitchToThisWindow(handle, true);

Ранее я также выполнял ShowWindow(handle, SW_SHOWMAXIMIZED); перед двумя другими, но удалил его, потому что это вызывало странное поведение.

Проблема с моей текущей реализацией заключается в том, что иногда фокус не будет установлен правильно. Окно станет видимым, но его верхняя часть будет отображаться серым, как если бы оно не было в фокусе.

Есть ли способ сделать это надежно, который работает 100% времени, или это противоречивое поведение - побочный эффект, от которого я не могу уйти? Пожалуйста, дайте мне знать, если у вас есть предложения или реализации, которые всегда работают.

Ответы [ 4 ]

8 голосов
/ 20 апреля 2010

Вам нужно использовать AttachThreadInput

Окна, созданные в разных потоках, обычно обрабатывают ввод независимо друг от друга. То есть они имеют свои собственные состояния ввода (фокус, активное, окна захвата, состояние ключа, состояние очереди и т. Д.), И они не синхронизируются с обработкой ввода других потоков. Используя функцию AttachThreadInput, поток может присоединить свою обработку ввода к другому потоку. Это также позволяет потокам совместно использовать свои состояния ввода, поэтому они могут вызывать функцию SetFocus, чтобы установить фокус клавиатуры на окне другого потока. Это также позволяет потокам получать информацию о состоянии ключа. Эти возможности, как правило, невозможны.

Я не уверен в последствиях использования этого API (предположительно) Windows Forms. Тем не менее, я использовал его в 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.

3 голосов
/ 17 марта 2011
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool SetForegroundWindow(IntPtr hWnd);

Этот работал для меня

1 голос
/ 20 апреля 2010

Если это все внутреннее в вашем приложении, вы можете получить родительское окно или это окно и активировать его (vb Извините):

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
0 голосов
/ 17 сентября 2018
        hwnd_WhoRecvFocus.ShowWindow( SW_MINIMIZE )
        hwnd_WhoRecvFocus.ShowWindow( SW_RESTORE )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...