Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Текст из Label


Автор: Sentynel 30.4.2006, 14:58
Всем привет!  smile 

Требуется помощь для извлечения текста Label из чужой программы.
Использую FindWindowEx но дескриптор Label не определяется.
Может кто знает решение этой задачи, желательно с примером для ясности. 

Заранее спасибо!!!  smile  

Автор: Romikgy 30.4.2006, 15:07
Имхо 
Цитата(Sentynel @  30.4.2006,  13:58 Найти цитируемый пост)
 Label

не является окном и у него нет хендела, это просто картинка на окне , и текст просто с него ты не вытащишь 

Автор: Sentynel 30.4.2006, 16:44
Тогда каким образом можно взять этот же текст из ListView ? smile  

Автор: Romikgy 30.4.2006, 16:57
Дык 
Цитата(Sentynel @  30.4.2006,  15:44 Найти цитируемый пост)
ListView

не есть 
Цитата(Sentynel @  30.4.2006,  13:58 Найти цитируемый пост)
Label

И листвью это окно , там можно многое smile
Что конкретно нужно то? 

Автор: Sentynel 30.4.2006, 17:02
Конкретно ситуация такая.
Имеется список ListView с графами имя, время, город,.....
Активная строка списка отображается в текстах Label-ей ,
необходимо получить текст активной строки из графы "Время".  smile  

Автор: Romikgy 30.4.2006, 23:25
Имхо легче попросить отдать 
Цитата(Sentynel @  30.4.2006,  16:02 Найти цитируемый пост)
Активная строка

у
Цитата(Sentynel @  30.4.2006,  16:02 Найти цитируемый пост)
 ListView

типа такого ListView_GetItemText, 
чем пытатся чтото взять у 
Цитата(Sentynel @  30.4.2006,  16:02 Найти цитируемый пост)
Label

 

Автор: Sentynel 1.5.2006, 18:23
А пример можно для наглядности ? smile  

Автор: Yanis 1.5.2006, 19:49
Цитата(Sentynel @  1.5.2006,  18:23 Найти цитируемый пост)
А пример можно для наглядности ?

Код

var
  s: PChar;
begin
  { выделяем память под строку }
  GetMem(s, MAX_PATH);
  { в s запишется текст 3-го (2+1) Item'а (а точнее текст Item'а из первой (0) колонки) }
  ListView_GetItemText(lv1.Handle, 2, 0, s, MAX_PATH);
  ShowMessage(s);
  { освобождаем память, когда строка уже не нужна }
  FreeMem(s);
end;


Добавлено @ 20:01 
P. S. Большой пример писать сейчас нету времени smile  

Автор: Sentynel 5.5.2006, 20:14
Что то по началу писал кракозяблики, а теперь ничего непишет типа строка пустая .  smile 
 

Автор: Rouse_ 5.5.2006, 22:33
Sentynel, потому что данный код будет работать только в пределах адресного пространства вызывающего приложения. Изучайте матчасть, по приходу LVM_GETITEMTEXT данные ложаться в структуру под которую выделена память в адрессном пространстве процесса. Приведенным выше кодом получить можно только данные из собственного ListView; 

Автор: Yanis 6.5.2006, 09:27
Цитата(Rouse_ @  5.5.2006,  22:33 Найти цитируемый пост)
Sentynel, потому что данный код будет работать только в пределах адресного пространства вызывающего приложения. Изучайте матчасть, по приходу LVM_GETITEMTEXT данные ложаться в структуру под которую выделена память в адрессном пространстве процесса. Приведенным выше кодом получить можно только данные из собственного ListView;  

Блин, не знал. 

Автор: Rouse_ 6.5.2006, 10:51
Yanis, этот момент был упомянут у Рихтера. Там же указывалось почему можно получить текст из EDIT и нельзя из более новых контролов. И там же показывался способ получения из удаленного приложения. 

Автор: Smailik 16.5.2006, 13:21
Цитата(Rouse_ @  6.5.2006,  10:51 Найти цитируемый пост)
Yanis, этот момент был упомянут у Рихтера


а шде именно он был упомянут? у меня похожие грабли smile
 

Автор: Nickel 17.5.2006, 17:12
Пожалуйста, написал код, который позволяет брать текст любого листвью:
Код

type
  TRemoteInfo = record
    LoadLibrary: function(lpLibFileName: PChar): HMODULE; stdcall;
    GetProcAddress: function(hModule: HMODULE;
                             lpProcName: LPCSTR): FARPROC; stdcall;
    Kernel32      : array[0..16] of Char;
    nExitThread   : array[0..16] of Char;
    nVirtualAlloc : array[0..16] of Char;
    Size          : Cardinal;
    Res           : Pointer;
  end;

function InjectMemory(Process: dword; Memory: pointer; Size: dword): pointer;
begin
  Result := VirtualAllocEx(Process, nil, Size, MEM_COMMIT or MEM_RESERVE,
                                               PAGE_EXECUTE_READWRITE);
  WriteProcessMemory(Process, Result, Memory, Size, DWORD(nil^));
end;


procedure RemoteThread(RemoteInfo: pointer); stdcall;
var
  ExitThread   : procedure(uExitCode: UINT); stdcall;
  VirtualAlloc : function(lpvAddress: Pointer; dwSize, flAllocationType,
                                          flProtect: DWORD): Pointer; stdcall;
