隐藏Windows系统托盘图标(改进版)

    在上一篇文章 中,写了一个sample ,用于隐藏图标,但是有网友提出,能不能在程序界面上显示当前的托盘图标,这样更直观一些。这一点我也曾想到过,也知道奥秘就在TBBUTTON这个结构体的dwData域里面,可惜这个域的结构在MSDN 中没有描述。我也曾试着发送TB_GETIMAGELIST消息获取image list的句柄,然后用CImageList::FromHandle加载到CImageList中,但却都失败了。

    在csdn 网友的帮助下,我弄清了dwData的结构,并据此改进了程序,下面的截图是改进版运行的画面。
    隐藏Windows系统托盘图标(改进版)_第1张图片

    其实dwData有一个这样的机构,我们命名为TRAYDATA:

  1. struct  TRAYDATA
  2. {
  3.      HWND  hwnd;                  
  4.      UINT  uID;               
  5.      UINT  uCallbackMessage;      
  6.      DWORD  Reserved[2];          
  7.      HICON  hIcon;                 //托盘图标的句柄
  8. }; 

    要获取到这个hIcon,其实很简单:

  1. //分配虚拟内存
  2. lngAddress = VirtualAllocEx(hProcess,  NULL,   sizeof (TBBUTTON), MEM_COMMIT, PAGE_READWRITE); 
  3.   
  4. //将hProcess进程内,地址为lngAddress中的内容(大小为sizeof(TBBUTTON))获取到tb中
  5. ret = ::ReadProcessMemory(hProcess, LPVOID( long (lngAddress)), &tb,  sizeof (TBBUTTON), 0);

  6. //将hProcess进程内,地址为tb.dwData中的内容(大小为sizeof(TRAYDATA))获取到tray中
  7. ret = ::ReadProcessMemory(hProcess, LPVOID(tb.dwData), &tray,  sizeof (TRAYDATA), 0);

    然后就可以用tray.hIcon索引到这个图标句柄了,此外我们还可以用tray.hwnd获取到它所在进程的执行路径,最后我们添加一个CListControl控件,并在OnInitDialog()过程中进行控件的初始化:

  1. m_ImageList.Create(16,16,ILC_COLOR24,16,16);
  2. m_ListCtl.SetImageList(&m_ImageList,LVSIL_SMALL);    
  3. m_ListCtl.SetExtendedStyle(LVS_EX_FULLROWSELECT);
  4. m_ListCtl.InsertColumn(0,  "图标" , LVCFMT_LEFT, 50);
  5. m_ListCtl.InsertColumn(1,  "应用程序路径" , LVCFMT_LEFT, 500);
  6. m_ListCtl.InsertColumn(2,  "提示信息" , LVCFMT_LEFT,300);

    最后将获取到的信息填入这个控件中:

  1.         lv.iSubItem = 0;
  2.         lv.mask = LVIF_IMAGE;
  3.         lv.iItem = m_ListCtl.GetItemCount();
  4.     
  5.          if (GetIconInfo(tray.hIcon,&icon_info) != 0)
  6.         {           
  7.                 lv.iImage = m_ImageList.Add(tray.hIcon);
  8.                 ::ZeroMemory(&icon_info, sizeof (ICONINFO));
  9.         }
  10.         m_TifoVec.push_back(tifo);
  11.          int  index = m_ListCtl.InsertItem(&lv);
  12.         m_ListCtl.SetItemText(index,1,GetFilenameFromPid(dwProcessId));
  13.          if (!(tb.fsState&TBSTATE_HIDDEN))
  14.         {
  15.             ret = ::ReadProcessMemory(hProcess, LPVOID (tb.iString),&strBuff,1024,0);
  16.             USES_CONVERSION;
  17.             m_ListCtl.SetItemText(index,2,OLE2T((LPOLESTR)(strBuff)));
  18.         }
  19.          else
  20.         {
  21.              m_ListCtl.SetItemText(index,2, "[Hidden Icon]" );
  22.         }

    此外,因为我们能得到进程id,所以可以有更多的应用,这里就不演示了,这个改进版的代码可以在这里下载 。

你可能感兴趣的:(Visual,C++)