Подтвердить что ты не робот

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

Хорошо, я немного понял это.

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

...
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);

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

Ответ 3

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

Ответ 4

Да, это возможно во многих отношениях (один способ - использовать 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

Ответ 5

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

Ответ 6

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