Чтение из текстового поля в окне другого приложения

есть ли способ для приложения Windows, чтобы получить доступ к другим данным приложений, более конкретно поле ввода текста в GUI, и захватить текст там для обработки в нашем собственном приложении?

Если это возможно, есть ли способ "защитить" ваше приложение, чтобы предотвратить это?

EDIT: три первых ответа, похоже, касаются получения заголовка другого окна приложения, а не конкретного поля ввода текста в этом окне.

Я не ожидаю Windows API, итак, не могли бы вы быть более точными, как найти определенное текстовое поле в этом окне, каковы его преквизиты (похоже, что требуется знать дескриптор окна, требуется ли также знать дескриптор текстового поля? Как мне это получить? так далее...)

фрагменты кода на C++ действительно были бы очень признательны. Справка MSDN трудно просматривать, так как Win32-API имеет такие ужасные соглашения об именах.

завершено! см. мой ответ ниже для how-to in С.++

7 ответов


для чтения текстового содержимого из текстового поля другого приложения вам нужно будет каким-то образом получить дескриптор окна этого элемента управления текстовым полем. В зависимости от того, как разработан пользовательский интерфейс приложения (если он имеет пользовательский интерфейс), есть несколько различных способов получения этого дескриптора. Вы можете использовать "FindWindow" / "FindWindowEx", чтобы найти свой элемент управления или использовать" WindowFromPoint", если это имеет смысл. В любом случае, как только у вас есть дескриптор текстового элемента управления, вы можете отправить сообщение "WM_GETTEXT это, чтобы получить его содержимое (предполагая, что это стандартный элемент управления текстового поля). Вот состряпанный образец (без проверки ошибок):

HWND hwnd = (HWND)0x00310E3A;
char szBuf[2048];
LONG lResult;

lResult = SendMessage( hwnd, WM_GETTEXT, sizeof( szBuf ) / sizeof( szBuf[0] ), (LPARAM)szBuf );
printf( "Copied %d characters.  Contents: %s\n", lResult, szBuf );

я использовал " Spy++", чтобы получить дескриптор окна текстового поля, которое оказалось лежащим вокруг.

Что касается защиты ваших собственных текстовых полей от такой проверки, вы всегда можете подклассировать свое текстовое поле (см. "SetWindowLong" с параметром" GWL_WNDPROC "для параметра" nIndex") и выполнить специальную обработку сообщения "WM_GETTEXT" для убедитесь, что обслуживаются только запросы одного и того же процесса.


хорошо, я кое-что понял.

начальная точка теперь точно знает дескриптор окна, мы знаем только частичный заголовок окна, поэтому первое, что нужно сделать, это найти это главное окно:

...
EnumWindows((WNDENUMPROC)on_enumwindow_cb, 0);
...

, который перебирает все окна на рабочем столе. Он делает обратный вызов с каждым из этих дескрипторов окна:

BOOL CALLBACK on_enumwindow_cb(HWND hwndWindow, LPARAM lParam) {
    TCHAR wsTitle[2048];
    LRESULT result;
result = SendMessage(hwndWindow, WM_GETTEXT, (WPARAM) 2048, (LPARAM) wsTitle);
    ...

и с помощью wstitle и little regex magic, мы можем найти окно, которое мы хотим.

С помощью вышеупомянутого Spy++ я мог бы выяснить имя класса поля редактирования текста и использовать его, чтобы найти нужное поле в hwndWindow:

hwndEdit = FindWindowEx(hwndWindow, NULL, L"RichEdit20W", NULL);

и затем мы можем прочитать текст из этого поля:

result = SendMessage(hwndEdit, WM_GETTEXT, (WPARAM) 4096, (LPARAM) wsText);

Я надеюсь, что это поможет любому, кто борется с той же проблемой!


посмотреть аутохотки-AutoHotkey. Если вам нужен API для вашего приложения, посмотрите на их источники. Чтобы предотвратить это, используйте пользовательский виджет вместо WinForms, MFC или Win32 API. Это не является надежным, но помогает.


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


Да, это возможно многими способами (один из способов-использовать WinAPI GetWindow и GetWindowText).

сначала получите дескриптор текстового поля, из которого вы хотите получить текст (используя FindWindow, EnumChildWindows и другие API), затем:

старый VB6-codeexample, объявление API:

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long  
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long  

код для извлечения текста:

Dim MyStr As String
MyStr = String(GetWindowTextLength(TextBoxHandle) + 1, Chr$(0))
GetWindowText TextBoxHandle, MyStr, Len(MyStr)
MsgBox MyStr

вы также можете получить текст из элемента управления richedit с сообщением EM_GETTEXTRANGE, но он работает только в том же процессе, в котором был создан элемент управления.


HWND FindWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName
);

http://msdn.microsoft.com/en-us/library/ms633499.aspx