Форум: "WinAPI";
Текущий архив: 2006.05.14;
Скачать: [xml.tar.bz2];
ВнизОшибка с LISTVIEW Найти похожие ветки
← →
Дубинка (2006-02-19 20:46) [0]
var
h1, h2, h3: HWND;
lvFindInfo: LV_FINDINFO;
h1 := FindWindow(nil, "Диспетчер задач Windows");
h2 := FindWindowEx(h1, 0, nil, "");
h3 := FindWindowEx(h2, 0, "SysListView32", "Процессы");
ListView_FindItem(h3, -1, lvFindInfo);
Конечно понять для чего нужен этот код просто, я думаю, но вот понять почему он не канает - диспетчер задач завершается ошибкой - у меня мозгов не хватает понять....
← →
begin...end © (2006-02-19 21:11) [1]> Дубинка (19.02.06 20:46)
> ListView_FindItem(h3, -1, lvFindInfo)
Здесь третьим параметром фактически передаётся указатель на структуру типа LV_FINDINFO, расположенную в памяти Вашего процесса. Оконная процедура "чужого" ListView"а, получив сообщение LVM_FINDITEM, а в качестве его параметра -- этот указатель, будет рассматривать последний как адрес структуры в адресном пространстве своего процесса. А там такой структуры нет -- отсюда и ошибка.
← →
Дубинка (2006-02-19 22:09) [2]хе-хе.... я сразу почему-то до этого не допер(ла)....
Я вообще ноль в работе с чужими приложениями... по сути как засунуть по данному адресу во вражеский процесс пару байт я знаю, а вот как найти "чистый" кусок памяти для этого? ну чтоб я ему ничего не испортил... Ну и как соответственно отметить это самое изменение вы мне не подскажите?
← →
Хинт © (2006-02-20 08:56) [3]Вот кусок кода из одного моего проекта. Немного модифицировать и...
procedure GetText(ListWND: HWND; Lines: TStrings);
const
PROCESS_ACCESS = PROCESS_VM_OPERATION or PROCESS_VM_READ or
PROCESS_VM_WRITE;
type
PProcData = ^TProcData;
TProcData = record
Item: TLVItemA;
Txt: packed array[0..1023] of AnsiChar;
ItemRect: TRect;
end;
var
Cnt, I,J: Integer;
ProcID: DWORD;
ProcessHandle: THandle;
Data: TProcData;
RemoteProcData: PProcData;
Res: Boolean;
LI: TListItem;
ColWid: Integer;
pt: TPoint;
List:Array of record
count,item:string;
end;
begin
ProcID := 0;
GetWindowThreadProcessId(ListWND, ProcID);
if ProcId = 0 then
begin
MessageDlg("Cannot retrieve process ID.", mtError, [mbOK], 0);
Exit;
end;
ProcessHandle := OpenProcess(PROCESS_ACCESS, False, ProcID);
if ProcessHandle = 0 then RaiseLastOSError;
try
RemoteProcData := VirtualAllocEx(ProcessHandle, nil,
SizeOf(RemoteProcData^), MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
if RemoteProcData = nil then RaiseLastOSError;
try
Cnt := ListView_GetItemCount(ListWND);
setlength(list,cnt);
Lines.Clear;
for I := 0 to Cnt - 1 do for j:=0 to 1 do
begin
FillChar(Data, SizeOf(Data), 0);
with Data.Item do
begin
iSubItem := j;
pszText := @RemoteProcData^.Txt;
cchTextMax := SizeOf(RemoteProcData^.Txt) - 1;
end;
Res := WriteProcessMemory(ProcessHandle, RemoteProcData,
@Data, SizeOf(Data), PLongWord(nil)^);
if not Res then RaiseLastOSError;
SendMessage(ListWND, LVM_GETITEMTEXT, I, LPARAM(@RemoteProcData^.Item));
SendMessage(ListWND, LVM_GETITEMRECT, I, LPARAM(@RemoteProcData^.ItemRect));
Res := ReadProcessMemory(ProcessHandle, RemoteProcData,
@Data, SizeOf(Data), PLongWord(nil)^);
if not Res then RaiseLastOSError;
if j=0 then List[i].item:=data.Txt else
begin
List[i].count:=data.txt;
Lines.Add(List[i].item+" - "+List[i].count);
end;
end;
finally
Res := LongBool(VirtualFreeEx(ProcessHandle, RemoteProcData,
0, MEM_RELEASE));
if not Res then RaiseLastOSError;
end;
finally
CloseHandle(ProcessHandle);
end;
end;
← →
begin...end © (2006-02-20 08:59) [4]> Дубинка (19.02.06 22:09) [2]
Находить чистые куски самостоятельно не придётся. Нужно запросить нужный объём памяти в чужом процессе (предварительно получив дескриптор процесса) с помощью функции VirtualAllocEx, передав ей в качестве второго параметра (желаемого начального адреса региона) 0 -- это означает, что функция выделит память там, где посчитает нужным.
Если функция отработает успешно, она вернёт значение, отличное от нуля -- базовый адрес выделенной памяти в адресном пространстве чужого процесса. Теперь по этому адресу можно записывать то, что Вам нужно. Конкретно для данного примера нужно будет записать, во-первых, саму структуру LV_FINDINFO. Во-вторых, если предполагается использовать тип поиска LVFI_STRING (т.е. поиск элементов, заголовки которых полностью или частично совпадают с некоторой указанной строкой), то в LV_FINDINFO нужно будет инициализировать поле psz, а именно -- поместить туда указатель на строку-образец. Причём этот указатель тоже должен быть действителен именно в чужом процессе. А значит, выделять память в нём нужно не только под структуру LV_FINDINFO, но и под строку.
ОК, теперь память выделена, в неё записаны строка и структура LV_FINDINFO . Вот теперь можно посылать LVM_FINDITEM (или использовать ListView_FindItem), причём это уже можно делать из своего процесса.
А после того, как сообщение будет обработано, выделенную "чужую" память надо освободить (если она больше не понадобится).
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2006.05.14;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.01 c