Написах функция, която може да даде текста на елемент от дървовиден изглед, дори ако дървовидният изглед е в отдалечен процес. Функцията разпределя две части памет в отдалечения процес, попълва структура TVITEM (която е копирана в отдалечения процес), изпраща съобщение TVM_GETITEM и накрая чете съдържанието на второто отдалечено парче памет обратно в локален буфер. Това е кодът:
std::string getTreeViewItemText( HWND treeView, HTREEITEM item )
{
DWORD pid;
::GetWindowThreadProcessId( treeView, &pid );
HANDLE proc = ::OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid );
if ( !proc )
// handle error
TVITEM tvi;
ZeroMemory( &tvi, sizeof(tvi) );
LPVOID tvi_ = ::VirtualAllocEx( proc, NULL, sizeof(tvi), MEM_COMMIT, PAGE_READWRITE);
if ( !tvi_ )
// handle error
TCHAR buffer[100] = { 'X' };
LPVOID txt_ = ::VirtualAllocEx( proc, NULL, sizeof(buffer), MEM_COMMIT, PAGE_READWRITE );
if ( !txt_ )
// handle error
tvi.mask = TVIF_TEXT | TVIF_HANDLE;
tvi.pszText = (LPTSTR)txt_;
tvi.cchTextMax = sizeof(buffer) / sizeof(buffer[0] );
tvi.hItem = item;
if ( !::WriteProcessMemory( proc, tvi_, &tvi, sizeof(tvi), NULL ) )
// handle error
if ( !::SendMessage( treeView, TVM_GETITEM, 0, (LPARAM)tvi_ ) )
// handle error
if ( !::ReadProcessMemory( proc, (LPCVOID)txt_, buffer, sizeof( buffer ), NULL ) )
// handle error
::VirtualFreeEx( proc, tvi_, 0, MEM_RELEASE );
::VirtualFreeEx( proc, txt_, 0, MEM_RELEASE );
::CloseHandle( proc );
return buffer;
}
Този код работи много добре с обикновените дървовидни изгледи, които получавате, когато предавате името на класа WC_TREEVIEW
на CreateWindow
. Забелязах обаче, че не работи с по-новите дървета, предоставени от MS Common Controls v5 (comctl32.ocx) или MS Common Controls v6 (mscomctl.ocx). В тези случаи върнатият текст винаги е празен (буферът е само нули). Също така забелязах, че извикването SendMessage връща нула (следователно се включва обработката на грешки, обозначена с // handle error
коментарите по-горе). Не ми е ясно дали това наистина означава грешка, във всеки случай буферът е пълен с всички нули.
Всички други съобщения за дървовиден изглед (като TVM_GETITEMRECT) изглежда работят перфектно.
Някой знае ли защо е така? Опитах се да си поиграя с флага UNICODE (забелязах, че TVM_GETITEM
е дефиниран като TVM_GETITEMA
или TVM_GETITEMW
), но това не изглежда да помогне.