我寫了一個函數,可以生成樹視圖項的文本,即使樹視圖位於遠程進程中。該函數在遠程進程中分配兩塊內存,填充TVITEM結構(將其複製到遠程進程中),發送TVM_GETITEM消息,最後將第二個遠程內存塊的內容讀回本地緩衝區。這是代碼:爲什麼TVM_GETITEM消息在comctl32.ocx或mscomctl.ocx樹視圖上失敗?
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
),但這似乎沒有幫助。
SendMessage返回0後,請嘗試GetLastError。它重新啓動了什麼?MSDN:Microsoft Windows Vista和更高版本。當一個消息被UIPI阻塞時,最後一個錯誤(使用GetLastError檢索)被設置爲5(拒絕訪問)。 – Igor 2010-02-17 16:05:29
@Igor:好主意,但沒有運氣:調用GetLastError函數()後的SendMessage()產生錯誤代碼0可能的錯誤代碼是在遠程進程設置,因爲同時發放TVM_GETITEM出現了錯誤? – 2010-02-17 16:20:49