Существует ли надежный способ активироваться / фокус набора к окну с помощью C#?

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

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

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

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

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

8
задан tshepang 7 July 2014 в 11:58
поделиться

2 ответа

Вам необходимо использовать AttachThreadInput

Windows, созданные в разных потоках, обычно обрабатывают ввод независимо друг от друга. То есть у них есть свои собственные состояния ввода (фокус, активное, окна захвата, состояние ключа, состояние очереди и т. Д.), И они не синхронизируются с обработкой ввода других потоков. Используя функцию 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.

8
ответ дан 5 December 2019 в 12:57
поделиться

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

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
1
ответ дан 5 December 2019 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: