Ce code permet de lister les icones du "Tray" à côté de l'horloge et de savoir à quel programme une icone appartient...
C'est une interprétation des données systèmes de cette zone (une barre d'outils sous ME/2000/XP)
Ce code a été testé sur 98/2000/XP
Source / Exemple :
//pour 95/98
#include "common.h"
//ToolHelp32
#include "tlhelp32.h"
//renvoie les icones du tray sous 9x
LPSYSTRAY GetTrayIcons_9x()
{
//demande le hwnd du tray
HWND hTray = GethWndTray();
//alloue de la mémoire pour les infos sur le tray
LPSYSTRAY lpSystray=(LPSYSTRAY)VirtualAlloc(NULL,sizeof(SYSTRAY),MEM_COMMIT,PAGE_READWRITE);
if (lpSystray)
{
//demande le pointeur vers les infos du tray
LPVOID lpData = (LPVOID)GetWindowLong(hTray,0);
if (lpData)
{
DWORD pid=0;
//demande le pid de Explorer.exe
GetWindowThreadProcessId(hTray,&pid);
//demande un handle de Explorer.exe pour lire dans son espace mémoire
HANDLE hP = OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION,FALSE,pid);
if (hP)
{
//lit les infos sur le tray
if (ReadProcessMemory(hP,lpData,(LPVOID)lpSystray,sizeof(SYSTRAY),NULL))
{
//copie le pointeur vers l'entête de la liste d'icones
lpData = (LPVOID)lpSystray->lpsysListHeader;
//alloue de la mémoire pour l'entête de la liste d'icones
lpSystray->lpsysListHeader = (LPNOTIFYLISTHEADER)VirtualAlloc(NULL,sizeof(NOTIFYLISTHEADER),MEM_COMMIT,PAGE_READWRITE);
if (lpSystray->lpsysListHeader)
{
//lit l'entête de la liste d'icones
if (ReadProcessMemory(hP,lpData,(LPVOID)lpSystray->lpsysListHeader,sizeof(NOTIFYLISTHEADER),NULL))
{
//nombre d'icones dans le tray
ULONG dwCount =lpSystray->lpsysListHeader->dwCount;
//copie le pointeur vers la liste de pointeurs vers les infos sur les icones
lpData = (LPVOID)lpSystray->lpsysListHeader->lpNotifyDataList;
//alloue de la mémoire pour cette liste de pointeurs
lpSystray->lpsysListHeader->lpNotifyDataList = (LPNOTIFYENTRY*)VirtualAlloc(NULL,dwCount * sizeof(LPVOID),MEM_COMMIT,PAGE_READWRITE);
//lit la liste de pointeurs
if (ReadProcessMemory(hP,lpData,(LPVOID)lpSystray->lpsysListHeader->lpNotifyDataList,dwCount * sizeof(LPVOID),NULL))
{
//pour chaque pointeur
for (UINT x =0; x < dwCount;x++)
{
//peut-être NT4 ?
if (IsWindowsNT())
{
//on copie le notifyicondata
if (((lpSystray->lpsysListHeader->lpNotifyDataList))[x] = (LPNOTIFYENTRY)VirtualAlloc(NULL,sizeof(NOTIFYICONDATAW)+4,MEM_COMMIT,PAGE_READWRITE))
ReadProcessMemory(hP,(LPVOID)(((LPNOTIFYENTRY*)lpData)[x]),(LPVOID)((lpSystray->lpsysListHeader->lpNotifyDataList))[x],sizeof(NOTIFYICONDATAW)+4,NULL);
}
else
{
//on copie le notifyicondata
if (((lpSystray->lpsysListHeader->lpNotifyDataList))[x] = (LPNOTIFYENTRY)VirtualAlloc(NULL,sizeof(NOTIFYICONDATAA)+4,MEM_COMMIT,PAGE_READWRITE))
ReadProcessMemory(hP,(LPVOID)(((LPNOTIFYENTRY*)lpData)[x]),(LPVOID)((lpSystray->lpsysListHeader->lpNotifyDataList))[x],sizeof(NOTIFYICONDATAA)+4,NULL);
}
}
}
}
}
}
//ferme le handle de Explorer.exe
CloseHandle(hP);
}
}
}
//renvoie les infos
return lpSystray;
}
//libère la mémoire allouée par GetTrayIcons_9x
void FreeTrayIcons_9x(LPSYSTRAY lpSystray)
{
if (lpSystray)
{
if (lpSystray->lpsysListHeader)
{
ULONG dwCount =lpSystray->lpsysListHeader->dwCount;
for (UINT x =0; x < dwCount;x++)
{
//libère chaque NOTIFYENTRY
VirtualFree((LPVOID)(lpSystray->lpsysListHeader->lpNotifyDataList)[x],NULL,MEM_RELEASE);
}
//libère la liste
VirtualFree((LPVOID)lpSystray->lpsysListHeader->lpNotifyDataList,NULL,MEM_RELEASE);
//libère l'entête
VirtualFree((LPVOID)lpSystray->lpsysListHeader,NULL,MEM_RELEASE);
}
//libère les infos du tray
VirtualFree((LPVOID)lpSystray,NULL,MEM_RELEASE);
}
}
//renvoie le chemin et nom de l'exe d'un processus par son pid (sous 9x)
BOOL GetProcessNameFromPID_9x(DWORD pid,char* lpName)
{
//si pas de tampon fournit
if (lpName==NULL)
return FALSE;
//on crée une liste de processus
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
//on initialise la structure pour les infos sur un processus
PROCESSENTRY32 Process={0};
Process.dwSize = sizeof(PROCESSENTRY32);
//demande la premier processus
BOOL ret = Process32First(hSnap,&Process);
//tant qu'il y a encore des processus à énumérer et que l'on a pas trouvé le processus que l'on veut
while ((ret) && (Process.th32ProcessID != pid))
{
//demande le suivant
Process.dwSize = sizeof(PROCESSENTRY32);
ret = Process32Next(hSnap,&Process);
}
//libère la liste des processus
CloseHandle(hSnap);
//si on a trouvé
if (ret)
{
//on copie le nom de l'exe
strcpy(lpName,Process.szExeFile);
return TRUE;
}
else
return FALSE;
};
//renvoie les icones du tray sous windows ME
LPTRAY_ME GetTrayIcons_ME(int* nIcons)
{
HANDLE hProc=NULL; //handle de Explorer.exe
HWND hTray=NULL; //hWnd du tray
DWORD pid=0; //identifiant d'un processus
HGLOBAL ptrVM=NULL; //pointeur vers la zone mémoire pour TBBUTTON
DWORD ret=0; //valeur de retour
LPVOID ptrTip=NULL; //pointeur vers une chaîne Unicode (Tip ou Path)
TBBUTTON tbut; //les infos sur le bouton
CHAR Char=0; //contient un caractère unicode
int X,Y; //compteurs
LPTRAY_ME pTray=NULL; //pointeur vers l'entrée active du buffer Tray
//on initialise tbut
ZeroMemory((LPVOID)&tbut,sizeof(TBBUTTON));
//on demande le hWnd du tray
if ((hTray = GethWndTray())==NULL)
return NULL;
//on demande l//identifiant de Explorer.exe
GetWindowThreadProcessId(hTray, &pid);
//on demande un handle de Explorer.exe
if ((hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid))==NULL)
{
//on alloue de la mémoire pour TBBUTTON
if (ptrVM = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,sizeof(tbut)))
{
//on demande le nombre de boutons dans le tray
- nIcons = (int)SendMessage(hTray, TB_BUTTONCOUNT, (WPARAM)NULL, (LPARAM)NULL);
//on alloue la mémoire nécessaire pour les infos
pTray = (LPTRAY_ME)VirtualAlloc(NULL,(*nIcons) * sizeof(TRAY),MEM_COMMIT,PAGE_READWRITE);
//pour chaque icone
for (X = 0;X < *nIcons;X++)
{
//on demande les infos sur le bouton
SendMessage(hTray, TB_GETBUTTON, X, (LPARAM)ptrVM);
//on lit les infos sur le bouton
ReadProcessMemory(hProc, ptrVM, (LPVOID)&tbut, sizeof(TBBUTTON), &ret);
//on extrait les données utiles
pTray[X].dwData = (LPVOID)tbut.dwData;
pTray[X].fsState = tbut.fsState;
pTray[X].fsStyle = tbut.fsStyle;
pTray[X].iBitmap = tbut.iBitmap;
pTray[X].idCommand = tbut.idCommand;
pTray[X].iString = (LPVOID)tbut.iString;
//la Tip
ptrTip = (LPVOID)tbut.iString;
Y=0;
do
{
Char=NULL;
//on lit chaque caractère unicode
ReadProcessMemory(hProc, ptrTip, (LPVOID)&Char, sizeof(CHAR), &ret);
pTray[X].sTip[Y] = Char;
ptrTip = (LPBYTE)ptrTip + 1;
Y++;
//jusqu'au NULL
} while (Char);
//on lit les données sur l//icone (Path...)
ReadProcessMemory(hProc, (LPVOID)tbut.dwData, (LPVOID)&(pTray[X]), 36, &ret);
GetWindowThreadProcessId(pTray[X].hwnd,&pid);
GetProcessNameFromPID_9x(pid,pTray[X].Path);
}
GlobalFree(ptrVM);
}
CloseHandle(hProc);
}
return pTray;
}
//pour NT
#include "common.h"
#include "psapi.h"
//pointeurs de fonctions de PSAPI.dll (uniquement pour NT/2000/XP)
//si l'on link avec, l'application ne marchera pas sous 9x
//pour énumérer les modules de d'un processus
typedef BOOL (_stdcall *lpEnumProcessModules)(HANDLE hProcess,HMODULE* lphModule,DWORD cb,LPDWORD lpcbNeeded);
//pour obtenir le nom d'un module
typedef DWORD (_stdcall *lpGetModuleFileNameExW)(HANDLE hProcess,HMODULE hModule,LPWSTR lpFilename,DWORD nSize);
//renvoie la liste des icones présentes dans le tray
//comme les infos se trouvent dans Explorer.exe et non dans notre processus
//on doit allouée de la mémoire dans Explorer.exe pour pouvoir fournir un pointeur valide vers un TBBUTTON à SendMessage
//cette fonction ne fonctionne que sous NT/2000/XP (car VirtualAllocEx n//est pas présent sous 9x)
LPTRAY GetTrayIcons_NT(int* nIcons)
{
HANDLE hProc=NULL; //handle de Explorer.exe
HWND hTray=NULL; //hWnd du tray
DWORD pid=0; //identifiant d'un processus
LPVOID ptrVM=NULL; //pointeur vers la zone mémoire pour TBBUTTON
DWORD ret=0; //valeur de retour
LPVOID ptrTip=NULL; //pointeur vers une chaîne Unicode (Tip ou Path)
TBBUTTON tbut; //les infos sur le bouton
TCHAR TChar=0; //contient un caractère unicode
int X,Y; //compteurs
LPTRAY pTray=NULL; //pointeur vers l'entrée active du buffer Tray
//on initialise tbut
ZeroMemory((LPVOID)&tbut,sizeof(TBBUTTON));
//on demande le hWnd du tray
if ((hTray = GethWndTray())==NULL)
return NULL;
//on demande l//identifiant de Explorer.exe
GetWindowThreadProcessId(hTray, &pid);
//on demande un handle de Explorer.exe
if ((hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid))==NULL)
return NULL;
//on alloue de la mémoire pour TBBUTTON
if ((ptrVM = VirtualAllocEx(hProc, NULL, sizeof(tbut), MEM_COMMIT, PAGE_READWRITE))==NULL)
{
CloseHandle(hProc);
return NULL;
}
//on demande le nombre de boutons dans le tray
- nIcons = (int)SendMessage(hTray, TB_BUTTONCOUNT, (WPARAM)NULL, (LPARAM)NULL);
//on alloue la mémoire nécessaire pour les infos
pTray = (LPTRAY)VirtualAlloc(NULL,(*nIcons) * sizeof(TRAY),MEM_COMMIT,PAGE_READWRITE);
//pour chaque icone
for (X = 0;X < *nIcons;X++)
{
//on demande les infos sur le bouton
SendMessage(hTray, TB_GETBUTTON, X, (LPARAM)ptrVM);
//on lit les infos sur le bouton
ReadProcessMemory(hProc, ptrVM, (LPVOID)&tbut, sizeof(TBBUTTON), &ret);
//on extrait les données utiles
pTray[X].dwData = (LPVOID)tbut.dwData;
pTray[X].fsState = tbut.fsState;
pTray[X].fsStyle = tbut.fsStyle;
pTray[X].iBitmap = tbut.iBitmap;
pTray[X].idCommand = tbut.idCommand;
pTray[X].iString = (LPVOID)tbut.iString;
//la Tip
ptrTip = (LPVOID)tbut.iString;
Y=0;
do
{
TChar=NULL;
//on lit chaque caractère unicode
ReadProcessMemory(hProc, ptrTip, (LPVOID)&TChar, sizeof(TCHAR), &ret);
pTray[X].sTip[Y] = TChar;
ptrTip = (LPBYTE)ptrTip + 2;
Y++;
//jusqu'au NULL
} while (TChar);
//on lit les données sur l//icone (Path...)
ReadProcessMemory(hProc, (LPVOID)tbut.dwData, (LPVOID)&(pTray[X]), 36, &ret);
//demande la PID du processus propriétaire de l'icone
GetWindowThreadProcessId(pTray[X].hwnd,&pid);
//demand el nom de ce processus
GetProcessNameFromPID_NT(pid,pTray[X].uniPath,255);
}
//on libère la mémoire allouée
VirtualFreeEx(hProc,ptrVM,NULL, MEM_RELEASE);
//on ferme le handle de Explorer.exe
CloseHandle(hProc);
//on renvoie le tout
return pTray;
}
//renvoie le nom du processus par son PID
BOOL GetProcessNameFromPID_NT(DWORD pid,WCHAR* lpName,DWORD cbName)
{
//si mauvais tampon
if (lpName==NULL)
return FALSE;
//on charge PSAPI
HMODULE hPSAPI = LoadLibrary("psapi.dll");
if (hPSAPI)
{
//on "active" les pointeurs vers EnumProcessModules et GetModuleFileNameEx
lpEnumProcessModules EnumProcessModules = (lpEnumProcessModules)GetProcAddress(hPSAPI,"EnumProcessModules");
lpGetModuleFileNameExW GetModuleFileNameExW = (lpGetModuleFileNameExW)GetProcAddress(hPSAPI,"GetModuleFileNameExW");
if (EnumProcessModules && GetModuleFileNameExW)
{
//demande un handle du processus
HANDLE hP = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,FALSE,pid);
if (hP)
{
HMODULE hMod=NULL; //HMODULE de l'exe (toujours le premier module du processus)
DWORD ret=0;
//demande le HMODULE de l'exe
(*EnumProcessModules)(hP,&hMod,sizeof(HMODULE),&ret);
if (hMod)
//demande le nom de l'exe
(*GetModuleFileNameExW)(hP,hMod,(WCHAR*)lpName,cbName);
//ferme le handle
CloseHandle(hP);
//libère PSAPI
FreeLibrary(hPSAPI);
return TRUE;
}
return FALSE;
}
}
}
//renvoie une chaine descriptive de l'état d'un bouton
char* GetState_NT(BYTE fsState,char* Buff)
{
if (!Buff)
return NULL;
if ((fsState & TBSTATE_CHECKED) == TBSTATE_CHECKED)
strcat(Buff,"Checked - ");
if ((fsState & TBSTATE_ELLIPSES) == TBSTATE_ELLIPSES)
strcat(Buff,"Ellipses - ");
if ((fsState & TBSTATE_ENABLED) == TBSTATE_ENABLED)
strcat(Buff,"Enabled - ");
if ((fsState & TBSTATE_HIDDEN) == TBSTATE_HIDDEN)
strcat(Buff,"Hidden - ");
if ((fsState & TBSTATE_INDETERMINATE) == TBSTATE_INDETERMINATE)
strcat(Buff,"Grayed - ");
if ((fsState & TBSTATE_MARKED) == TBSTATE_MARKED)
strcat(Buff,"Marked - ");
if ((fsState & TBSTATE_PRESSED) == TBSTATE_PRESSED)
strcat(Buff,"Pressed - ");
if ((fsState & TBSTATE_WRAP) == TBSTATE_WRAP)
strcat(Buff,"Wrap - ");
return Buff;
}
Conclusion :
Ce code fonctionne même lorsque l'option "Masquer les icones inactives" est activée (XP)...
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.