Конференция "WinAPI" » прочесть что написано в Label другого приложния [D7, WinXP]
 
  • ivanoff (25.08.09 16:06) [0]
    получаю так

    SendMessage(H, WM_GETTEXT, 256, LParam(@S[1]));



    ... но только с Edit, Button, Panel, ...
    как посмотреть что в Label написано, по его координатам
  • Медвежонок Пятачок © (25.08.09 16:10) [1]
    лабел не оконный, так что остается только ocr
  • Сергей М. © (25.08.09 16:48) [2]

    > остается только ocr


    Или внедрить туда свой код, перехватывающий TextOut()
  • ivanoff (25.08.09 17:11) [3]

    > Сергей М. ©   (25.08.09 16:48) [2]


    уже легче :)

    .... можно по подробней?
  • Сергей М. © (25.08.09 17:24) [4]
  • Игорь © (25.08.09 18:47) [5]
  • ivanoff (26.08.09 04:13) [6]
    вроде то, даже обрадовался

    переделал так
    function MyGetWndText(Wnd: HWND): PChar; stdcall; export;
    var
     Point: TPoint;
     Buffer: array[0..256] of char;
    begin
     GlobalData^.Wnd := Wnd;
     GlobalData^.cancapture := True;
     Point:= Mouse.CursorPos;

     Windows.ScreenToClient(Wnd, Point);

     if (Point.x < 0) or (Point.y < 0) then
       GetWindowText(Wnd, Buffer, SizeOf(Buffer) - 1);

     Result := Buffer;
    end;

    ...
    exports
     MyGetWndText name 'MyGetWndText';
    ...



    вызываю так

    ...
    function MyGetWndText(Wnd: HWND): PChar; stdcall; external 'TextCapture.dll';
    ...
    var
     Wnd: HWND;
    begin
     Wnd := WindowFromPoint(Mouse.CursorPos);
     Label1.Caption := MyGetWndText(Wnd);
    end;



    чтоб функция техт возвращала

    компилятор ругается, ОС плясать начинает
    Access violation at address 099CCCBE in module 'TextCapture.dll'. Read of address 00000000.

    просьба ткнуть носом - с dll полный профан я
  • Leonid Troyanovsky © (26.08.09 08:41) [7]

    > ivanoff   (26.08.09 04:13) [6]

    > вроде то, даже обрадовался

    Откуда это? По ссылке [5]? :(

    Во-первых, GetWindowText работает с окнами, TLabel окна не имеет.
    Во-вторых,  PChar должен указывать на буфер, распределенный
    в приложении, например, buf: array [0..255] of Char.
    И, в-третьих, при таких базовых знаниях можно смело полагать,
    что получить текст из чужого TLabel невозможно.

    --
    Regards, LVT.
  • Сергей М. © (26.08.09 09:17) [8]
    Sleep(INFINITE) - это сильно.
  • Leonid Troyanovsky © (26.08.09 09:43) [9]

    > Сергей М. ©   (26.08.09 09:17) [8]

    > Sleep(INFINITE) - это сильно.

    Поэзия :)

    Это тоже из [5]?

    --
    Regards, LVT.
  • Сергей М. © (26.08.09 12:19) [10]

    > Это тоже из [5]?


    Угу. Шедевр)
    Заглянул из любопытства, а там .. Черт ногу сломит как там понахреноверчено ..
  • ivanoff (26.08.09 13:22) [11]

    > > вроде то, даже обрадовался
    >
    > Откуда это? По ссылке [5]? :(
    >
    > Во-первых, GetWindowText работает с окнами, TLabel окна
    > не имеет.


    а ведь Label-то видит - вот и обрадовался, есть от чего плясать, тока там много всего разбираюсь чего надо, чего не надо .... но как говорил с DLL не работал

    - а я и не говорил что в этой области знания у меня большие
    - чтаю, просвесщаюсь, но пока недопер - вот и прошу чтоб нормальным а не литературным языком объяснили в чем трабл или как правельно делать надо
  • Leonid Troyanovsky © (26.08.09 13:57) [12]

    > ivanoff   (26.08.09 13:22) [11]

    > а ведь Label-то видит

    Значит, это не TLabel, а TStaticText. Класс окна выяснял?

    Ну, или там не GetWindowText.
    Хотя, исходный образчик, судя по всему, для дела не пригоден.

    > не литературным языком объяснили в чем трабл

    Нелитературным нельзя, забанят.

    > или как правельно делать надо

    Конкретно спрашивай, что осталось непонятым.

    --
    Regards, LVT.
  • Сергей М. © (26.08.09 13:59) [13]

    > а ведь Label-то видит


    Что значит "видит" ?
    Прошу чтоб нормальным а не литературным языком объяснили)

    И еще прошу,  чтоб нормальным а не литературным языком объяснили, зачем тут нужен глобальный хук, если известен конкретный процесс и конкретное окно с конкретным лейблом)
  • ivanoff (26.08.09 14:52) [14]
    есть прога которая принимает некоторые данные от своей серверной части в зашифрованном виде и визуализирует посредством Label

    задача получить и использовать инфу которую ставят в те самые Label

    "они" не хотят делится этой инфой поэтому надо выдергиватить из их проги


    > зачем тут нужен глобальный хук, если известен конкретный
    > процесс и конкретное окно с конкретным лейблом)

    а мне всеравно как лишь бы данные из Label получить

    > Что значит "видит" ?

    я сделал тестовую программу положил там Label
    ... так как брал текст из TEdit, к примеру из TLabel не берет
    ... с примером из [5] - берет


    > Конкретно спрашивай, что осталось непонятым.

    так как тока разбираюсь с DLL не пойму че не так испаравил дабы по [5] техт получить а не рисовать сверху

    цитата из нета
    "Выдрать текст из Label'a можно, но для этого придется перехватывать TextOutW, так как это так сказать последняя инстанция, когда текст ещё существует в своем состоянии текста"
  • Сергей М. © (26.08.09 15:44) [15]

    > ivanoff   (26.08.09 14:52) [14]
    >
    > есть прога


    Дельфийская ? Ты уверен в этом ? Ты уверен что это именно TLabel, а не какой-либо иного класса контрол ?


    > мне всеравно как лишь бы данные из Label получить


    Пример, который ты мусолишь, устанавливает хук во все GUI-процессы.
    Не исключено (и оч даже вероятно), что среди этих процессов может оказаться более чем один процесс с контролом интересующего класса.
    И тут к тебе возникает вопрос: как ты намерен идентифицировать нужный тебе процесс, если ты установилл глоб.хук, поскольку тебе "всеравно" ?
  • ivanoff (26.08.09 16:28) [16]

    > Дельфийская ? Ты уверен в этом ? Ты уверен что это именно
    > TLabel


    CBuilder


    > "всеравно"

    важно получить инфу с Label-а конкретного окна (от которого знаю заголовок) который находится на панелке (Panel), как - не важно главное чтоб правельно

    ...не заню с какой стороны подойти, вот и кидаюсь из стороны в сторону и мучаю всех вопросами
  • Сергей М. © (26.08.09 17:32) [17]
    Отсюда следует, что следует ставить локальный хук в процесс, создавший этот лейбл.


    > не заню с какой стороны подойти


    У тебя есть заголовок окна, в котором отрисовывается искомый лейбл.
    Для простоты положим, что текст этого заголовка уникален среди заголовков всех окон тек.десктопа.
    1. Ищешь хэндл окна по заданному заголовку.
    2. Получаешь ID треда, создавшего окно - см. GetWindowThreadProcessId
    3. Устанавливаешь локальный (!!!) хук на этот тред - см. SetWindowsHookEx, тип хука выбираешь, например, WH_GETMESSAGE
    4. Посылаешь окну сообщение WM_NULL - см. PostMessage()
    При этом в АП целевого процесса будет внедрена DLL, указанная в п.3
    В процедуре инициализации этой DLL перехватываешь ф-цию TexOut (до кучи и все прочие, выводящие текст, фигурирующие в [5])
    5. В теле подмененных ф-ций извещаешь любым удобным способом (например, SendMessage) свой процесс о том, что целевой процесс для вывода некоего текста вызвал такую-то перехваченную тобой ф-цию с такими-то параметрами, в частности с параметрами-координатами, с которыми выводится текст. Остается только сравнить координаты с теми, в которых расположен искомый лейбл - и все, задача решена.
  • Rouse_ © (26.08.09 17:53) [18]

    > так как тока разбираюсь с DLL не пойму че не так испаравил
    > дабы по [5] техт получить а не рисовать сверху

    Ну во первых заменить wParam: word; на правильное значение, во вторых убрать ненуный слип, втретьих убрать мемлик GDI ресурсов, разрушая в нужное время dtc, , в четвертых начать таки возвращать в MessageProc правильный результат, а не ноль, ну и заменить процедуры отрисовки
             dtc.Rectangle(300, 3, 900, 20);
             dtc.TextOut(305, 5, Copy(Str, 0, Count));



    На отправку строки Str своему приложению
  • Сергей М. © (26.08.09 21:00) [19]
    Сейчас последует "Вы, ...., не умничайте - вы код давайте !!"
  • ivanoff (27.08.09 19:52) [20]

    > Сергей М. ©   (26.08.09 21:00) [19]
    > Сейчас последует "Вы, ...., не умничайте - вы код давайте
    > !!"


    ну зачем же так сурово ...
    ... если не трудно ... код дайте :)
    ... Спасибо

    а если серъезно
    сделал так (на базе [5])
    ...
    type
     TWM_TextCapture = record
       Text: PAnsiChar;
     end;

    const
     WM_TextCapture = WM_USER + 1;

    var
     processWnd: HWND;
     WMTextCapture: TWM_TextCapture;

    ...
    procedure GetWndText(Wnd, SourceWnd: HWND); stdcall; export;
    ...
    processWmd := SourceWnd;
    ...



    добавил в для проверки
    function MessageProc(code: integer; wParam: word;
     lParam: longint): longint; stdcall;
    ...
     WMTextCapture.Text := TimeToStr(Time);
     SendMessage(processWnd, WM_TextCapture, 0, 0);
    ...


    -----------------------------------------------------------

    в тестовой программе ловлю так
    ...
     private
       procedure WMTextCapture(var Msg: TWM_TextCapture); message WM_TextCapture;
    ...
    procedure GetWndText(Wnd, SourceWnd: HWND); stdcall; external 'TxCapture.dll';
    ...
    procedure TForm1.prWMsd(var Msg: TWM_TextCapture);
    begin
     Label1.Caption := TimeToStr(Time);

         //так сообщение принимаю - ОК
     Label1.Caption := Msg.Text;

                    //Так - Error
    end;



    где ошибаюсь?
    как из DLL  послать текст в мое приложение :(
  • Сергей М. © (27.08.09 20:35) [21]

    > ну зачем же так сурово


    А как же иначе, если это уже стало печальной традицией ?


    > сделал так (на базе [5])


    Из [5] тебе нужен только перехват WinAPI-вызовов, о котором идет речь в [17] п.4

    Все остальное в [5] - абсолютно бесполезный хлам.
    Нет никакого резона приспосабливать его к твоей задаче.
  • ivanoff (27.08.09 20:53) [22]

    > А как же иначе, если это уже стало печальной традицией ?

    я хочу научится с этим работать, понять (понятно что на конкретном примере легче) а не просто решить вознишую проблему и забить

    нашел кучу примеров посылки сообсчении из DLL но не втом виде как мне нужно

    и еще
     CallNextHookEx(0, Code, wParam, lparam);

    первый параметр не должен быть идетифицатором Hook-а?


    > Из [5] тебе нужен только перехват WinAPI-вызовов, о котором
    > идет речь в [17] п.4
    >
    > Все остальное в [5] - абсолютно бесполезный хлам.
    > Нет никакого резона приспосабливать его к твоей задаче.


    как говорил с самого начала в первые приходится иметь дело с DLL

    ...для начала хочу добится нужного результата а потом буду ненужное убирать потому как не знаю что там нужное и что не нужное.
      Начал там коментировать как мне казалось ненужное - перестало работать

    Вот и решил для начала принять бы Техт в мое приложение а далее ...

    ----------
    как из DLL  послать текст в мое приложение?
  • Сергей М. © (27.08.09 20:59) [23]

    > как из DLL  послать текст в мое приложение?


    Один из множества возможных вариантов:

    http://www.google.ru/search?hl=ru&client=firefox&rls=org.mozilla%3Aru%3Aofficial&hs=s2N&newwindow=1&q=delphi+wm_copydata&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&lr=&aq=f&oq=
  • rrader © (08.09.09 12:15) [24]
    Чтобы вытащить текст из TLabel, не нужно внедряться и ставить хуки для перехвата, достаточно воспользоваться мощью RTTI. Нужно знать имя (или другой уникальный параметр) метки в коде (можно подсмотреть в DFM), чтобы отфильтровать ее от других. А дальше ReadProcessMemory... Я таким образом вытягиваю информацию из TStringGrid.
  • Сергей М. © (08.09.09 20:20) [25]

    > достаточно воспользоваться мощью RTTI


    Структура RTTI отличается от версии к версии.
    Это раз.

    Что если требуется отслеживать изменения текста контрола ?
    На таймер что ли ставить ReadProcessMemory ?
    Это два.
  • rrader © (09.09.09 04:27) [26]
    >Структура RTTI отличается от версии к версии.

    Со времен D3 до D2010 ничего того, что помешало бы получению данных, не изменилось. Иначе бы я и заикаться не стал на эту тему.

    >Что если требуется отслеживать изменения текста контрола ?
    >На таймер что ли ставить ReadProcessMemory ?

    А что плохого? Это очень быстро.
  • Сергей М. © (09.09.09 08:31) [27]

    > А что плохого?


    Плохое в том, что модификация данных типа string относится к атомарным операциям.
  • rrader © (09.09.09 09:53) [28]
    Не знаю почему, но у меня из головы вылетело, что нереентерабельность VCL может испортить чтение данных из чужого процесса, когда данные меняются. Потому что чтение осуществляется два раза (длина и сама строка), а нас могут вытеснить в любой момент. Я предлагаю на время чтения останавливать обновление данных (способ индивидуален в каждом конкретном случае, но не имеется в виду делать SuspendThread) и после чтения возобновлять.
  • Сергей М. © (09.09.09 10:31) [29]
    Модификация данных типа string не относится к атомарным операциям


    > предлагаю на время чтения останавливать обновление


    И что толку ?
    Все равно это чревато как минимум недостоверным результатом, а как максимум - отказом ReadProcessMemory.
  • rrader © (09.09.09 11:18) [30]
    > И что толку ?

    Скажем так, в некоторых случаях это - вариант. Возвращаясь к теме, я хотел указать именно на получение текста из неменяющегося TLabel.
  • Сергей М. © (09.09.09 12:44) [31]

    > в некоторых случаях это - вариант


    Для этих "некоторых" случаев проще и удобней будет не лезть в дебри RTTI: опять же внедрить свой код, но не для перехвата WinAPI-вызовов, а работающий напрямую с VCL-объектами в процессе-"жертве".
  • rrader © (09.09.09 13:10) [32]
    Ну, допустим, будет у нас в чужом процессе дополнительный поток, работающий напрямую с VCL-объектом. ReadProcessMemory заменяем, образно, говоря, на крышки (^), т.е. получаем доступ к данным напрямую, как в своем процессе. Проблем синхронизации это не решает. Или имеется в виду другой подход?
  • Сергей М. © (09.09.09 13:24) [33]

    > допустим, будет у нас в чужом процессе дополнительный поток


    Зачем дополнительный ?
    Прямо в основном и обращаемся.
    И крышки тут ни причем.
  • AntiZOG (15.09.09 02:12) [34]

    > ivanoff   (25.08.09 16:06)
    >
    > получаю так
    >
    > SendMessage(H, WM_GETTEXT, 256, LParam(@S[1]));
    >
    > ... но только с Edit, Button, Panel, ...
    > как посмотреть что в Label написано, по его координатам


    Самый простой и чаще всего работающий способ:
    - WmPrint окна на котором лежит label, b в качестве канваса указать битмап.
    - потом распознать каким-то простым алгоритмом (можно даже тупо наложением изображений букв).
 
Конференция "WinAPI" » прочесть что написано в Label другого приложния [D7, WinXP]
Есть новые Нет новых   [134434   +28][b:0][p:0.002]