我给我的程序按照网上的教程,设置了系统托盘图标,代码://实现系统托盘图标
  ntida.cbSize:=sizeof(tnotifyicondataa);
  ntida.Wnd:=handle; 
  ntida.uID:=1;
  ntida.uFlags:=nif_icon+nif_tip+nif_message;
  ntida.uCallbackMessage:=mousemsg;
  ntida.hIcon:=Application.Icon.handle;
  ntida.szTip:='文档共享系统';
  shell_notifyicona(NIM_ADD, @ntida);   //在系统状态栏增加一个新图标运行后,系统托盘区多出一个位置,但是没有图标!或者说空图标!
关闭程序后,该空位消失!
已经在Project属性里面设置了Application的图标。也改过图标,仍然不行。
请教大家,这是怎么回事?

解决方案 »

  1.   


    {---------------------------}
         MyTrayIcon.cbSize :=sizeof(MyTrayIcon);
         MyTrayIcon.Wnd :=Handle;
         MyTrayIcon.uID :=100;//内部标识,可设为任意数
         MyTrayIcon.hIcon :=Application.Icon.Handle;
         MyTrayIcon.uCallbackMessage:=MYMESSAGE;//回调函数消息
         MyTrayIcon.szTip :='祥云复烤厂LED监控系统';
         MyTrayIcon.uFlags :=NIF_ICON or NIF_TIP or NIF_MESSAGE;//指明哪些字段有效
         //将程序的窗口样式设为TOOL窗口,可避免在任务条上出现}
         //SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
         //向托盘中添加图标
         Shell_NotifyIcon(NIM_ADD,@MyTrayIcon);
      

  2.   

    转一个实现原理     
        
      任务栏状态区的图标添加、删除、以及修改是通过Windows   API函数Shell_NotifyIcon来实现的,该函数是由Windows的SHELL32.DLL动态联接库提供的。在Delphi中,Shell_NotifyIcon函数是在ShellAPI单元声明的,其     
        
      函数原型如下:     
        
      function   Shell_NotifyIcon(dwMessage:   DWORD;   lpData:   PNotifyIconData):   BOOL;   stdcall;     
        
      其中参数dwMessage的取值决定函数Shell_NotifyIcon所要进行的操作的类型,它的取值可以是以下三者之一:     
        
      NIM_ADD(值为0):在任务栏状态区插入一个图标。     
        
      NIM_DELETE(值为1):从任务栏状态区删除一个图标。     
        
      NIM_MODIFY(值为2):修改任务栏状态区的图标、提示信息、或者通知消息。     
        
      参数lpData   是一个记录类型(结构类型)的指针,记录类型NotifyIconData的定义如下:     
        
          NOTIFYICONDATA   =   record   
              cbSize:   DWORD;   
              Wnd:   HWND;   
              uID:   UINT;   
              uFlags:   UINT;   
              uCallbackMessage:   UINT;   
              hIcon:   HICON;   
              szTip:   array   [0..63]   of   AnsiChar;   
          end;   
      ----   cbSize:NOTIFYICONDATA记录的大小。     
        
      Wnd:与此状态区图标相关联的窗口句柄,此窗口将负责处理uCallbackMessage消息。     
        
      uID:程序自定义的状态区图标的标识符。     
        
      uFlags:这个字段指明NOTIFYICONDATA记录中的成员uCallbackMessage、hIcon和szTip这三者的哪些项的值有效。它的取值可以是下列三者的组合(or运算):     
        
      NIF_MESSAGE   (值为1):uCallbackMessage项包含了有效的信息。     
        
      NIF_ICON(值为2):hIcon项包含了有效的信息。     
        
      NIF_TIP(值为4):   szTip项包含了有效的信息。     
        
      uCallbackMessage:程序定义的消息标识符(32位的整数)。当鼠标在状态区图标上移动或者点击(即,发生了鼠标事件)时,操作系统将向Wnd指定的那个窗口发送uCallbackMessage消息。在uCallbackMessage消息中,lParam参数包含了Windows的鼠标消息的类型,而wParam参数则包含了图标标识(即uID)。有效的鼠标消息包括以下几个:WM_LBUTTONDOWN、WM_RBUTTONDOWN、WM_MBUTTONDOWN、WM_LBUTTONUP、WM_RBUTTONUP、WM_MBUTTONUP、WM_MOUSEMOVE、WM_LBUTTONDBLCLK、WM_RBUTTONDBLCLK以及WM_MBUTTONDBLCLK。     
        
      hIcon:指定一个图标句柄。     
        
      szTip:显示在图标上的提示信息(少于63个字符)。     
        
      Delphi中的实现     
        
      通过上面的介绍中,我们不难看出,任务栏状态区的编程主要是处理两方面的工作:添加、删除、修改图标;以及处理通知消息。对于图标的添加、删除、修改操作,可以通过调用Shell_NotifyIcon函数来实现。而对于自定义的通知消息,我们就应该在消息循环中给予处理了。     
        
      下面的示例给出了状态区图标的添加、修改和删除操作的例子,以及图标的通知消息的基本处理框架。     
        
      unit   Unit1;   
        
      interface   
        
      uses   
          Windows,   Messages,   SysUtils,   Classes,   Graphics,   
          Controls,   Forms,   Dialogs,   ExtCtrls,   ShellAPI;   
        
      const   
          WM_TRAYNOTIFY=WM_USER+1;//定义通知消息   
        
      type   
          TForm1   =   class(TForm)   
              Timer1:   TTimer;   
              procedure   FormCreate(Sender:   TObject);   
              procedure   Timer1Timer(Sender:   TObject);   
              procedure   FormDestroy(Sender:   TObject);   
          private   
              {   Private   declarations   }   
          public   
              {   Public   declarations   }   
              procedure   WndProc(var   Msg:   TMessage);   override;   
          end;   
        
      var   
          Form1:   TForm1;   
          nd0,   nd1:NotifyIconData;   
          hs:array[0..9]of   LongWord;   
        
      implementation   
      {$R   *.DFM}   
        
      procedure   TForm1.FormCreate(Sender:   TObject);   
      begin   
          //加载Icon0..Icon9这10个图标资源,   
      并且保存它们的句柄。   
          //图标Icon0..Icon9分别对应与0..9这9个数字。   
          hs[0]:=LoadIcon(hInstance,   'Icon0');   
          hs[1]:=LoadIcon(hInstance,   'Icon1');   
          hs[2]:=LoadIcon(hInstance,   'Icon2');   
          hs[3]:=LoadIcon(hInstance,   'Icon3');   
          hs[4]:=LoadIcon(hInstance,   'Icon4');   
          hs[5]:=LoadIcon(hInstance,   'Icon5');   
          hs[6]:=LoadIcon(hInstance,   'Icon6');   
          hs[7]:=LoadIcon(hInstance,   'Icon7');   
          hs[8]:=LoadIcon(hInstance,   'Icon8');   
          hs[9]:=LoadIcon(hInstance,   'Icon9');   
        
          //填充NotifyIconData记录型变量nd0   
          nd0.cbSize   :=   sizeof(NotifyIconData);   
          nd0.Wnd   :=   handle;   
          nd0.uID   :=   0;   
          nd0.uFlags   :=   NIF_MESSAGE   or   NIF_ICON   or   NIF_TIP;   
          nd0.uCallbackMessage   :=   WM_TRAYNOTIFY;   
          nd0.hIcon   :=   hs[0];   
          StrPLCopy(nd0.szTip,   'Hello,   World!',   63);   
        
          //填充NotifyIconData记录型变量nd1   
          nd1.cbSize   :=   sizeof(NotifyIconData);   
          nd1.Wnd   :=   handle;   
          nd1.uID   :=   1;   
          nd1.uFlags   :=   NIF_MESSAGE   or   NIF_ICON   or   NIF_TIP;   
          nd1.uCallbackMessage   :=   WM_TRAYNOTIFY;   
          nd1.hIcon   :=   hs[0];   
          StrPLCopy(nd1.szTip,   'Simon   Loves   Daisy',   63);   
        
          //在任务栏状态区添加图标   
          Shell_NotifyIcon(NIM_ADD,   @nd0);   
          Shell_NotifyIcon(NIM_ADD,   @nd1);   
      end;   
        
      procedure   TForm1.Timer1Timer(Sender:   TObject);   
      var   
          st:SystemTime;   
      begin   
          //每秒钟更新一次图标:图标0显示秒数的十位,   
      图标1显示秒数的个位。   
          GetLocalTime(st);   
          nd0.hIcon   :=   hs[st.wSecond   div   10];   
          nd1.hIcon   :=   hs[st.wSecond   mod   10];   
          //修改任务栏状态区的图标   
          Shell_NotifyIcon(NIM_MODIFY,   @nd0);   
          Shell_NotifyIcon(NIM_MODIFY,   @nd1);   
      end;   
        
      procedure   TForm1.FormDestroy(Sender:   TObject);   
      begin   
          //将图标从任务栏状态区删除   
          Shell_NotifyIcon(NIM_DELETE,   @nd0);   
          Shell_NotifyIcon(NIM_DELETE,   @nd1);   
      end;   
        
      //处理   通知消息   
      procedure   TForm1.WndProc(var   Msg:   TMessage);   
      var   
          IconID:integer;   
          pt:TPOINT;   
      begin   
          if   msg.Msg   =   WM_TRAYNOTIFY   then   
          begin   
          {   
          在通知消息中,wParam参数为图标的uID,   
          lParam参数为鼠标事件的类型。   
          }   
              iconID   :=   msg.WParam;   
              //获取鼠标的在屏幕上的位置   
              GetCursorPos(pt);   
        
          //通知消息的处理的基本框架结构如下:   
              case   msg.lParam   of   
                  WM_LBUTTONDOWN:   
                  begin   
                      //鼠标右键被按下   
                  end;   
                  WM_RBUTTONDOWN:   
                  begin   
                      //鼠标左键被按下   
                  end;   
                  WM_LBUTTONUP:   
                  begin   
                      //释放鼠标左键   
                  end;   
                  WM_RBUTTONUP:   
                  begin   
                      //释放鼠标右键   
                  end;   
                  WM_MOUSEMOVE:   
                  begin   
                      //鼠标在图标上移动   
                  end;   
                  WM_LBUTTONDBLCLK:   
                  begin   
                      //鼠标左键双击   
                  end;   
                  WM_RBUTTONDBLCLK:   
                  begin   
                      //鼠标右键双击   
                  end;   
              end;   //end   case   
          end   
          else//调用父类的WndProc方法处理其它消息   
              inherited;   
      end;   
        
      end.   
      

  3.   


    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs,Menus,shellAPI;
      const WM_MYTRAYICONCALLBACK = WM_USER + 1000 ;type
      TForm1 = class(TForm)
        PopupMenu1: TPopupMenu;
        dd1: TMenuItem;
        dsa1: TMenuItem;
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
      MyTrayIcon : TNotifyIconData ;
    procedure WMMyTrayIconCallBack(Var Msg : TMessage); message WM_MYTRAYICONCALLBACK ;
    //托盘消息处理过程
    procedure WMCommand(Var msg : TWMCommand); message WM_Command;
    //处理托盘图标的右键菜单事件
    procedure Minimize(var mess:TWMNCLBUTTONDOWN); message WM_NCLBUTTONDOWN;
    //窗体最小化时的消息处理    { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    begin
    //设置托盘
    Icon.Handle := LoadIcon(Hinstance,'MAINICON');
    MyTrayIcon.cbSize := SizeOf(TNotifyIconData);// nid变量的字节数
    MyTrayIcon.Wnd := Handle ;// 主窗口句柄
    MyTrayIcon.uID := 1 ;// 内部标识,可设为任意数
    MyTrayIcon.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE ;// 指明哪些字段有效
    MyTrayIcon.uCallBackMessage := WM_MYTRAYICONCALLBACK ;//回调函数消息,将自定义托盘消息传递进去
    MyTrayIcon.hIcon := Application.Icon.Handle; // 要加入的图标句柄,可任意指定
    StrCopy(MyTrayIcon.szTip, PChar(Caption));
    Shell_NotifyIcon(NIM_ADD,@MyTrayIcon);
    ShowWindow(Handle,sw_Hide);
    // Visible := False ;//当程序启动时就最小化在托盘区即Form.Create时启用此语句
    Application.ShowMainForm := False ;
    SetForegroundWindow(Application.Handle);
    end;////消息过程实现
    procedure TForm1.WMMyTrayIconCallBack(var Msg: TMessage);
    var CursorPos : TPoint;
    begin
    case Msg.LParam of
    WM_LBUTTONDBLCLK : //双击消息:弹出主窗口
    begin
    Visible := not Visible ;
    Application.ShowMainForm := Visible ;
    SetForegroundWindow(Application.Handle);
    end ;
    WM_RBUTTONDOWN : //鼠标右键:弹出菜单
    begin
    GetCursorPos(CursorPos);
    PopupMenu1.Popup(cursorpos.x,cursorpos.y);
    { Popupmenu1.Popup(CursorPos.X,CursorPos.Y);
    popupmen1里面就可以加入显示主窗口、退出等功能。这个右键菜单可以是静态的,如上面一句来弹出;也可以动态建立,如下面所示的方法:}
    //pm := createpopupmenu;//建立一个Hmenu,pm:hmenu;
    //AppendMenu(pm,0,ord('A'),'关于....');//在指定的菜单里添加一个菜单项
    //AppendMenu(pm,0,Ord('B'),'&Exit');
    //加入菜单事件---》处理WMCOMMAND消息即可
    //TrackPopupMenu(pm,Tpm_BottomAlign or Tpm_RightAlign, CursorPos.x, CursorPos.y, 0,handle,nil);
    //在图标上方显示该弹出式菜单
    end ;
    end ;
    end;procedure TForm1.WMCommand(var msg : TWMCommand);
    begin
    Case msg.ItemID of
    Ord('A') : showmessage('我的右键菜单!');
    Ord('B') : Self.close;//关闭程序主窗体
    else inherited;
    end;
    end;procedure Tform1.Minimize(var mess:TWMNCLBUTTONDOWN);//应用程序最小化消息处理
    begin
    if Mess.Hittest = htReduce then
    Self.Hide
    else inherited;
    end;
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    var {程序被关闭时通知Windows去掉小图标}
    nid: TNotifyIconData;
    begin
    nid.cbSize := sizeof(nid); // nid变量的字节数
    nid.uID := 1; //内部标识,与加入小图标时的数一致
    nid.Wnd := Handle; //主窗口句柄
    Shell_NotifyIcon(NIM_DELETE, @nid); //去掉小图标
    end;end.
    这个不错,测试通过,可以使用
      

  4.   

    我用cooltrayicon,没遇到这个问题。你换这个控件试试.
      

  5.   

    最后换用rzTrayIcon来做了。
    谢谢大家。