Текст их чужого окна

Тема в разделе "WASM.WIN32", создана пользователем QuAzI, 25 дек 2011.

  1. QuAzI

    QuAzI New Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    26
    Адрес:
    Belarus
    Доброго дня.
    Пишу не на ассемблере, но т.к. фаны ЯПВУ ничего толком не подсказали, может тут найдётся помощь.
    Есть задачка по нажатию горячей кнопки выдёргивать текст из чужого приложения (редактируемый контрол). По всем описаниям или через GetWindowText() или SendMessage( handle, GETTEXT, len, LPARAM((LPTSTR)buff));
    Беды собственно две
    1) В большинстве окон вместо текста контрола получаю заголовок окна. А нужно именно содержимое активного контрола.
    2) Как правильно перебрасывать к себе большие тексты? malloc/free кажется не совсем красивым решением, в том же MSDN написано по крайней мере для RichEdit создавать EditStreamCallback для крупных текстов. А для остальных элементов?
     
  2. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    QuAzI
    Формально GetWindowText не годится. В действительности - иногда работает, но не со всеми контролами, и ещё более не со всеми - так, как хотелось бы. Поэтому - только WM_GETTEXT.

    Я это делал вот таким колдунством
    Код (Text):
    1.          found_wnd:=GetForegroundWindow;
    2.          c_tid:=GetCurrentThreadId;
    3.          t_tid:=GetWindowThreadProcessId(found_wnd,nil);
    4.          if AttachThreadInput(t_tid,c_tid,True) then
    5.           begin
    6.            found_wnd:=GetFocus; // ВОТ СЮДА МЫ ЗАСУНУЛИ ИСКОМЫЙ ХЭНДЛ
    7.            AttachThreadInput(t_tid,c_tid,False);
    8.           end//if AttachThreadInput...
    WM_GETTEXTLENGTH-выделить буфер-WM_GETTEXT. Всё. Есть, правда, маловероятная ситуация, когда между запросом длины текста и собственно текста текст успеет поменяться.
     
  3. QuAzI

    QuAzI New Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    26
    Адрес:
    Belarus
    Пофиг что текст успеет поменяться, размер буфера передаётся в параметрах. Максимум - будет скопировано меньше текста, чем стало.
    Ваше колдунство на Qt у меня выглядит так
    Код (Text):
    1.             HWND active = GetForegroundWindow();
    2.             DWORD tid = GetWindowThreadProcessId(active, 0);
    3.             DWORD cid = GetCurrentThreadId();
    4.             AttachThreadInput(cid, tid, true);
    5.             HWND focused = GetFocus();
    6.  
    7.             DWORD res = 0;
    8.             TCHAR *buff;
    9.  
    10.                 DWORD len = SendMessage( focused, WM_GETTEXTLENGTH, 0, 0);
    11.                 if (len<=65536)
    12.                 {
    13.                     buff = (TCHAR *) malloc(len*2);
    14.                     res = SendMessage( focused,
    15.                                 WM_GETTEXT,
    16.                                 len,
    17.                                 LPARAM((LPTSTR)buff));
    18.                 }
    19.  
    20. if (res!=0)
    21.               editor->setText(QString::fromUtf16((ushort*)buff));
    22.  
    23.             free(buff);
    24.             AttachThreadInput(cid, tid, false);
    И вот что я получаю из эдитов
    Блокнот, Texter2, консоль Total Commander, Dev C++ - всё отлично.
    MS Office - текст "Документ Microsoft Word"
    Qt - Текст заголовка окна
    QIP - пусто
    FlameRobin - текст "stcwindow"
    Opera - Заголовок текущего таба
    Firefox - Текст заголовка окна
    DrWeb - вообще китайская бНОПНЯ, реальные иероглифы, причём они меняются в зависимости от текста введённого в тестовой строке (проверял на списке исключений)
    Кстати да, буффер у меня увеличен вдвое относительно количества знаков из рассчёта на двухбайтовую кодировку. Иначе наблюдались вылеты.
     
  4. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    А из owner-draw контролов вообще ничего осмысленного при всём желании не получить, разве что перехватом функций рисования, но даже и это не везде сработает. Ну или делать снимок окна и заряжать в распознавалку текста.
     
  5. QuAzI

    QuAzI New Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    26
    Адрес:
    Belarus
    Ну как-то же работают все эти Punto Switcher, переводчики и прочая гадость
     
  6. CyberManiac

    CyberManiac New Member

    Публикаций:
    0
    Регистрация:
    2 сен 2003
    Сообщения:
    2.473
    Адрес:
    Russia
    QuAzI
    Да очень просто он работает: мониторит все нажатые кнопки, а потом в нужный момент имитирует много нажатий на backspace, переключает раскладку и имитирует ввод последнего слова. Про переводчики точно не скажу, но вероятнее всего сохраняют содержимое clipboard, жмут Ctrl-C, переводят текст в буфере и восстанавливают clipboard.
     
  7. QuAzI

    QuAzI New Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    26
    Адрес:
    Belarus
    изврат
     
  8. QuAzI

    QuAzI New Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    26
    Адрес:
    Belarus
    Ну сделал я этот изврат. Когда начинает отрабатывать keybd_event, хук начинает ловить сам себя (это ведь он подменяет старый текст). К тому же приложения посложнее блокнота (аки офис, Qt, браузеры) вообще не совсем понятно как отрабатывают, хук не срабатывает вообще на них.
    Собственно продолжение сабжа с кусками кода http://www.prog.org.ru/index.php?topic=20443.msg140303;topicseen#new
     
  9. QuAzI

    QuAzI New Member

    Публикаций:
    0
    Регистрация:
    13 дек 2005
    Сообщения:
    26
    Адрес:
    Belarus
    Какая-то нестырковочка
    http://msdn.microsoft.com/en-us/library/windows/desktop/ms644974(v=vs.85).aspx
    Код (Text):
    1. LRESULT WINAPI CallNextHookEx(
    2.   __in_opt  HHOOK hhk,
    3.   __in      int nCode,
    4.   __in      WPARAM wParam,
    5.   __in      LPARAM lParam
    6. );
    7.  
    8. hhk [in, optional]
    9.  
    10.     Type: HHOOK
    11.  
    12.     This parameter is ignored.
    в то время как у Iczelion'a http://wasm.ru/article.php?article=1001024
    Код (Text):
    1.        CallNextHookEx proto hHook:DWORD, nCode:DWORD, wParam:DWORD,
    2.        lParam:DWORD
    3.  
    4.     * hHook - хэндл вашего хука. Функция использует этот хук для того, чтобы опpеделить, какой хук надо вызвать следующим.
    Так его надо задавать или нет?