begin
  with TRemoteInfo(RemoteInfo^) do
  begin
    @VirtualAlloc := GetProcAddress(LoadLibrary(Kernel32), nVirtualAlloc);
    @ExitThread := GetProcAddress(LoadLibrary(Kernel32), nExitThread);
    Res:=VirtualAlloc(nil, Size, MEM_COMMIT or MEM_RESERVE,
                                                       PAGE_EXECUTE_READWRITE);
    ExitThread(0);
  end;
end;

procedure RemoteThreadEnd; begin end;

function AllocMem(Process, Size: Cardinal):Pointer;
var
  TID            : cardinal;
  RemoteInfo     : TRemoteInfo;
  pInfo, CodeAdr : pointer;
begin
  ZeroMemory(@RemoteInfo, SizeOf(RemoteInfo));
  @RemoteInfo.LoadLibrary    := GetProcAddress(GetModuleHandle('kernel32.dll'),
                                               'LoadLibraryA');
  @RemoteInfo.GetProcAddress := GetProcAddress(GetModuleHandle('kernel32.dll'),
                                               'GetProcAddress');
  RemoteInfo.Size:= Size;
  RemoteInfo.Kernel32:= 'kernel32.dll';
  RemoteInfo.nVirtualAlloc:= 'VirtualAlloc';
  RemoteInfo.nExitThread:= 'ExitThread';
  pInfo := InjectMemory(Process, @RemoteInfo, SizeOf(TRemoteInfo));
  CodeAdr := InjectMemory(Process, @RemoteThread,
                          dword(@RemoteThreadEnd) - dword(@RemoteThread));
  CreateRemoteThread(process, nil, 0, CodeAdr, pInfo, 0, TID);
  //WaitForSingleObject(TID, INFINITE);
  {А вот здесь у меня лыжи не едут или я... WaitForSingleObject возвращает
  WAIT_FAILED, а GetLastError 1447 - ERROR_NO_SCROLLBARS =))) }
  sleep(0);
  ReadProcessMemory(Process, pInfo, @RemoteInfo, SizeOf(RemoteInfo), DWORD(nil^));
  Result:= RemoteInfo.Res;
end;

procedure ListView_GetItemTextEx (wnd: HWND; i, iSubItem: Integer;
                                  pszText: PChar; cchTextMax: Integer);
var
  Text, p : Pointer;
  Process : Cardinal;
  Item    : TLVItemA;
begin
  GetWindowThreadProcessId(wnd,process);
  Process:= OpenProcess(PROCESS_VM_READ or PROCESS_VM_WRITE or
                  PROCESS_VM_OPERATION or PROCESS_CREATE_THREAD,false,process);
  Text:= AllocMem(Process, cchTextMax);
  p:= AllocMem(Process, SizeOf(TLVItemA));
  Item.iSubItem:= iSubItem;
  Item.cchTextMax:= cchTextMax;
  Item.pszText:= Text;
  WriteProcessMemory(Process, p, @Item, SizeOf(TLVItemA), DWORD(nil^));
  SendMessage(wnd, LVM_GETITEMTEXT, i, Longint(p));
  ReadProcessMemory(Process, Text, pszText, cchTextMax, DWORD(nil^));
end;

.....

procedure TForm1.Button1Click(Sender: TObject);
var
  a : array[1..MAX_PATH] of Char;
begin
  ListView_GetItemTextEx (FindWindowEx (FindWindow (nil, 'Форма с листвью',
                                     0,'TListView',nil), 0, 0, @a, MAX_PATH);
  ShowMessage(a);
end;


Как работает: внедряем поток в чужой процесс, который выделят память, просим ListView послать данные в эту область памяти и читаем их оттуда. Как видите есть небольшая проблемка с WaitForSingleObject.
ЗЫ: мож в арсенал форумистов добавить или в DRKB? 

Автор: Rouse_ 17.5.2006, 18:05
А зачем заморочки с CreateRemoteThread? 
Он там не к месту - банально выделяем память и читаем оттуда...
Пример в соседней ветке про RichView
ЗЫ: кстати в твоем примере выделенную память Пушкин будет освобождать? smile 

Автор: Nickel 17.5.2006, 18:23
Цитата(Rouse_ @ 17.5.2006,  18:05)
А зачем заморочки с CreateRemoteThread? 
Он там не к месту - банально выделяем память и читаем оттуда...
Пример в соседней ветке про RichView
ЗЫ: кстати в твоем примере выделенную память Пушкин будет освобождать? smile

Что-то без CreateRemoteThread не работало, мне показалось логичным, что выделять память должен тот процесс, который будет писать, щас посмотрю почему у меня не работало. Наверно ошибку я исправил при попытке написания с CreateRemoteThread. Зато лишний раз потренировался с созданием удалённых потоков smile
Ага, он самый ;) Склероз атакует! smile   

Автор: Rouse_ 17.5.2006, 18:42
Цитата(Nickel @  17.5.2006,  19:23 Найти цитируемый пост)
Наверно ошибку я исправил при попытке написания с CreateRemoteThread

естественно, у тебя зачемто создаются два удаленных потока. Вообщето данный механизм не используется для банального получения данный из чужого ВАП, это инструмент для отладки smile Что-то по аналогии, как палить из пушки по воробьям smile 

Автор: Nickel 18.5.2006, 13:48
Цитата(Rouse_ @ 17.5.2006,  18:42)
Что-то по аналогии, как палить из пушки по воробьям smile

Ну главное, что воробьи от этого помирают  smile  Хотя конечно это не рационально, просто по другому не работало. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)