===============================下面這些很好====================================
//本例以擷取程式托盤圖示位置為例
//根據需要還可以擷取不少資訊
參考:http://www.cnblogs.com/daxingxing/archive/2012/02/06/2340384.html
[cpp] view plain copy
- //擷取托盤區域資料
- RECT CTray::GetTrayRect()
- {
- RECT rect = {0};
- HWND hWnd = NULL;
- hWnd = FindTrayWnd();
- if (hWnd != NULL)
- {
- if (!EnumNotifyWindow(rect,hWnd))//如果沒在普通托盤區
- {
- hWnd = FindNotifyIconOverflowWindow();//在溢出區(win7)
- if (hWnd != NULL)
- {
- EnumNotifyWindow(rect,hWnd);
- }
- }
- }
- return rect;
- }
- //枚舉擷取托盤區域位置
- bool CTray::EnumNotifyWindow(RECT &rect,HWND hWnd)
- {
- //RECT rect = {0};
- bool bSuc = false;
- unsigned long lngPID = 0;
- long ret = 0,lngButtons = 0;
- long lngHwndAdr = 0,lngHwnd = 0;//,lngTextAdr,lngButtonID;
- HANDLE hProcess = NULL;
- LPVOID lngAddress = NULL,lngRect = NULL;
- if (hWnd != NULL)
- {
- ret = GetWindowThreadProcessId(hWnd, &lngPID);
- if(ret != 0 && lngPID != 0)
- {
- hProcess = OpenProcess(PROCESS_ALL_ACCESS|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE,0,lngPID);//
- if (hProcess != NULL)
- {
- lngAddress = VirtualAllocEx(hProcess,0, 0x4096, MEM_COMMIT, PAGE_READWRITE);
- lngRect = VirtualAllocEx(hProcess,0,sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);
- lngButtons = SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0); //發送消息擷取托盤button數量
- if (lngAddress != NULL && lngRect != NULL)
- {
- for(int i=0 ;i< lngButtons;i++)
- {
- RECT rc = {0};
- int j = i;
- ret = SendMessage(hWnd,TB_GETBUTTON,j,long(lngAddress));//發送消息擷取托盤項資料起始位址
- ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + 12),&lngHwndAdr,4,0);
- if(ret != 0 && lngHwndAdr != -1)
- {
- ret = ReadProcessMemory(hProcess, LPVOID(lngHwndAdr),&lngHwnd, 4,0);//擷取句柄
- if(ret != 0 && (HWND)lngHwnd == m_NotifyIconData.hWnd)//
- {
- ret = ::SendMessage(hWnd,TB_GETITEMRECT,(WPARAM)j,(LPARAM)lngRect); //發送消息擷取托盤項區域資料
- ret = ReadProcessMemory(hProcess,lngRect,&rc, sizeof(rc),0); //讀取托盤區域資料
- if(ret != 0)
- {
- CWnd::FromHandle(hWnd)->ClientToScreen(&rc);
- rect = rc;
- }
- bSuc = true;//在普通托盤區找到,在溢出區不再查找
- break;
- }
- }
- }
- }
- if (lngAddress != NULL)
- {
- VirtualFreeEx( hProcess, lngAddress, 0x4096, MEM_DECOMMIT);
- VirtualFreeEx( hProcess, lngAddress, 0, MEM_RELEASE);
- }
- if (lngRect != NULL)
- {
- VirtualFreeEx( hProcess, lngRect, sizeof(RECT), MEM_DECOMMIT);
- VirtualFreeEx( hProcess, lngRect, 0, MEM_RELEASE);
- }
- CloseHandle(hProcess);
- }
- }
- }
- return bSuc;
- }
- //擷取普通托盤區視窗句柄
- HWND CTray::FindTrayWnd()
- {
- HWND hWnd = NULL;
- HWND hWndPaper = NULL;
- if ((hWnd = FindWindow(_T("Shell_TrayWnd"), NULL)) != NULL)
- {
- if ((hWnd = FindWindowEx(hWnd, 0, _T("TrayNotifyWnd"), NULL)) != NULL)
- {
- hWndPaper = FindWindowEx(hWnd, 0, _T("SysPager"), NULL);
- if(!hWndPaper)
- hWnd = FindWindowEx(hWnd, 0, _T("ToolbarWindow32"), NULL);
- else
- hWnd = FindWindowEx(hWndPaper, 0, _T("ToolbarWindow32"), NULL);
- }
- }
- return hWnd;
- }
- //擷取溢出托盤區視窗句柄
- HWND CTray::FindNotifyIconOverflowWindow()
- {
- HWND hWnd = NULL;
- hWnd = FindWindow(_T("NotifyIconOverflowWindow"), NULL);
- if (hWnd != NULL)
- {
- hWnd = FindWindowEx(hWnd, NULL, _T("ToolbarWindow32"), NULL);
- }
- return hWnd;
- }
//以下代碼網上收集的,變量 初始化 指針句柄 及函數是否成功都沒判定
//需要的自己加下判定,有時間再改了
[cpp] view plain copy
- struct TRAYDATA
- {
- HWND hwnd;
- UINT uID;
- UINT uCallbackMessage;
- DWORD Reserved[2];
- HICON hIcon;
- };
- void CTray::GetTrayRect()
- {
- HWND hWnd,hWndPaper;
- unsigned long lngPID;
- long ret,lngButtons;
- HANDLE hProcess;
- LPVOID lngAddress;
- long lngTextAdr,lngHwndAdr,lngHwnd,lngButtonID;
- TCHAR strBuff[1024]={0};
- TRAYDATA trayData = {0};
- TBBUTTON btnData={0};
- hWnd = FindWindow(_T("Shell_TrayWnd"), NULL);
- hWnd = FindWindowEx(hWnd, 0, _T("TrayNotifyWnd"), NULL);
- hWndPaper = FindWindowEx(hWnd, 0, _T("SysPager"), NULL);
- if(!hWndPaper)
- hWnd = FindWindowEx(hWnd, 0, _T("ToolbarWindow32"), NULL);
- else
- hWnd = FindWindowEx(hWndPaper, 0, _T("ToolbarWindow32"), NULL);
- ret = GetWindowThreadProcessId(hWnd, &lngPID);
- hProcess = OpenProcess(PROCESS_ALL_ACCESS|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE,0,lngPID);
- lngAddress = VirtualAllocEx(hProcess,0, 0x4096, MEM_COMMIT, PAGE_READWRITE);
- lngButtons = SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0);
- RECT rc; POINT point;
- LPVOID lngRect = VirtualAllocEx(hProcess,0,sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);
- CRect rect;
- for(int i=0 ;i< lngButtons;i++)
- {
- int j = i;
- ret = SendMessage(hWnd,TB_GETBUTTON,j,long(lngAddress));
- ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + 16),&lngTextAdr,4,0);
- if(lngTextAdr != -1)
- {
- ret = ReadProcessMemory(hProcess, LPVOID(lngTextAdr),strBuff,1024,0);
- //ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + 12),&lngHwndAdr,4,0); //擷取句柄
- //ret = ReadProcessMemory(hProcess, LPVOID(lngHwndAdr),&lngHwnd, 4,0);
- //ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + 4),&lngButtonID,4,0);//擷取buttonID
- CString str(strBuff);
- if (str.Compare(m_NotifyIconData.szTip) == 0)
- {
- ::SendMessage(hWnd,TB_GETITEMRECT,(WPARAM)j,(LPARAM)lngRect);
- ReadProcessMemory(hProcess,lngRect,&rc, sizeof(rc),0); //擷取托盤圖示區域
- CWnd::FromHandle(hWnd)->ClientToScreen(&rc);
- }
- //以下是隐藏托盤圖示
- // {
- // if(show)
- // {
- // SendMessage(hWnd,TB_HIDEBUTTON,lngButtonID,0);
- // }
- // else
- // {
- // SendMessage(hWnd,TB_HIDEBUTTON,lngButtonID,1);
- // }
- // }
- }
- }
- VirtualFreeEx( hProcess, lngAddress, 0x4096, MEM_DECOMMIT);
- VirtualFreeEx( hProcess, lngAddress, 0, MEM_RELEASE);
- VirtualFreeEx( hProcess, lngRect, sizeof(RECT), MEM_DECOMMIT);
- VirtualFreeEx( hProcess, lngRect, 0, MEM_RELEASE);
- CloseHandle(hProcess);
- }
//另一例子
[cpp] view plain copy
- VOID StartStorm()
- {
- HWND hMain = FindWindow("animate_layered_window_class", "暴風媒體中心");
- if ( hMain )
- {
- ShowWindow(hMain, SW_HIDE);
- }
- //得到工具欄句柄
- HWND hTray = FindWindow("Shell_TrayWnd", NULL);
- hTray = FindWindowEx(hTray, 0, "TrayNotifyWnd", NULL);
- hTray = FindWindowEx(hTray, 0, "SysPager", NULL);
- hTray = FindWindowEx(hTray, 0, "ToolbarWindow32", NULL);
- //擷取explore程序ID
- DWORD TrayPid;
- GetWindowThreadProcessId(hTray, &TrayPid);
- //打開程序 并且開辟程序空間
- RECT rect;
- TBBUTTON tb;
- TBBUTTON pTb;
- LPVOID lpAddr;
- DWORD dwThreadIdOfICO;
- DWORD dwTempId = FindStorm("Stormtray.exe"); //你要點選的程序的PID
- TRAYDATA traydata;
- HANDLE hOpen = OpenProcess(PROCESS_ALL_ACCESS, FALSE, TrayPid);
- lpAddr = VirtualAllocEx(hOpen, NULL, sizeof(tb) + sizeof(rect), MEM_COMMIT, PAGE_READWRITE);
- int nCount = SendMessage(hTray, TB_BUTTONCOUNT, 0, 0);
- int i;
- DWORD dwOutWrite;
- for ( i = 0; i < nCount; i ++)
- {
- ZeroMemory(&tb, sizeof(tb));
- ZeroMemory(&rect, sizeof(rect));
- //把參數寫進目标程序
- WriteProcessMemory(hOpen, lpAddr, &tb, sizeof(tb), &dwOutWrite);
- //WriteProcessMemory(hOpen, (LPVOID)((DWORD)lpAddr + sizeof(pTb)), &rect, sizeof(rect), &dwOutWrite);
- //擷取BUTTON
- SendMessage(hTray, TB_GETBUTTON, i, LPARAM(lpAddr));
- //讀取TBBUTTON結構
- ReadProcessMemory(hOpen, lpAddr, &pTb, sizeof(TBBUTTON), &dwOutWrite);
- //讀取TRAYDATA結構
- ReadProcessMemory(hOpen, (LPVOID)pTb.dwData, &traydata, sizeof(TRAYDATA), &dwOutWrite);
- GetWindowThreadProcessId(traydata.hwnd, &dwThreadIdOfICO);
- if ( dwThreadIdOfICO == dwTempId )
- {
- //擷取ICO的RECT
- LPVOID lp = (LPVOID)((DWORD)lpAddr + sizeof(pTb));
- SendMessage(hTray, TB_GETITEMRECT, i, (LPARAM)lp);
- LPVOID lpdata = (LPVOID)((DWORD)lpAddr + sizeof(TBBUTTON));
- ReadProcessMemory(hOpen, lpdata, &rect, sizeof(rect), &dwOutWrite);
- int iGap = rect.right/2; //得到圖示的中間坐标的間隔
- //點選
- SendMessage(hTray, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(rect.right - iGap, rect.bottom - iGap));
- SendMessage(hTray, WM_LBUTTONUP, 0, MAKELPARAM(rect.right - iGap, rect.bottom - iGap));
- //
- CloseHandle(hOpen);
- break;;
- }
- }
- }
//下面這個我試了,win7下可以用//
//win7有一個溢出托盤區:以下是隐藏在托盤區中的托盤資訊,用以上的方法找不到,因為在NotifyIconOverflowWindow裡
Fhwnd = FindWindow("NotifyIconOverflowWindow", NULL)
參考文章:http://topic.csdn.net/u/20101003/23/859851ee-5aa1-4476-8ce1-1359826df2b0.html
[cpp] view plain copy
- #include "stdafx.h"
- #include <afx.h>
- #include <locale.h>
- #include <string>
- using namespace std;
- typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
- BOOL IsWow64()
- {
- BOOL bIsWow64 = FALSE;
- LPFN_ISWOW64PROCESS
- fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
- GetModuleHandle(_T("kernel32")),"IsWow64Process");
- if (NULL != fnIsWow64Process)
- {
- if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
- {
- // handle error
- }
- }
- return bIsWow64;
- }
- HWND FindTrayWnd()
- {
- HWND hWnd = NULL;
- hWnd = FindWindow(_T("Shell_TrayWnd"), NULL);
- hWnd = FindWindowEx(hWnd, NULL, _T("TrayNotifyWnd"), NULL);
- hWnd = FindWindowEx(hWnd, NULL, _T("SysPager"), NULL);
- hWnd = FindWindowEx(hWnd, NULL, _T("ToolbarWindow32"), NULL);
- return hWnd;
- }
- HWND FindNotifyIconOverflowWindow()
- {
- HWND hWnd = NULL;
- hWnd = FindWindow(_T("NotifyIconOverflowWindow"), NULL);
- hWnd = FindWindowEx(hWnd, NULL, _T("ToolbarWindow32"), NULL);
- return hWnd;
- }
- void EnumNotifyWindow(HWND hWnd)
- {
- DWORD dwProcessId = 0;
- GetWindowThreadProcessId(hWnd,&dwProcessId);
- HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcessId);
- if ( hProcess==NULL ){
- return;
- }
- LPVOID lAddress = VirtualAllocEx(hProcess, 0, 4096, MEM_COMMIT, PAGE_READWRITE);
- if ( lAddress==NULL ){
- return;
- }
- DWORD lTextAdr = 0;
- BYTE buff[1024] = {0};
- CString strFilePath;
- CString strTile;
- HWND hMainWnd = NULL;
- int nDataOffset = sizeof(TBBUTTON) - sizeof(INT_PTR) - sizeof(DWORD_PTR);
- int nStrOffset = 18;
- if ( IsWow64() ){
- nDataOffset+=4;
- nStrOffset+=6;
- }
- //得到圖標個數
- int lButton = SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0);
- for (int i = 0; i < lButton; i++) {
- SendMessage(hWnd, TB_GETBUTTON, i, (LPARAM)lAddress);
- //讀文本位址
- ReadProcessMemory(hProcess, (LPVOID)((DWORD)lAddress + nDataOffset), &lTextAdr, 4, 0);
- if ( lTextAdr!=-1 ) {
- //讀文本
- ReadProcessMemory(hProcess, (LPCVOID)lTextAdr, buff, 1024, 0);
- hMainWnd = (HWND)(*((DWORD*)buff));
- strFilePath = (WCHAR *)buff + nStrOffset;
- strTile = (WCHAR *)buff + nStrOffset + MAX_PATH;
- _tprintf(_T("%s %s\n"),strTile,strFilePath);
- }
- }
- VirtualFreeEx(hProcess, lAddress, 4096, MEM_RELEASE);
- CloseHandle(hProcess);
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- setlocale(LC_ALL, "chs");
- EnumNotifyWindow(FindTrayWnd());
- _tprintf(_T("\n"));
- EnumNotifyWindow(FindNotifyIconOverflowWindow());
- system("pause");
- return 0;
- }
==================================================================
對于使用托盤圖示的程式,當我們通過強制結束程序,或者程式異常退出時,托盤圖示區域總會有托盤圖示的殘留,需要我們用滑鼠移到殘留區域時,托盤圖示才會自動消失。有時我們需要去做相關的處理,比如在軟體更新時,會強制結束程序,這時需要自動的去清除殘留的托盤圖示。通過研究和查閱網絡,整理如下的方法。
1、實際上托盤圖示區域對應一個ToolbarWindow32工具條視窗,每個托盤圖示對應一個按鈕,通過周遊找到指定程式的按鈕ID,向這個按鈕ID發送TB_HIDEBUTTON,使托盤圖示消失,代碼如下:
[cpp] view plain copy
- HWND hWnd,hWndPaper;
- unsigned long lngPID;
- long ret,lngButtons;
- HANDLE hProcess;
- LPVOID lngAddress;
- long lngTextAdr,lngHwndAdr,lngHwnd,lngButtonID;
- char strBuff[1024]={0};
- char* str = NULL;
- char *pp = NULL;
- hWnd = ::FindWindow( "Shell_TrayWnd", NULL );
- hWnd = ::FindWindowEx( hWnd, 0, "TrayNotifyWnd", NULL );
- hWndPaper = ::FindWindowEx( hWnd, 0, "SysPager", NULL );
- if( !hWndPaper )
- hWnd = ::FindWindowEx( hWnd, 0, "ToolbarWindow32", NULL );
- else
- hWnd = ::FindWindowEx( hWndPaper, 0, "ToolbarWindow32", NULL );
- ret = GetWindowThreadProcessId( hWnd, &lngPID );
- hProcess = OpenProcess( PROCESS_ALL_ACCESS
- |PROCESS_VM_OPERATION
- |PROCESS_VM_READ
- |PROCESS_VM_WRITE,
- 0,
- lngPID );
- lngAddress = VirtualAllocEx( hProcess,0, 0x4096, MEM_COMMIT, PAGE_READWRITE );
- lngButtons = ::SendMessage( hWnd, TB_BUTTONCOUNT, 0, 0 );
- for( int i=0; i< lngButtons - 1; i++ )
- {
- ret = ::SendMessage( hWnd, TB_GETBUTTON, i, long(lngAddress) );
- ret = ReadProcessMemory( hProcess, LPVOID(long(lngAddress) + 16), &lngTextAdr, 4, 0 );
- if( lngTextAdr != -1 )
- {
- ret = ReadProcessMemory( hProcess, LPVOID(lngTextAdr), strBuff, 1024, 0 );
- ret = ReadProcessMemory( hProcess, LPVOID(long(lngAddress) + 12), &lngHwndAdr, 4, 0 );
- ret = ReadProcessMemory( hProcess, LPVOID(lngHwndAdr),&lngHwnd, 4, 0 );
- ret = ReadProcessMemory( hProcess, LPVOID(long(lngAddress) + 4), &lngButtonID, 4, 0 );
- USES_CONVERSION;
- str = OLE2T( (LPOLESTR)( strBuff ) );
- pp=strstr( str,"阿裡旺旺" ); // 通過視窗名稱來比對
- if(pp != NULL)
- {
- ::SendMessage( hWnd, TB_HIDEBUTTON, lngButtonID, 1 );
- }
- }
- }
- VirtualFreeEx( hProcess, lngAddress, 0X4096, MEM_RELEASE );
- CloseHandle( hProcess );
上述方法比較負責,但相對合理很多,但是這種方法隻對win2000,XP系統有效,對與Win7卻無能為力,沒有效果。
3、對于Win7系統,程式的托盤圖示最終是放置在和XP一樣的ToolbarWindow32工具條視窗,但是有兩個地方,同樣是ToolbarWindow32工具條視窗,父視窗是不一樣的。在右下角可見區域,ToolbarWindow32工具條視窗的父視窗是SysPager視窗,周遊方法同XP一樣。對于掩藏的ToolbarWindow32工具條視窗,必須通過點選桌面右下角的可見區域左邊的一個按鈕,才會顯示出來,其父視窗則是一個叫做托盤溢出的視窗NotifyIconOverflowWindow。是以除了這兩個地方都要查找,查找後面的ToolbarWindow32工具條視窗,則隻要直接查找NotifyIconOverflowWindow即可,代碼如下:
[cpp] view plain copy
- //擷取托盤溢出區域視窗句柄
- hWnd = ::FindWindow(_T("NotifyIconOverflowWindow"), NULL);
- hWnd = ::FindWindowEx(hWnd, NULL, _T("ToolbarWindow32"), NULL);
上述相關代碼已認證實際測試,均能達到指定的效果。
================================================================
方法二:(已測試,在XP下可用)
//--------找出該圖示所對應的程序ID,如果該ID為NULL則删除該圖示--------//
bool refreshTray()
{
HWND hStatus=::FindWindow("Shell_TrayWnd",NULL); //得到工作列句柄
if (hStatus==NULL)
{
qDebug()<<"Get Shell_TrayWnd error!\n";
return false;
}
HWND hNotify=FindWindowEx(hStatus,NULL,"TrayNotifyWnd",NULL); //右下角區域
if (hNotify==NULL)
{
qDebug()<<"Get TrayNotifyWnd error!\n";
return false;
}
HWND hNotify1=FindWindowEx(hNotify,NULL,"SysPager",NULL);
if (hNotify==NULL)
{
qDebug()<<"Get SysPager error!\n";
return false;
}
HWND hNotify1_0=FindWindowEx(hNotify1,NULL,"ToolBarWindow32",NULL);//右下角區域(不包括時間)
if (hNotify1_0==NULL)
{
qDebug()<<"Get ToolBarWindow64 error!\n";
return false;
}
//-------------------以上是得到工作列右下腳一塊地方的句柄-----------------//
DWORD pid = 0;
GetWindowThreadProcessId(hNotify1_0,&pid);
if (pid==NULL)
{
qDebug()<<"Get pid error!\n";
return false;
}
HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_ALL_ACCESS,true,pid);
if (hProcess==NULL)
{
qDebug()<<"Get hd error!\n";
return false;
}
::SendMessage(hNotify1_0,WM_PAINT ,NULL,NULL);
CRect rect;
::GetWindowRect(hNotify1_0,&rect);
::InvalidateRect(hNotify1_0,&rect,false);
int iNum=::SendMessage(hNotify1_0,TB_BUTTONCOUNT ,NULL,NULL); //擷取工作列上圖示個數
unsigned long n = 0;
TBBUTTON *pButton = new TBBUTTON;
CString strInfo = _T("");
wchar_t name[256] = {0};
TBBUTTON BButton;
unsigned long whd,proid;
CString x;
for(int i=0; i<iNum; i++)
{
::SendMessage(hNotify1_0,TB_GETBUTTON,i,(LPARAM)(&BButton));
ReadProcessMemory(hProcess,&BButton,pButton,sizeof(TBBUTTON),&n);
if (pButton->iString != 0xffffffff)
{
try
{
ReadProcessMemory(hProcess,(void *)pButton->iString,name,255,&n);
}
catch(...)
{
}
strInfo.Format("%d : %s\n",i+1,CString(name));
TRACE(strInfo);
qDebug()<<"strInfo = "<<strInfo<<endl;
}
try
{
whd=0;
ReadProcessMemory(hProcess,(void *)pButton->dwData,&whd,4,&n);
}
catch(...)
{
}
proid=NULL;
GetWindowThreadProcessId((HWND)whd,&proid);
if(proid==NULL)
::SendMessage(hNotify1_0,TB_DELETEBUTTON,i,0);
}
delete pButton;
return true;
}
注:上述代碼在XP中是可以用的,已經測試,但是,在win7中需要把加粗部分換成下面的代碼:
//擷取托盤溢出區域視窗句柄
HWND hStatus = ::FindWindow(_T("NotifyIconOverflowWindow"), NULL);
if (hStatus==NULL)
{
qDebug()<<"Get Shell_TrayWnd error!\n";
return false;
}
HWND hNotify1_0 = ::FindWindowEx(hStatus, NULL, _T("ToolbarWindow32"), NULL);
if (hNotify1_0==NULL)
{
qDebug()<<"Get TrayNotifyWnd error!\n";
return false;
}
但是,有時誤清除,會把其他的沒有結束的程序的圖示也關掉。還有待解決。。。