XP/WIN7系统中删除已结束进程托盘图标的方法
2014-05-07 18:30
615 查看
===============================下面这些很好====================================
//本例以获取程序托盘图标位置为例
//根据需要还可以获取不少信息
参考:http://www.cnblogs.com/daxingxing/archive/2012/02/06/2340384.html
[cpp] view
plaincopy
//获取托盘区域数据
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
plaincopy
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
plaincopy
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
plaincopy
#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
plaincopy
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
plaincopy
//获取托盘溢出区域窗口句柄
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;
}
但是,有时误清除,会把其他的没有结束的进程的图标也关掉。还有待解决。。。
//本例以获取程序托盘图标位置为例
//根据需要还可以获取不少信息
参考:http://www.cnblogs.com/daxingxing/archive/2012/02/06/2340384.html
[cpp] view
plaincopy
//获取托盘区域数据
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
plaincopy
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
plaincopy
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
plaincopy
#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
plaincopy
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
plaincopy
//获取托盘溢出区域窗口句柄
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;
}
但是,有时误清除,会把其他的没有结束的进程的图标也关掉。还有待解决。。。
相关文章推荐
- XP/WIN7系统中删除残留托盘图标的方法
- XP/WIN7系统中删除残留托盘图标的方法
- 删除EM,强制结束EM进程后,启动数据库ORA-00119,ORA-00132报错的解决方法
- Win7系统删除桌面上多余图标的方法
- Win7系统托盘图标消失怎么办?Win7托盘图标消失的解决方法
- Win7系统托盘图标居中方法与设置技巧(图文步骤)
- 删除EM,强制结束EM进程后,启动数据库ORA-00119,ORA-00132报错的解决方法
- win7系统删除资源管理器左侧的家庭组图标方法图解
- 删除已知进程ID的程序的系统托盘中的图标
- 删除已知进程ID的程序的系统托盘中的图标
- Win7怎么删除Nvidia图标?Win7系统删除Nvidia图标的方法
- Win7系统提示文件或文件夹不能删除的解决方法
- Linux父进程创建子进程的方法,监控子进程的结束
- Windows中根据端口号或PID查看进程、结束进程方法
- Android后台强制结束进程,Application入口或者activity回调的是哪个方法?
- 神代码,结束进程神方法
- linux内核模块的强制删除-结束rmmod这类disk sleep进程
- Android下结束进程的方法
- 删除win7系统中多余的本地连接的方法
- Win7系统删除开始菜单里的气泡提示的方法