Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 21.06.2013, 14:15
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию Работа с чужим приложением

Доброе время суток уважаемые программисты.
Суть вопроса в следующем:

Есть процедура считывания с чужого листа ListView или syslistview32 в свой TStringGrid
Код:
procedure GetListViewGrid(ALVHandle: HWND; AColumnCount, AItemCount: Integer;
  ADataGrid: TStringGrid);
const
  cchTextMax=255;
var
  hProcess: THandle;
  dwProcessID: DWORD;
  dwWriten: DWORD;
  LVItemCount: Integer;
  i, j, nTextLength: Integer;
  pLVItem: ^LV_ITEM;
  LVItem: LV_ITEM;
  pszText: PChar;
  svText: ShortString;
begin
  if ALVHandle=0 then
    Exit;
  // Получаем количество строк
  LVItemCount := ListView_GetItemCount(ALVHandle);
  if AItemCount>LVItemCount then
    Exit;
  if AItemCount>0 then
    LVItemCount := AItemCount;
  // Получаем ID процесса, которому принадлежит найденное окно
  dwProcessID := 0;
  GetWindowThreadProcessId(ALVHandle, @dwProcessID);
  if dwProcessID=0 then
    ExitProcess(GetLastError);
  // Открываем процесс
  //hProcess := 0;
  hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, dwProcessID);
  if hProcess=0 then
    ExitProcess(GetLastError);
  // Выделяем в нем память под текстовый буффер
  pszText := VirtualAllocEx(hProcess, nil, cchTextMax, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
  // Выделяем в нем память под структуру LVITEM
  pLVItem := VirtualAllocEx(hProcess, nil, SizeOf(LV_ITEM), MEM_COMMIT or MEM_TOP_DOWN,
    PAGE_READWRITE);

  // Устанавливаем колич строк и столбцов в TStringGrid
  ADataGrid.RowCount := LVItemCount;
  ADataGrid.ColCount := AColumnCount;

  // Заполняем структуру
  ZeroMemory(@LVItem, SizeOf(LV_ITEM));
  LVItem.Mask := LVIF_TEXT;
  LVItem.pszText := pszText;
  LVItem.cchTextMax := cchTextMax;

  // Считываем строки
  for i := 0 to LVItemCount do
  begin
    LVItem.iSubItem := 0;
    // Пишем ее в память удаленного процесса
    if not WriteProcessMemory(hProcess, pLVItem, @LVItem, SizeOf(LV_ITEM), dwWriten) then
      Exit;
    nTextLength := sendMessage(ALVHandle, LVM_GETITEMTEXT, i, Integer(pLVItem));
    // Читаем результат
    ZeroMemory(@svText, cchTextMax);
    ReadProcessMemory(hProcess, LVItem.pszText, @svText[1], nTextLength, dwWriten);
    // заполняем строки TStringGrid
    ADataGrid.Cells[1, i+1] := StrPas(PChar(@svText[1]));
    // Считываем столбцы
    for j := 0 to AColumnCount do
    begin
      LVItem.iSubItem := j;
      // Пишем ее в память удаленного процесса
      if not WriteProcessMemory(hProcess, pLVItem, @LVItem, SizeOf(LV_ITEM), dwWriten) then
        Exit;
      nTextLength := sendMessage(ALVHandle, LVM_GETITEMTEXT, i, Integer(pLVItem));
      // Читаем результат
      ZeroMemory(@svText, cchTextMax);
      ReadProcessMemory(hProcess, LVItem.pszText, @svText[1], nTextLength, dwWriten);
      // заполняем столбцы TStringGrid
      ADataGrid.Cells[j, i] := StrPas(PChar(@svText[1]));
    end;
  end;

  // Освобождаем ранее выделенную память
  VirtualFreeEx(hProcess, pszText, 0, MEM_RELEASE);
  VirtualFreeEx(hProcess, pLVItem, 0, MEM_RELEASE);
  // Закрываем описатель процесса
  CloseHandle(hProcess);
end;

и ее вызов
Код:
...
d := FindWindowEx(H3, 0, 'ListView20WndClass', nil);
GetListViewGrid(d, 2, 0, FindComponent(Format('StringGrid%d', [q])) as TStringGrid);
...

Проблема в том, что в Delphi7, ячейки моих StringGrid'ов заполняются, а в DelphiXE ячейки StringGrid'ов становятся ПУСТЫМИ.

(Предварительно ячейки моих StringGrid'ов заполнены нулями)
Ответить с цитированием
  #2  
Старый 21.06.2013, 14:22
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
Радость

ну так приставка Wide как обычно в таких случаях...
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #3  
Старый 21.06.2013, 14:55
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
ну так приставка Wide как обычно в таких случаях...

Не понимаю, к чему это?
Ответить с цитированием
  #4  
Старый 21.06.2013, 15:28
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

String - WideString, Char - WideChar, PChar - PWideChar
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #5  
Старый 21.06.2013, 15:56
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
String - WideString, Char - WideChar, PChar - PWideChar
Все равно пустые.
Мне кажется что дело не в кодировке.

Последний раз редактировалось Barsdg, 21.06.2013 в 16:26.
Ответить с цитированием
  #6  
Старый 23.06.2013, 09:12
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

а что ты сделал, что не помогает? SendMessageW() тоже не помогло что-ли?
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
  #7  
Старый 24.06.2013, 09:11
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
а что ты сделал, что не помогает? SendMessageW() тоже не помогло что-ли?
В самой процедуре, в объявлениях переменных вместо pszText: PChar; и svText: ShortString; подставлял:
WideChar, PWideChar, WideString, AnsiString.

Программа либо вылетала, либо также пустые строки
Ответить с цитированием
  #8  
Старый 24.06.2013, 09:31
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

а PAnsiChar, либо SendMessage с правильной буковкой на конце в память получают значение?
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
Barsdg (25.06.2013)
  #9  
Старый 24.06.2013, 11:53
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию

Цитата:
Сообщение от NumLock
а PAnsiChar, либо SendMessage с правильной буковкой на конце в память получают значение?
Я извиняюсь за глупый вопрос, но как это проверить?
Ответить с цитированием
  #10  
Старый 24.06.2013, 12:16
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Все API-функции, которые потенциально могут работать со строками, имеют два названия, для однобайтовых строк и для двучбайтовых, с буквой A и с буквой W на конце. Например SendMessageA и SendMessageW. До D2009 по умолчанию, в функции без этой буквы на конце, подразумевалась буква A, начиная с D2009 подразумевается буква W. То есть если пишем SendMessage, то в D7 вызывается функция SendMessageA, а в DelphiXE - вызывается функция SendMessageW. (см Windows.pas). И соответственно в первую нужно подавать PAnsiChar, а во вторую PWideChar. Когда в одной программе используются и Ansi и Wide строки, нужно явно указывать, какую именно функцию собираетесь вызывать.
Ответить с цитированием
Этот пользователь сказал Спасибо icWasya за это полезное сообщение:
Barsdg (25.06.2013)
  #11  
Старый 24.06.2013, 12:31
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию

Цитата:
Все API-функции, которые потенциально могут работать со строками, имеют два названия, для однобайтовых строк и для двучбайтовых, с буквой A и с буквой W на конце. Например SendMessageA и SendMessageW. До D2009 по умолчанию, в функции без этой буквы на конце, подразумевалась буква A, начиная с D2009 подразумевается буква W. То есть если пишем SendMessage, то в D7 вызывается функция SendMessageA, а в DelphiXE - вызывается функция SendMessageW. (см Windows.pas). И соответственно в первую нужно подавать PAnsiChar, а во вторую PWideChar. Когда в одной программе используются и Ansi и Wide строки, нужно явно указывать, какую именно функцию собираетесь вызывать.

Спасибо понятно.
Заменил везде в процедуре PChar на PWideChar и SendMessage на SendMessageW. Результат не изменился.
Ответить с цитированием
  #12  
Старый 24.06.2013, 14:17
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

А то приложение, - из которого читаешь, юникодовое?
Ответить с цитированием
  #13  
Старый 24.06.2013, 14:34
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию

Цитата:
А то приложение, - из которого читаешь, юникодовое?
Чем это можно проверить?
повторюсь, но подробнее: процедура срабатывает в версии Portable Turbo Delphi Lite "Borland® Delphi® for Microsoft® Windows™ Version 10.0.2558.35231 Update 2 Copyright © 2005 Borland® Software Corporation"

Последний раз редактировалось Barsdg, 24.06.2013 в 14:38.
Ответить с цитированием
  #14  
Старый 24.06.2013, 17:11
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

Я просто предлагаю попробывать написать две версии- Ansi и Wide.
Только не забыть, что структура типа LV_ITEM тоже существует в двух вариантах - LV_ITEMA и LV_ITEMW
Ответить с цитированием
Этот пользователь сказал Спасибо icWasya за это полезное сообщение:
Barsdg (25.06.2013)
  #15  
Старый 25.06.2013, 09:17
Barsdg Barsdg вне форума
Прохожий
 
Регистрация: 02.06.2011
Сообщения: 24
Репутация: 10
По умолчанию

Цитата:
Я просто предлагаю попробывать написать две версии- Ansi и Wide.
Только не забыть, что структура типа LV_ITEM тоже существует в двух вариантах - LV_ITEMA и LV_ITEMW

Пробовал и Ansi и Wide, StringGrid (предварительно заполнены нулями) по прежнему становятся пустыми.

Вот с Wide (может я что-то пропустил):
Код:
procedure GetListViewGrid(ALVHandle: HWND; AColumnCount, AItemCount: Integer;
ADataGrid: TStringGrid);
const
cchTextMax=255;
var
hProcess: THandle;
dwProcessID: DWORD;
dwWriten: DWORD;
LVItemCount: Integer;
i, j, nTextLength: Integer;
pLVItem: ^LV_ITEMW;
LVItem: LV_ITEMW;
pszText: PWideChar;
svText: ShortString;
begin
if ALVHandle=0 then
Exit;
// Получаем количество строк
LVItemCount := ListView_GetItemCount(ALVHandle);
if AItemCount>LVItemCount then
Exit;
if AItemCount>0 then
LVItemCount := AItemCount;
// Получаем ID процесса, которому принадлежит найденное окно
dwProcessID := 0;
GetWindowThreadProcessId(ALVHandle, @dwProcessID);
if dwProcessID=0 then
ExitProcess(GetLastError);
// Открываем процесс
hProcess := 0;
hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, dwProcessID);
if hProcess=0 then
ExitProcess(GetLastError);
// Выделяем в нем память под текстовый буффер
pszText := VirtualAllocEx(hProcess, nil, cchTextMax, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
// Выделяем в нем память под структуру LVITEM
pLVItem := VirtualAllocEx(hProcess, nil, SizeOf(LV_ITEMW), MEM_COMMIT or MEM_TOP_DOWN,
PAGE_READWRITE);
// Устанавливаем колич строк и столбцов в TStringGrid
ADataGrid.RowCount := LVItemCount;
ADataGrid.ColCount := AColumnCount;
// Заполняем структуру
ZeroMemory(@LVItem, SizeOf(LV_ITEMW));
LVItem.Mask := LVIF_TEXT;
LVItem.pszText := pszText;
LVItem.cchTextMax := cchTextMax;
// Считываем строки
for i := 0 to LVItemCount do
begin
LVItem.iSubItem := 0;
// Пишем ее в память удаленного процесса
if not WriteProcessMemory(hProcess, pLVItem, @LVItem, SizeOf(LV_ITEMW), dwWriten) then
Exit;
nTextLength := sendMessageW(ALVHandle, LVM_GETITEMTEXT, i, Integer(pLVItem));
// Читаем результат
ZeroMemory(@svText, cchTextMax);
ReadProcessMemory(hProcess, LVItem.pszText, @svText[1], nTextLength, dwWriten);
// заполняем строки TStringGrid
ADataGrid.Cells[1, i+1] := StrPas(PWideChar(@svText[1]));
// Считываем столбцы
for j := 0 to AColumnCount do
begin
LVItem.iSubItem := j;
// Пишем ее в память удаленного процесса
if not WriteProcessMemory(hProcess, pLVItem, @LVItem, SizeOf(LV_ITEMW), dwWriten) then
Exit;
nTextLength := sendMessageW(ALVHandle, LVM_GETITEMTEXT, i, Integer(pLVItem));
// Читаем результат
ZeroMemory(@svText, cchTextMax);
ReadProcessMemory(hProcess, LVItem.pszText, @svText[1], nTextLength, dwWriten);
// заполняем столбцы TStringGrid
ADataGrid.Cells[j, i] := StrPas(PWideChar(@svText[1]));
end;
end;
// Освобождаем ранее выделенную память
VirtualFreeEx(hProcess, pszText, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, pLVItem, 0, MEM_RELEASE);
// Закрываем описатель процесса
CloseHandle(hProcess);
end;
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 14:21.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter