Вчера на одном форуме встретился интересный вопрос про то, как выделить строки в «чужой» программе в ListView. Суть вопроса такова: нужно из своего процесса (A) зная хэндл окна ListView (hList) в другом процессе (B) программно выделить нужные строки. Ответ вроде бы банален, послать сообщение:
SendMessage(hList, LVM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM) (LV_ITEM *)&lvi);
Но не все так просто. Дело в том, что переменная объявленная как: LV_ITEM lvi, находится в адресном пространстве нашего процесса (A) и, вызывая SendMessage, передавая ей в качестве одного из аргументов указатель на lvi, мы ставим в очередь другому процессу (B) сообщений с неверным указателем, что, как правило, приводит к исключению и падению процесса (B). Чтоб все прошло гладко нужно выделить память в целевом процессе (B) скопировать туда lvi и уже вызывать SendMessage, передавая ей указатель на lvi размещенную в адресном пространстве целевого процесса (B). То есть выполнить примерно следующий код:
int SelectList(HWND hList, int iIndex) { /* Получаем process Id владеющего ListView */ GetWindowThreadProcessId(hList, pid);
if(!pid){
/* Открываем процесс с нужными правами */ HANDLE hProcess = OpenProcess(PROCESS_VM_WRITE|PROCESS_VM_OPERATION, TRUE, pid);
if(!hProcess){
/* Выделяем память в целевом процессе */ LPVOID lpMem = VirtualAllocEx(hProcess, NULL, sizeof(LV_ITEM), MEM_COMMIT, PAGE_READWRITE);
if(!lpMem){
/* Заполняем структуру */ LV_ITEM LV; LV.state = LVIS_SELECTED; LV.mask = LVIS_SELECTED;
SIZE_T cdWrite;
/* Копируем LV в целевой процесс */ if (WriteProcessMemory(hProcess, lpMem, &LV, sizeof(LV_ITEM), &cdWrite)) { /* Посылаем сообщение о выделении нужной строки */ SendMessage(hList, LVM_SETITEMSTATE, (WPARAM)iIndex, (LPARAM)lpMem); }
/* Освобождаем выделенную память */ VirtualFreeEx(hProcess, lpMem, 0, MEM_RELEASE); } /* Закрываем дескриптор открытого процесса*/ CloseHandle(hProcess); } } }
Аналогично нужно вызывать любые другие сообщения для «чужих» окон, где в качестве параметров передаются какие-либо указатели на переменные.