Я пытаюсь найти надежный способ активироваться / фокус набора к окну внешнего приложения с помощью C#. В настоящее время я пытаюсь достигнуть этого использования следующего Windows API calls:
SetActiveWindow(handle);
SwitchToThisWindow(handle, true);
Ранее я также имел ShowWindow(handle, SW_SHOWMAXIMIZED);
выполнение перед другими 2, но удаленный это, потому что это вызывало странное поведение.
Проблема, которую я имею со своей текущей реализацией, состоит в том, что иногда фокус не будет установлен правильно. Окно станет видимым, но верхняя часть его все еще появится grayed, как будто это не было в фокусе.
Существует ли способ надежно сделать это, которое работает 100% времени, или действительно ли непоследовательное поведение является побочным эффектом, из которого я не могу выйти? Сообщите мне, есть ли у Вас какие-либо предложения или реализации, это всегда работает.
Вам необходимо использовать 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.
Если это все внутреннее в вашем приложении, вы можете получить родительское окно или это окно и таким образом активировать его (извините):
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