关闭

关于系统托盘图标的小问题

1151人阅读 评论(0) 收藏 举报

    昨天同事写一个进程的守护程序,实时监控另一个进程,如果异常退出则重新加载该进程。问题的描述大致如此。按道理说,通过一个进程来监控另一个进程问题不大。然而被监控进程是一个最小化托盘的程序,在其异常退出后没有自己清除系统托盘里的图标。这样,经过几次异常退出,重新加载的轮回,系统托盘里就快排满了一个足球队的Icon。看上去尉为壮观。

    很多时候我们也有这样的经验,在托盘程序异常退出的时候自身的图标往往不能自我清除,这大多是许多应用程序自身异常检测机制中没有去清除的缘故,但原因也不仅限于此。此时我们用鼠标hover过这些图标区域,哪些dead icon自然就清除掉了。因此我们自然想到了在守护进程中,每次检测到被守护进程异常退出时候,首先将鼠标set过托盘区域,模拟人手操作的过程,最后再复原到原有position。实时说明,这样做的效果是不错的。由于内部处理速度极快,用户根本觉察不到鼠标的移动过程,这样就实现了自动清除dead icon的目的。

    下面把这段儿代码共享一下:

{  刷新系统托盘图标}
procedure RefreshTrayIcon;
var
  TrayWindow : HWnd;
  WindowRect : TRect;
  SmallIconWidth : Integer;
  SmallIconHeight : Integer;
  CursorPos : TPoint;
  Row : Integer;
  Col : Integer;
begin
  { Get tray window handle and bounding rectangle }
  TrayWindow := FindWindowEx(FindWindow('Shell_TrayWnd',NIL),0,'TrayNotifyWnd',NIL);
  if not GetWindowRect(TrayWindow,WindowRect) then Exit;
  { Get small icon metrics }
  SmallIconWidth := GetSystemMetrics(SM_CXSMICON);
  SmallIconHeight := GetSystemMetrics(SM_CYSMICON);
  { Save current mouse position }
  GetCursorPos(CursorPos);
  { Sweep the mouse cursor over each icon in the tray in both dimensions }
  with WindowRect do
    for Row := 0 to (Bottom - Top) DIV SmallIconHeight do
      for Col := 0 to (Right - Left) DIV SmallIconWidth do
        begin
        SetCursorPos(Left + Col * SmallIconWidth, Top + Row * SmallIconHeight);
        Sleep(0);
        end;
  { Restore mouse position }
  SetCursorPos(CursorPos.X,CursorPos.Y);
  { Redraw tray window (to fix bug in multi-line tray area) }
  RedrawWindow(TrayWindow,NIL,0,RDW_INVALIDATE OR RDW_ERASE OR RDW_UPDATENOW);

end;

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:645273次
    • 积分:7675
    • 等级:
    • 排名:第2947名
    • 原创:77篇
    • 转载:153篇
    • 译文:12篇
    • 评论:158条
    最新评论
    Famous people