我编写了一个函数,它可以产生树视图项的文本,即使树视图位于远程进程中。该函数在远程进程中分配两个内存块,填充 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
),但这似乎没有帮助。