Re[4]: Чтение данных из SysListView32 со стилем LVS_OWNERDATA
От: Kirhog  
Дата: 20.12.13 12:58
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Невиртуальные и не должны. Всё ли правильно делаете?

AG>
  • Сообщение WM_NOTIFY отсылается родителю SysListView32, а не ему самому, сам SysListView32 в параметрах сообщения
    AG>
  • перед отправкой заполняются соответствующие поля NMLVDISPINFO
    AG>
  • это сообщение нельзя слать из другого процесса

    Привожу код, с помощью которого я это делал.

    Первые два пункта выполнил, а вот про третий не знал (в статье про LVN_GETDISPINFO на MSDN'e про это не говорится, но наверное подразумевается). Я так понимаю, что необходимо встроить свою Dll в другой процесс и посылать это сообщение из нее?
    Спасибо за наводку, вечером попробую.

    int GetListViewItemText2(HWND handle, int row, int column, LPTSTR text, int size) {
        const int SIZE = 512;
    
        TCHAR item[SIZE];
        LPTSTR _item;
        unsigned long pid;
        HANDLE process;
        NMLVDISPINFO info, *_info;
        
        GetWindowThreadProcessId(handle, &pid);
        process = OpenProcess(
            PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 
            FALSE, 
            pid);
        //log(string("process: ") +  to_string((llong) process));
    
        _info = (NMLVDISPINFO*) VirtualAllocEx(process, NULL, sizeof(NMLVDISPINFO), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
        _item = (LPTSTR) VirtualAllocEx(process, NULL, SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
        
        memset(&info, 0, sizeof(NMLVDISPINFO));
        memset(item, 0, SIZE);
    
        int controlId = GetDlgCtrlID(handle);
        
        info.hdr.code = LVN_GETDISPINFO;
        info.hdr.idFrom = controlId;
        info.hdr.hwndFrom = handle;
    
        info.item.iItem = row;
        info.item.mask = LVIF_TEXT;
        info.item.iSubItem = column;
        info.item.pszText = _item;
        info.item.cchTextMax = SIZE;
        
        SIZE_T* bytes = new SIZE_T;
        *bytes = 0;
    
        LRESULT res = WriteProcessMemory(process, _info, &info, sizeof(NMLVDISPINFO), bytes);
        if (!res) {
            DWORD error = GetLastError();
            log(string("WriteProcessMemory error: ") + to_string((llong) error));
        }
    
        HWND parent = (HWND) GetWindowLongPtr(handle, GWL_HWNDPARENT);
    
        res = SendMessage(parent, WM_NOTIFY, (WPARAM) controlId, (LPARAM) _info);
        
        res = ReadProcessMemory(process, _item, item, SIZE, bytes);
        if (!res) {
            DWORD error = GetLastError();
            log(string("ReadProcessMemory error: ") + to_string((llong) error));
        }
        
        // TODO: refactor
        int i;
        for (i = 0; i + 1 < size && item[i]; ++i) {
            text[i] = item[i];
        }
        text[i] = 0;
    
        int result = _tlen(item);
        
        VirtualFreeEx(process, _info, 0, MEM_RELEASE);
        VirtualFreeEx(process, _item, 0, MEM_RELEASE);
        delete bytes;
        
        CloseHandle(process);
    
        return result;
    }
  •  
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.