您的位置:首页 > 其它

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;

}

但是,有时误清除,会把其他的没有结束的进程的图标也关掉。还有待解决。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: