Pinvoke SetFocus для определенного элемента управления - PullRequest
3 голосов
/ 29 февраля 2012

Простой вопрос: можно ли установить фокус на текстовое поле другого приложения (используя его ClassName).У меня есть окно как «intptr» и т. Д., Но мне нужно лишь некоторое руководство относительно того, какие функции / API доступны для этого!

Проблема в том, что я использую API SetForegroundWindow, чтобы получить фокус окна, но это неПозвольте мне отправить клавиши Ctrl + L, чтобы сфокусироваться на текстовом поле!

Любая помощь будет отличной!

1 Ответ

3 голосов
/ 03 марта 2012

... насколько я помню, это код, который я должен был использовать, чтобы заставить это работать - и это хорошо работало на моих приложениях, и более новых Windows и т. Д.

void SetFocus(IntPtr hwndTarget, string childClassName)
{
    // hwndTarget is the other app's main window 
    // ...
    IntPtr targetThreadID = WindowsAPI.GetWindowThreadProcessId(hwndTarget, IntPtr.Zero); //target thread id
    IntPtr myThreadID = WindowsAPI.GetCurrentThread(); // calling thread id, our thread id
    try
    {
        bool lRet = WindowsAPI.AttachThreadInput(myThreadID, targetThreadID, -1); // attach current thread id to target window

        // if it's not already in the foreground...
        lRet = WindowsAPI.BringWindowToTop(hwndTarget);
        WindowsAPI.SetForegroundWindow(hwndTarget);

        // if you know the child win class name do something like this (enumerate windows using Win API again)...
        var hwndChild = EnumAllWindows(hwndTarget, childClassName).FirstOrDefault();

        if (hwndChild == IntPtr.Zero)
        {
            // or use keyboard etc. to focus, i.e. send keys/input...
            // SendInput (...);
            return;
        }

        // you can use also the edit control's hwnd or some child window (of target) here
        WindowsAPI.SetFocus(hwndChild); // hwndTarget);
    }
    finally
    {
        bool lRet = WindowsAPI.AttachThreadInput(myThreadID, targetThreadID, 0); //detach from foreground window
    }
}

...что-то в этом роде (оно делает то, что вам нужно и в правильном порядке, не забудьте отсоединить и т. д. - но вам нужно будет настроить его под ваши конкретные условия, контролировать / редактировать hwnd и т. д. - и все же вы можетеесть другие проблемы, связанные с целевым окном / приложением, это работает для большинства, но не во всех случаях, это длинная история, и, как я уже сказал, зависит от вашего конкретного сценария),

(WindowsAPI являются типичными оболочками PInvoke Iповерьте) в основном вам нужно присоединиться к другому потоку для операций ввода, я считаю, что это официальное объяснение: «Это также позволяет потокам совместно использовать свои состояния ввода, поэтому они могут вызывать функцию SetFocus, чтобы установить фокус клавиатуры на окнедругая тема. "Google для AttachThreadInput для получения дополнительной информации (чтобы узнать причины), и это также часто связано с SetFocus и другими операциями ввода / клавиатуры.Кроме того, API автоматизации может помочь в соответствии с предложением - это самый «чистый» способ сделать это - но зависит, если целевое приложение выставляет и обрабатывает это должным образом - что все еще «не существует» для большинства из них, не согласовано и т. Д. - есливы хотите обрабатывать свое «собственное приложение», которое отличается от этого, вам нужно спросить себя, каков лучший сценарий и т. д. Надеюсь, это поможет

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

РЕДАКТИРОВАТЬ: я немного уточнил для вашего конкретного случая и фокус ребенка
РЕДАКТИРОВАТЬ (2):
код является примером для этой спецификации.и основаны на рабочем коде, но могут потребоваться тестирование и проработка некоторых деталей (которые, по-видимому, выходят за рамки данного вопроса), например ..
WindowsAPI содержит сигнатуры PInvoke для Windows API и собственных вызовов (аналог MS.Win32.UnsafeNativeMethods) и это статический класс (см. этот класс или http://pinvoke.net/ - также Доступ к Microsoft.Win32.UnsafeNativeMethods? ), должен иметь имя (Safe / Unsafe) NativeMethods (http://msdn.microsoft.com/en-us/library/ms182161.aspx) - а также см. IntPtr, SafeHandle и HandleRef - объяснено (IntPtr - немного «старый» стиль)
EnumAllWindows использует EnumChildWindows и GetClassName Win API (и это для другого вопроса, я думаю) и требует, чтобы для него был полезен метод-обертка (которым является EnumAllWindows - он просто перечисляет через рекурсивную проверку окон на имена классов).

...