//////////////////////////////////////////////////////////////// #include "stdafx.h" #include "TrayIcon.h" IMPLEMENT_DYNAMIC(CTrayIcon, CCmdTarget) CTrayIcon::CTrayIcon(UINT uID) : m_SysToolBarHandle(NULL) { // Initialize NOTIFYICONDATA memset(&m_ID, 0 , sizeof(m_ID)); m_ID.cbSize = NOTIFYICONDATA_V3_SIZE; m_ID.uID = uID; // never changes after construction } CTrayIcon::~CTrayIcon() { SetIcon(0, NULL, NULL); // remove icon from system tray } /***************************************************************** **【函数名称】 SetNotificationWnd **【函数功能】 设置托盘图标消息的通知窗口 **【参数】 pNotifyWnd:窗口指针 uCbMsg:消息 **【返回值】 ****************************************************************/ void CTrayIcon::SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg) { ASSERT(pNotifyWnd==NULL || ::IsWindow(pNotifyWnd->GetSafeHwnd())); m_ID.hWnd = pNotifyWnd->GetSafeHwnd(); ASSERT(uCbMsg==0 || uCbMsg>=WM_USER); m_ID.uCallbackMessage = uCbMsg; } /***************************************************************** **【函数名称】 SetIcon **【函数功能】 设置托盘图标样式 **【参数】 uID:ICON ID hicon: ICON句柄 lpTip:提示消息 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ BOOL CTrayIcon::SetIcon(UINT uID, HICON hicon, LPCTSTR lpTip) { ASSERT((uID == 0) || (hicon == 0)); UINT msg; m_ID.uFlags = 0; if(uID) { hicon = AfxGetApp()->LoadIcon(uID); } // Set the icon if (hicon) { // Add or replace icon in system tray msg = m_ID.hIcon ? NIM_MODIFY : NIM_ADD; m_ID.hIcon = hicon; m_ID.uFlags |= NIF_ICON; } else { // remove icon from tray if (m_ID.hIcon==NULL) return TRUE; // already deleted msg = NIM_DELETE; } // Use the tip, if any if (lpTip) lstrcpyn(m_ID.szTip, lpTip, sizeof(m_ID.szTip)); if (m_ID.szTip[0]) m_ID.uFlags |= NIF_TIP; // Use callback if any if (m_ID.uCallbackMessage && m_ID.hWnd) m_ID.uFlags |= NIF_MESSAGE; // Do it BOOL bRet = Shell_NotifyIcon(msg, &m_ID); if (msg==NIM_DELETE || !bRet) m_ID.hIcon = NULL; // failed return bRet; } /***************************************************************** **【函数名称】 ShowBalloonTip **【函数功能】 托盘气泡通知消息 **【参数】 szMsg:消息内容 szTitle:消息标题 UINT:消息持续时间 dwInfoFlags:消息类型 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ BOOL CTrayIcon::ShowBalloonTip(LPCTSTR szMsg, LPCTSTR szTitle, UINT uTimeout, DWORD dwInfoFlags) { m_ID.cbSize = NOTIFYICONDATA_V3_SIZE; m_ID.uFlags = NIF_INFO; m_ID.uTimeout = uTimeout; m_ID.dwInfoFlags = dwInfoFlags; lstrcpy(m_ID.szInfo, szMsg ? szMsg : _T("")); lstrcpy(m_ID.szInfoTitle, szTitle ? szTitle : _T("")); return Shell_NotifyIcon(NIM_MODIFY, &m_ID); } /***************************************************************** **【函数名称】 SetTip **【函数功能】 设置托盘提示消息 **【参数】 szTip:提示内容 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ BOOL CTrayIcon::SetTip(LPCTSTR szTip) { m_ID.cbSize = NOTIFYICONDATA_V3_SIZE; m_ID.uFlags = NIF_TIP; lstrcpy(m_ID.szTip, szTip ? szTip : _T("")); return Shell_NotifyIcon(NIM_MODIFY, &m_ID); } /***************************************************************** **【函数名称】 FindTrayWnd **【函数功能】 获取托盘区域的窗口句柄 **【参数】 **【返回值】 托盘区域的窗口句柄 ****************************************************************/ HWND CTrayIcon::__FindTrayWnd(void) { 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 == NULL) hWnd = FindWindowEx(hWnd, 0, _T("ToolbarWindow32"), NULL); else hWnd = FindWindowEx(hWndPaper, 0, _T("ToolbarWindow32"), NULL); } } return hWnd; } /***************************************************************** **【函数名称】 EnumTrayIcon **【函数功能】 枚举托盘区域所有图标为获取本图标的Rect数据 **【参数】 hWnd: 系统托盘窗口句柄 rect:本图标Rect值 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ BOOL CTrayIcon::__EnumTrayIcon( HWND hWnd, RECT &rect ) { BOOL bSuc = FALSE; unsigned long lngPID = 0; long ret = 0; long lngButtons = 0; long lngHwndAdr = 0; long lngHwnd = 0; HANDLE hProcess = NULL; LPVOID lngAddress = NULL; LPVOID LPlngRect = 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); LPlngRect = VirtualAllocEx(hProcess, 0, sizeof(RECT), MEM_COMMIT, PAGE_READWRITE); lngButtons = SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0); //发送消息获取托盘button数量 if(lngAddress != NULL && LPlngRect != NULL) { for(int i = 0; i < lngButtons; i++) { RECT rc = { 0 }; int j = i; SendMessage(hWnd, TB_GETBUTTON, j, long(lngAddress)); //发送消息获取托盘项数据起始地址 //ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + 4), &m_IconBtnID, 4, 0); //获取buttonID 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_ID.hWnd)) //即我们要找的ICON { SendMessage(hWnd, TB_GETITEMRECT, (WPARAM)j, (LPARAM)LPlngRect); //发送消息获取托盘项区域数据 ret = ReadProcessMemory(hProcess, LPlngRect, &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(LPlngRect != NULL) { VirtualFreeEx(hProcess, LPlngRect, sizeof(RECT), MEM_DECOMMIT); VirtualFreeEx(hProcess, LPlngRect, 0, MEM_RELEASE); } CloseHandle(hProcess); } } } return bSuc; } /***************************************************************** **【函数名称】 FindNotifyIconOverflowWindow **【函数功能】 获取溢出托盘区域的窗口句柄(WIN7适用) **【参数】 **【返回值】 托盘区域的窗口句柄 ****************************************************************/ HWND CTrayIcon::__FindNotifyIconOverflowWindow( void ) { HWND hwnd = NULL; hwnd = FindWindow(_T("NotifyIconOverflowWindow"), NULL); if(hwnd != NULL) { hwnd = FindWindowEx(hwnd, NULL, _T("ToolbarWindow32"), NULL); } return hwnd; } /***************************************************************** **【函数名称】 __GetDefaultHideRect **【函数功能】 获取托盘图标区域失败时给出缺省RECT **【参数】 **【返回值】 ****************************************************************/ void CTrayIcon::__GetDefaultHideRect( RECT& rect ) { int Wideth = GetSystemMetrics(SM_CXSCREEN); int Height = GetSystemMetrics(SM_CYSCREEN); rect.left = Wideth - 10; rect.right = Wideth; rect.top = Height - 10; rect.bottom = Height; } /***************************************************************** **【函数名称】 GetTrayRect **【函数功能】 获取本图标的Rect数据 **【参数】 **【返回值】 成功图标的Rect数据,失败Rect{ 0 } ****************************************************************/ RECT CTrayIcon::GetTrayRect( void ) { RECT rect = { 0 }; if(m_SysToolBarHandle != NULL) { __EnumTrayIcon(m_SysToolBarHandle, rect); } else { m_SysToolBarHandle = __FindTrayWnd(); if(m_SysToolBarHandle != NULL) { if(!__EnumTrayIcon(m_SysToolBarHandle, rect)) { m_SysToolBarHandle = __FindNotifyIconOverflowWindow(); //在溢出区(win7) if(m_SysToolBarHandle != NULL) { __EnumTrayIcon(m_SysToolBarHandle, rect); } } } } if(IsRectEmpty(&rect)) __GetDefaultHideRect(rect); return rect; }