J'ai écrit une fonction qui peut générer le texte d'un élément de vue arborescente, même si l'arborescence est dans un processus distant. La fonction alloue deux blocs de mémoire dans le processus distant, remplit une structure TVITEM (qui est copiée dans le processus distant), envoie un message TVM_GETITEM et lit finalement le contenu du second bloc de mémoire distant dans un tampon local. Voici le code:Pourquoi le message TVM_GETITEM échoue-t-il sur les vues arborescentes comctl32.ocx ou 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;
}
Ce code fonctionne très bien avec les vues d'arbres simples que vous obtenez en passant le nom de classe WC_TREEVIEW
-CreateWindow
. Cependant, j'ai remarqué que cela ne fonctionne pas avec les nouveaux arbres fournis par MS Common Controls v5 (comctl32.ocx) ou MS Common Controls v6 (mscomctl.ocx). Dans ces cas, le texte renvoyé est toujours vide (le tampon est entièrement zéros). J'ai également remarqué que l'appel SendMessage renvoie zéro (d'où le traitement des erreurs indiqué par les commentaires // handle error
ci-dessus). Il n'est pas clair pour moi si cela indique vraiment une erreur, en tout cas le tampon est rempli avec tous les zéros.
Tous les autres messages d'arborescence (comme TVM_GETITEMRECT) semblent parfaitement fonctionner.
Est-ce que quelqu'un sait pourquoi? J'ai essayé de jouer avec le drapeau UNICODE (j'ai remarqué que TVM_GETITEM
est soit défini à TVM_GETITEMA
ou TVM_GETITEMW
) mais cela n'a pas semblé aider.
Après SendMessage retournant 0, essayez GetLastError. Ce qu'il restaure MSDN: Microsoft Windows Vista et versions ultérieures Lorsqu'un message est bloqué par UIPI, la dernière erreur, récupérée avec GetLastError, est définie sur 5 (accès refusé). – Igor
@Igor: Bonne idée, mais pas de chance: appeler GetLastError() après SendMessage() renvoie le code d'erreur 0. Peut-être que le code d'erreur est défini dans le processus distant car une erreur est survenue lors du transfert de TVM_GETITEM? –