Доброго дня. Пишу не на ассемблере, но т.к. фаны ЯПВУ ничего толком не подсказали, может тут найдётся помощь. Есть задачка по нажатию горячей кнопки выдёргивать текст из чужого приложения (редактируемый контрол). По всем описаниям или через GetWindowText() или SendMessage( handle, GETTEXT, len, LPARAM((LPTSTR)buff)); Беды собственно две 1) В большинстве окон вместо текста контрола получаю заголовок окна. А нужно именно содержимое активного контрола. 2) Как правильно перебрасывать к себе большие тексты? malloc/free кажется не совсем красивым решением, в том же MSDN написано по крайней мере для RichEdit создавать EditStreamCallback для крупных текстов. А для остальных элементов?
QuAzI Формально GetWindowText не годится. В действительности - иногда работает, но не со всеми контролами, и ещё более не со всеми - так, как хотелось бы. Поэтому - только WM_GETTEXT. Я это делал вот таким колдунством Код (Text): found_wnd:=GetForegroundWindow; c_tid:=GetCurrentThreadId; t_tid:=GetWindowThreadProcessId(found_wnd,nil); if AttachThreadInput(t_tid,c_tid,True) then begin found_wnd:=GetFocus; // ВОТ СЮДА МЫ ЗАСУНУЛИ ИСКОМЫЙ ХЭНДЛ AttachThreadInput(t_tid,c_tid,False); end//if AttachThreadInput... WM_GETTEXTLENGTH-выделить буфер-WM_GETTEXT. Всё. Есть, правда, маловероятная ситуация, когда между запросом длины текста и собственно текста текст успеет поменяться.
Пофиг что текст успеет поменяться, размер буфера передаётся в параметрах. Максимум - будет скопировано меньше текста, чем стало. Ваше колдунство на Qt у меня выглядит так Код (Text): HWND active = GetForegroundWindow(); DWORD tid = GetWindowThreadProcessId(active, 0); DWORD cid = GetCurrentThreadId(); AttachThreadInput(cid, tid, true); HWND focused = GetFocus(); DWORD res = 0; TCHAR *buff; DWORD len = SendMessage( focused, WM_GETTEXTLENGTH, 0, 0); if (len<=65536) { buff = (TCHAR *) malloc(len*2); res = SendMessage( focused, WM_GETTEXT, len, LPARAM((LPTSTR)buff)); } if (res!=0) editor->setText(QString::fromUtf16((ushort*)buff)); free(buff); AttachThreadInput(cid, tid, false); И вот что я получаю из эдитов Блокнот, Texter2, консоль Total Commander, Dev C++ - всё отлично. MS Office - текст "Документ Microsoft Word" Qt - Текст заголовка окна QIP - пусто FlameRobin - текст "stcwindow" Opera - Заголовок текущего таба Firefox - Текст заголовка окна DrWeb - вообще китайская бНОПНЯ, реальные иероглифы, причём они меняются в зависимости от текста введённого в тестовой строке (проверял на списке исключений) Кстати да, буффер у меня увеличен вдвое относительно количества знаков из рассчёта на двухбайтовую кодировку. Иначе наблюдались вылеты.
А из owner-draw контролов вообще ничего осмысленного при всём желании не получить, разве что перехватом функций рисования, но даже и это не везде сработает. Ну или делать снимок окна и заряжать в распознавалку текста.
QuAzI Да очень просто он работает: мониторит все нажатые кнопки, а потом в нужный момент имитирует много нажатий на backspace, переключает раскладку и имитирует ввод последнего слова. Про переводчики точно не скажу, но вероятнее всего сохраняют содержимое clipboard, жмут Ctrl-C, переводят текст в буфере и восстанавливают clipboard.
Ну сделал я этот изврат. Когда начинает отрабатывать keybd_event, хук начинает ловить сам себя (это ведь он подменяет старый текст). К тому же приложения посложнее блокнота (аки офис, Qt, браузеры) вообще не совсем понятно как отрабатывают, хук не срабатывает вообще на них. Собственно продолжение сабжа с кусками кода http://www.prog.org.ru/index.php?topic=20443.msg140303;topicseen#new
Какая-то нестырковочка http://msdn.microsoft.com/en-us/library/windows/desktop/ms644974(v=vs.85).aspx Код (Text): LRESULT WINAPI CallNextHookEx( __in_opt HHOOK hhk, __in int nCode, __in WPARAM wParam, __in LPARAM lParam ); hhk [in, optional] Type: HHOOK This parameter is ignored. в то время как у Iczelion'a http://wasm.ru/article.php?article=1001024 Код (Text): CallNextHookEx proto hHook:DWORD, nCode:DWORD, wParam:DWORD, lParam:DWORD * hHook - хэндл вашего хука. Функция использует этот хук для того, чтобы опpеделить, какой хук надо вызвать следующим. Так его надо задавать или нет?