中间件标准版5.1git,去除基础模块

TrayIcon.cpp 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. ////////////////////////////////////////////////////////////////
  2. #include "stdafx.h"
  3. #include "TrayIcon.h"
  4. IMPLEMENT_DYNAMIC(CTrayIcon, CCmdTarget)
  5. CTrayIcon::CTrayIcon(UINT uID) : m_SysToolBarHandle(NULL)
  6. {
  7. // Initialize NOTIFYICONDATA
  8. memset(&m_ID, 0 , sizeof(m_ID));
  9. m_ID.cbSize = NOTIFYICONDATA_V3_SIZE;
  10. m_ID.uID = uID; // never changes after construction
  11. }
  12. CTrayIcon::~CTrayIcon()
  13. {
  14. SetIcon(0, NULL, NULL); // remove icon from system tray
  15. }
  16. /*****************************************************************
  17. **【函数名称】 SetNotificationWnd
  18. **【函数功能】 设置托盘图标消息的通知窗口
  19. **【参数】 pNotifyWnd:窗口指针
  20. uCbMsg:消息
  21. **【返回值】
  22. ****************************************************************/
  23. void CTrayIcon::SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg)
  24. {
  25. ASSERT(pNotifyWnd==NULL || ::IsWindow(pNotifyWnd->GetSafeHwnd()));
  26. m_ID.hWnd = pNotifyWnd->GetSafeHwnd();
  27. ASSERT(uCbMsg==0 || uCbMsg>=WM_USER);
  28. m_ID.uCallbackMessage = uCbMsg;
  29. }
  30. /*****************************************************************
  31. **【函数名称】 SetIcon
  32. **【函数功能】 设置托盘图标样式
  33. **【参数】 uID:ICON ID
  34. hicon: ICON句柄
  35. lpTip:提示消息
  36. **【返回值】 成功TRUE,失败FALSE
  37. ****************************************************************/
  38. BOOL CTrayIcon::SetIcon(UINT uID, HICON hicon, LPCTSTR lpTip)
  39. {
  40. ASSERT((uID == 0) || (hicon == 0));
  41. UINT msg;
  42. m_ID.uFlags = 0;
  43. if(uID)
  44. {
  45. hicon = AfxGetApp()->LoadIcon(uID);
  46. }
  47. // Set the icon
  48. if (hicon)
  49. {
  50. // Add or replace icon in system tray
  51. msg = m_ID.hIcon ? NIM_MODIFY : NIM_ADD;
  52. m_ID.hIcon = hicon;
  53. m_ID.uFlags |= NIF_ICON;
  54. }
  55. else
  56. { // remove icon from tray
  57. if (m_ID.hIcon==NULL)
  58. return TRUE; // already deleted
  59. msg = NIM_DELETE;
  60. }
  61. // Use the tip, if any
  62. if (lpTip)
  63. lstrcpyn(m_ID.szTip, lpTip, sizeof(m_ID.szTip));
  64. if (m_ID.szTip[0])
  65. m_ID.uFlags |= NIF_TIP;
  66. // Use callback if any
  67. if (m_ID.uCallbackMessage && m_ID.hWnd)
  68. m_ID.uFlags |= NIF_MESSAGE;
  69. // Do it
  70. BOOL bRet = Shell_NotifyIcon(msg, &m_ID);
  71. if (msg==NIM_DELETE || !bRet)
  72. m_ID.hIcon = NULL; // failed
  73. return bRet;
  74. }
  75. /*****************************************************************
  76. **【函数名称】 ShowBalloonTip
  77. **【函数功能】 托盘气泡通知消息
  78. **【参数】 szMsg:消息内容
  79. szTitle:消息标题
  80. UINT:消息持续时间
  81. dwInfoFlags:消息类型
  82. **【返回值】 成功TRUE,失败FALSE
  83. ****************************************************************/
  84. BOOL CTrayIcon::ShowBalloonTip(LPCTSTR szMsg, LPCTSTR szTitle, UINT uTimeout, DWORD dwInfoFlags)
  85. {
  86. m_ID.cbSize = NOTIFYICONDATA_V3_SIZE;
  87. m_ID.uFlags = NIF_INFO;
  88. m_ID.uTimeout = uTimeout;
  89. m_ID.dwInfoFlags = dwInfoFlags;
  90. lstrcpy(m_ID.szInfo, szMsg ? szMsg : _T(""));
  91. lstrcpy(m_ID.szInfoTitle, szTitle ? szTitle : _T(""));
  92. return Shell_NotifyIcon(NIM_MODIFY, &m_ID);
  93. }
  94. /*****************************************************************
  95. **【函数名称】 SetTip
  96. **【函数功能】 设置托盘提示消息
  97. **【参数】 szTip:提示内容
  98. **【返回值】 成功TRUE,失败FALSE
  99. ****************************************************************/
  100. BOOL CTrayIcon::SetTip(LPCTSTR szTip)
  101. {
  102. m_ID.cbSize = NOTIFYICONDATA_V3_SIZE;
  103. m_ID.uFlags = NIF_TIP;
  104. lstrcpy(m_ID.szTip, szTip ? szTip : _T(""));
  105. return Shell_NotifyIcon(NIM_MODIFY, &m_ID);
  106. }
  107. /*****************************************************************
  108. **【函数名称】 FindTrayWnd
  109. **【函数功能】 获取托盘区域的窗口句柄
  110. **【参数】
  111. **【返回值】 托盘区域的窗口句柄
  112. ****************************************************************/
  113. HWND CTrayIcon::__FindTrayWnd(void)
  114. {
  115. HWND hWnd = NULL;
  116. HWND hWndPaper = NULL;
  117. if((hWnd = FindWindow(_T("Shell_TrayWnd"), NULL)) != NULL)
  118. {
  119. if((hWnd = FindWindowEx(hWnd, 0, _T("TrayNotifyWnd"), NULL)) != NULL)
  120. {
  121. hWndPaper = FindWindowEx(hWnd, 0, _T("SysPager"), NULL);
  122. if(hWndPaper == NULL)
  123. hWnd = FindWindowEx(hWnd, 0, _T("ToolbarWindow32"), NULL);
  124. else
  125. hWnd = FindWindowEx(hWndPaper, 0, _T("ToolbarWindow32"), NULL);
  126. }
  127. }
  128. return hWnd;
  129. }
  130. /*****************************************************************
  131. **【函数名称】 EnumTrayIcon
  132. **【函数功能】 枚举托盘区域所有图标为获取本图标的Rect数据
  133. **【参数】 hWnd: 系统托盘窗口句柄
  134. rect:本图标Rect值
  135. **【返回值】 成功TRUE,失败FALSE
  136. ****************************************************************/
  137. BOOL CTrayIcon::__EnumTrayIcon( HWND hWnd, RECT &rect )
  138. {
  139. BOOL bSuc = FALSE;
  140. unsigned long lngPID = 0;
  141. long ret = 0;
  142. long lngButtons = 0;
  143. long lngHwndAdr = 0;
  144. long lngHwnd = 0;
  145. HANDLE hProcess = NULL;
  146. LPVOID lngAddress = NULL;
  147. LPVOID LPlngRect = NULL;
  148. if(hWnd != NULL)
  149. {
  150. ret = GetWindowThreadProcessId(hWnd, &lngPID);
  151. if(ret != 0 && lngPID != 0)
  152. {
  153. hProcess = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, lngPID);
  154. if(hProcess != NULL)
  155. {
  156. lngAddress = VirtualAllocEx(hProcess, 0, 0x4096, MEM_COMMIT, PAGE_READWRITE);
  157. LPlngRect = VirtualAllocEx(hProcess, 0, sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);
  158. lngButtons = SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0); //发送消息获取托盘button数量
  159. if(lngAddress != NULL && LPlngRect != NULL)
  160. {
  161. for(int i = 0; i < lngButtons; i++)
  162. {
  163. RECT rc = { 0 };
  164. int j = i;
  165. SendMessage(hWnd, TB_GETBUTTON, j, long(lngAddress)); //发送消息获取托盘项数据起始地址
  166. //ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + 4), &m_IconBtnID, 4, 0); //获取buttonID
  167. ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + 12), &lngHwndAdr, 4, 0); //获取句柄地址
  168. if(ret != 0 && lngHwndAdr != -1)
  169. {
  170. ret = ReadProcessMemory(hProcess, LPVOID(lngHwndAdr), &lngHwnd, 4, 0); //获取句柄
  171. if((ret != 0) && ((HWND)lngHwnd == m_ID.hWnd)) //即我们要找的ICON
  172. {
  173. SendMessage(hWnd, TB_GETITEMRECT, (WPARAM)j, (LPARAM)LPlngRect); //发送消息获取托盘项区域数据
  174. ret = ReadProcessMemory(hProcess, LPlngRect, &rc, sizeof(rc), 0); //读取托盘区域数据
  175. if(ret != 0)
  176. {
  177. CWnd::FromHandle(hWnd)->ClientToScreen(&rc);
  178. rect = rc;
  179. }
  180. bSuc = TRUE;//在普通托盘区找到,在溢出区不再查找
  181. break;
  182. }
  183. }
  184. }
  185. }
  186. if(lngAddress != NULL)
  187. {
  188. VirtualFreeEx(hProcess, lngAddress, 0x4096, MEM_DECOMMIT);
  189. VirtualFreeEx(hProcess, lngAddress, 0, MEM_RELEASE);
  190. }
  191. if(LPlngRect != NULL)
  192. {
  193. VirtualFreeEx(hProcess, LPlngRect, sizeof(RECT), MEM_DECOMMIT);
  194. VirtualFreeEx(hProcess, LPlngRect, 0, MEM_RELEASE);
  195. }
  196. CloseHandle(hProcess);
  197. }
  198. }
  199. }
  200. return bSuc;
  201. }
  202. /*****************************************************************
  203. **【函数名称】 FindNotifyIconOverflowWindow
  204. **【函数功能】 获取溢出托盘区域的窗口句柄(WIN7适用)
  205. **【参数】
  206. **【返回值】 托盘区域的窗口句柄
  207. ****************************************************************/
  208. HWND CTrayIcon::__FindNotifyIconOverflowWindow( void )
  209. {
  210. HWND hwnd = NULL;
  211. hwnd = FindWindow(_T("NotifyIconOverflowWindow"), NULL);
  212. if(hwnd != NULL)
  213. {
  214. hwnd = FindWindowEx(hwnd, NULL, _T("ToolbarWindow32"), NULL);
  215. }
  216. return hwnd;
  217. }
  218. /*****************************************************************
  219. **【函数名称】 __GetDefaultHideRect
  220. **【函数功能】 获取托盘图标区域失败时给出缺省RECT
  221. **【参数】
  222. **【返回值】
  223. ****************************************************************/
  224. void CTrayIcon::__GetDefaultHideRect( RECT& rect )
  225. {
  226. int Wideth = GetSystemMetrics(SM_CXSCREEN);
  227. int Height = GetSystemMetrics(SM_CYSCREEN);
  228. rect.left = Wideth - 10;
  229. rect.right = Wideth;
  230. rect.top = Height - 10;
  231. rect.bottom = Height;
  232. }
  233. /*****************************************************************
  234. **【函数名称】 GetTrayRect
  235. **【函数功能】 获取本图标的Rect数据
  236. **【参数】
  237. **【返回值】 成功图标的Rect数据,失败Rect{ 0 }
  238. ****************************************************************/
  239. RECT CTrayIcon::GetTrayRect( void )
  240. {
  241. RECT rect = { 0 };
  242. if(m_SysToolBarHandle != NULL)
  243. {
  244. __EnumTrayIcon(m_SysToolBarHandle, rect);
  245. }
  246. else
  247. {
  248. m_SysToolBarHandle = __FindTrayWnd();
  249. if(m_SysToolBarHandle != NULL)
  250. {
  251. if(!__EnumTrayIcon(m_SysToolBarHandle, rect))
  252. {
  253. m_SysToolBarHandle = __FindNotifyIconOverflowWindow(); //在溢出区(win7)
  254. if(m_SysToolBarHandle != NULL)
  255. {
  256. __EnumTrayIcon(m_SysToolBarHandle, rect);
  257. }
  258. }
  259. }
  260. }
  261. if(IsRectEmpty(&rect))
  262. __GetDefaultHideRect(rect);
  263. return rect;
  264. }