Чтение из текстового поля в окне другого приложения - PullRequest
16 голосов
/ 09 декабря 2008

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

Если это возможно, есть ли способ «защитить» ваше приложение от его предотвращения?

РЕДАКТИРОВАТЬ: три первых ответа, кажется, о получении заголовка окна другого приложения, а не конкретного поля ввода текста в этом окне.

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

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

Завершено! См. Мой ответ ниже для получения инструкций по C ++.

Ответы [ 7 ]

14 голосов
/ 11 декабря 2008

Для чтения текстового содержимого из текстового поля другого приложения вам нужно каким-то образом получить дескриптор окна элемента управления этого текстового поля. В зависимости от того, как спроектирован пользовательский интерфейс вашего приложения (если он имеет пользовательский интерфейс), есть несколько разных способов, которые вы можете использовать для получения этого дескриптора. Вы можете использовать «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» "сообщение, чтобы гарантировать, что только запросы от того же самого процесса обслуживаются.

6 голосов
/ 12 декабря 2008

ОК, я кое-что понял.

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

...
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 и немного магии регулярных выражений, мы можем найти желаемое окно.

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

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

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

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

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

1 голос
/ 09 декабря 2008

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

0 голосов
/ 13 декабря 2008

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

0 голосов
/ 09 декабря 2008

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

0 голосов
/ 09 декабря 2008
HWND FindWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName
);

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

0 голосов
/ 09 декабря 2008

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

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

Старый пример VB6-кода, объявление 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
...