我做一个程序,想在程序一启动就在托盘中,想用时,再点击托盘。
我已经做出点最小化时在托盘中显示,但我不知道怎么让程序一启动就在托盘中显示,而且窗口不要显示。
这是现在已作出来功能的源码
{接收本程序系统命令}const 
WM_BARICON = WM_USER+200;type
  TMainForm = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
       procedure WMSysCommand(var Msg: TMessage); message WM_SYSCOMMAND;
    procedure WMBarIcon(var Msg: TMessage); message WM_BARICON;
  end;procedure TMainForm.WMSysCommand(var Msg: TMessage);
var
  lpdata: PNotifyIconData;
begin
  if Msg.WParam = SC_ICON then
  begin
    //如果用户最小化窗口则将窗口隐藏并在任务栏上添加图标
    New(lpData);
    lpData.cbSize := 88;
    lpData.Wnd := self.Handle;
    lpData.hIcon := Application.Icon.Handle;
    lpData.uCallbackMessage := WM_BARICON;
    lpData.uID := 0;
    StrCopy(lpData.szTip,PChar(self.Caption));
    lpData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
    Shell_NotifyIcon(NIM_ADD,lpData);
    Dispose(lpData);
    Self.Visible := False;
  end
  else
  begin
    //如果是其它的SystemCommand消息则调用系统缺省处理函数处理之。
    DefWindowProc(self.Handle,Msg.Msg,Msg.WParam,Msg.LParam);
  end;
end;procedure TMainForm.WMBarIcon(var Msg:TMessage);
var
  lpData:PNotifyIconData;
begin
  if (Msg.LParam = WM_LBUTTONDOWN) then
  begin
  //如果用户点击任务栏图标则将图标删除并回复窗口。
    New(lpData);
    lpData.cbSize := 88;
    lpData.Wnd := self.Handle;
    lpData.hIcon := Application.Icon.Handle;
    //lpData.uCallbackMessage := WM_BARICON;
    lpData.uID :=0;
    StrCopy(lpData.szTip,PChar(self.Caption));
    lpData.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
    Shell_NotifyIcon(NIM_DELETE,lpData);
    Dispose(lpData);
    Self.Visible := True;
  end;
end;

解决方案 »

  1.   

    可以在主窗体创建时增加TrayIcon的代码,hoho ,这种代码到处都是,
      

  2.   

    procedure TfrmMain.FormCreate(Sender: TObject)
    ...
    ShowWindow(frmMain.Handle,SW_HIDE);
    SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW or
                      GetWindowLong(Handle,GWL_EXSTYLE));
    ...运行起来时就隐藏主窗体
      

  3.   

    方法一:
    “我已经做出点最小化时在托盘中显示,但我不知道怎么让程序一启动就在托盘中显示,而且窗口不要显示。”
    对策:
    将主Form的windowstate设为最小化方法二:
    就是加TrayIcon的代码(用控件也可),同时在主Form中加入相应隐藏主窗体的代码:
    showmainform:=false;
    ...
      

  4.   

    TrayIcon的代码确实网上很多。我也一直在用。
      

  5.   

    Copy来的。unit JrTrayIcon;interfaceuses
      SysUtils, Classes, Windows, Forms, Graphics, Controls, ExtCtrls,
      Messages, Menus, ShellAPI;const
      WM_NOTIFYICON = WM_USER + 1;type 
      TJrTrayIcon = class(TComponent)
      private
        { Private declarations }
        FHideMainForm: Boolean;
        FMainWin: TForm;
        FWindowHandle: HWND;
        FActive: Boolean;
        FAnimate: Boolean;
        FAnimateInterval: Integer;
        FImages: TImageList;
        FCurrentImageIndex: Integer;
        FTimer: TTimer;
        FIcon: TIcon;
        FOriginalIcon: TIcon;
        FHint: String;
        FShowDesigning: Boolean;
        FPopupMenu: TPopupMenu;
        FOnClick: TNotifyEvent;
        FOnDblClick: TNotifyEvent;
        FOnRightClick: TNotifyEvent;
        FIconData: TNotifyIconData;
        procedure SetHint(const Value: String);
        procedure SetIcon(const Value: TIcon);
        procedure SetActive(const Value: Boolean);
        procedure SetAnimate(const Value: Boolean);
        procedure SetAnimateInterval(const Value: integer);
        procedure SetHideMainForm(const Value: Boolean);
        procedure SetShowDesigning(const Value: Boolean);
        procedure ChangeIcon(Sender: TObject);
        procedure DoRightClick(Sender: TObject);    procedure WndProc(var Msg: TMessage);    procedure FillDataStructure;
        function AddIcon: Boolean;
        function DeleteIcon: Boolean;
        function ModifyIcon: Boolean;
      protected
        { Protected declarations }
        procedure Notification(AComponent: TComponent; Operation: TOperation); override ;
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;    property HideMainForm: Boolean read FHideMainForm write SetHideMainForm default False;
      published
        { Published declarations }
        property Active: Boolean read FActive write SetActive default False;
        property Animate : Boolean read FAnimate write SetAnimate default False;
        property AnimateInterval : integer read FAnimateInterval write SetAnimateInterval default 300;
        property Hint: String read FHint write SetHint;
        property Icon: TIcon read FIcon write SetIcon;
        property Images : TImageList read FImages write FImages ;
        property MainForm : TForm read FMainWin write FMainWin;
        property PopupMenu : TPopupMenu read FPopupMenu write FPopupMenu;
        property ShowDesigning : Boolean read FShowDesigning write SetShowDesigning default False;
        property OnClick     : TNotifyEvent read FOnClick write FOnClick;
        property OnDblClick  : TNotifyEvent read FOnDblClick write FOnDblClick;
        property OnRightClick: TNotifyEvent read FOnRightClick write FOnRightClick;
      end;implementation{ TJrTrayIcon }function TJrTrayIcon.AddIcon: Boolean;
    begin
      FillDataStructure;
      Result:=Shell_NotifyIcon(NIM_ADD, @FIconData);
    end;procedure TJrTrayIcon.ChangeIcon(Sender: TObject);
    var
      temp: TIcon;
    begin
      temp:=TIcon.Create;
      try
        if FCurrentImageIndex = FImages.Count - 1 then
          FCurrentImageIndex:=0
        else
          Inc(FCurrentImageIndex);
        FImages.GetIcon(FCurrentImageIndex, temp);
        SetIcon(temp);
      finally
        temp.Free;
      end;
    end;constructor TJrTrayIcon.Create(AOwner: TComponent);
    begin
      inherited;
      FWindowHandle:=Classes.AllocateHWnd(WndProc);
      FTimer:=TTimer.Create(Self);
      FTimer.Enabled:=False;
      FAnimateInterval:=300;
      FTimer.Interval:=FAnimateInterval;
      FTimer.OnTimer:=ChangeIcon;  FHideMainForm:=False;
      if AOwner is TForm then
        FMainWin:=TForm(AOwner)
      else
        FMainWin:=Nil;  FIcon:=TIcon.Create;
      FIcon.Assign(Application.Icon);
      FOriginalIcon:=TIcon.Create;
      FOriginalIcon.Assign(FIcon);  FActive:=False;
      FAnimate:=False;
      FHint:=ClassName;
      FShowDesigning:=False;
      FCurrentImageIndex:=0;
    end;function TJrTrayIcon.DeleteIcon: Boolean;
    begin
      Result:=Shell_NotifyIcon(NIM_DELETE, @FIconData);
    end;destructor TJrTrayIcon.Destroy;
    begin
      if (not(csDesigning in ComponentState) and FActive) or
         ((csDesigning in ComponentState) and FShowDesigning) then
        DeleteIcon;
      FTimer.Free;
      FIcon.Free;
      FOriginalIcon.Free;
      Classes.DeallocateHWnd(FWindowHandle);
      inherited;
    end;procedure TJrTrayIcon.DoRightClick(Sender: TObject);
    var
      MouseCo: TPoint;
    begin
      if Assigned(FPopupMenu) then begin
        GetCursorPos(MouseCo);
        SetForegroundWindow(Application.Handle);
        Application.ProcessMessages;
        FPopupmenu.Popup(Mouseco.X, Mouseco.Y);
      end;  if Assigned(FOnRightClick) then
        FOnRightClick(Sender);
    end;procedure TJrTrayIcon.FillDataStructure;
    begin
      FIconData.cbSize:=Sizeof(FIconData);
      FIconData.Wnd:=FWindowHandle;
      FIconData.uID:=0;
      FIconData.uFlags:=NIF_TIP + NIF_ICON + NIF_MESSAGE;
      FIconData.uCallbackMessage := WM_NOTIFYICON;
      FIconData.hIcon:=FIcon.Handle;
      StrPCopy(FIconData.szTip, FHint);
    end;function TJrTrayIcon.ModifyIcon: Boolean;
    begin
      FillDataStructure;
      if (not(csDesigning in ComponentState) and FActive) or
         ((csDesigning in ComponentState) and FShowDesigning) then
        Result:=Shell_NotifyIcon(NIM_MODIFY, @FIconData)
      else
        Result:=True;
    end;procedure TJrTrayIcon.Notification(AComponent: TComponent;
      Operation: TOperation);
    begin
      inherited;
      if (AComponent = FImages) and (Operation = opRemove) then begin
        FAnimate:=False;
        FImages:=Nil;
      end
      else if (AComponent = FPopupMenu) and (Operation = opRemove) then 
        FPopupMenu:=Nil;
    end;procedure TJrTrayIcon.SetActive(const Value: Boolean);
    begin
      if FActive <> Value then begin
        FActive:=Value;
        if not(csdesigning in ComponentState) and FActive then
          AddIcon
        else if not((csdesigning in ComponentState) and FShowDesigning) then
          DeleteIcon;
      end;
    end;procedure TJrTrayIcon.SetAnimate(const Value: Boolean);
    begin
      if FAnimate <> Value then begin
        FAnimate:=Value;
        if (FImages <> Nil) and (FImages.Count > 0) then
          FTimer.Enabled:=FAnimate;
        if FAnimate then begin
          FOriginalIcon.Assign(FIcon);
          FCurrentImageIndex:=0;
        end
        else
          SetIcon(FOriginalIcon);
      end;
    end;procedure TJrTrayIcon.SetAnimateInterval(const Value: integer);
    begin
      if Value > 0 then begin
        FAnimateInterval:=Value;
        FTimer.Interval:=FAnimateInterval;
      end;
    end;procedure TJrTrayIcon.SetHideMainForm(const Value: Boolean);
    begin
      if FMainWin = Nil then Exit;
      if FHideMainForm <> Value then begin
        FHideMainForm := Value;
        if FHideMainForm then
          ShowWindow(FMainWin.Handle, SW_HIDE)
        else
          ShowWindow(FMainWin.Handle, SW_SHOWNORMAL);
      end;
    end;procedure TJrTrayIcon.SetHint(const Value: String);
    begin
      if Length(Value) > 62 then
        FHint:=Copy(Value, 1, 62)
      else
        FHint:=Value;
      ModifyIcon;
    end;procedure TJrTrayIcon.SetIcon(const Value: TIcon);
    begin
      if FIcon <> Value then begin
        FIcon.Assign(Value);
        ModifyIcon;
      end;
    end;procedure TJrTrayIcon.SetShowDesigning(const Value: Boolean);
    begin
      if csdesigning in ComponentState then
        if FShowDesigning <> Value then begin
          FShowDesigning:=Value;
          if FShowDesigning then AddIcon else DeleteIcon;
        end;
    end;procedure TJrTrayIcon.WndProc(var Msg: TMessage);
    begin
      with Msg do
        if (Msg = WM_NOTIFYICON) then begin
          case lParam of
            WM_LBUTTONDBLCLK: if Assigned(FOnDblClick) then FOnDblClick(Self);
            WM_LBUTTONUP    : if Assigned(FOnClick)then FOnClick(Self);
            WM_RBUTTONUP    : DoRightClick(Self);
          end;
        end
        else // Handle all messages with the default handler
          Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
    end;end.
      

  6.   

    下载 TrayIcon  控件
      

  7.   

    楼主,我完全按照你的要求“程序一启动就在托盘中显示,而且窗口不要显示。 ”做了一个工程。你启动DELPHI后点全部保存,保存后得到四个文件:Project1.DPR、Unit1.PAS、Unit1.DFM、Project1.res关闭DELPHI,用记事本打开Unit1.PAS文件,用下面的内容替换:unit Unit1;interfaceuses
      Windows,ShellAPI, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Menus;//必须包含:ShellAPI
    const WM_NID=WM_USER+1000;    //自定义此消息,为托盘事件打好基础。
    type
      TForm1 = class(TForm)
        PopupMenu1: TPopupMenu;
        N1: TMenuItem;
        N2: TMenuItem;
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure N1Click(Sender: TObject);
        procedure N2Click(Sender: TObject);
      private
        { Private declarations }
      procedure mwy(var Msg:TMessage);Message WM_NID;//过程声明。用于响应托盘单击或右击等事件。
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      NotifyIcon:TNotifyIconData;//定义托盘类型变量。implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    begin
     
    with NotifyIcon do
        begin
          cbSize:=SizeOf(TNotifyIconData); //变量的字节数
          Wnd:=Handle; //主窗口句柄
          uID:=19; // 内部标识,可设为任意数。如果建立多这托盘,这个是区分它们的标志。
          uFlags:=NIF_ICON OR NIF_TIP OR NIF_MESSAGE;
          uCallBackMessage:=WM_NID; //回调函数消息
          hIcon:=Application.Icon.Handle; //要加入的图标句柄。这里设定为程序自身所附带的图标。
          szTip:='单击显示或隐藏主窗体,右击获取更多功能……'; //提示字符串
        end;
        Shell_NotifyIcon(NIM_ADD,@NotifyIcon);
    //不显示任务按扭:
    SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);end;
    procedure TForm1.mwy(var Msg:TMessage);
    var mouse:TPoint;
    begin
       if msg.LParam=WM_LBUTTONDOWN then
            MessageBox(0,chr(13)+'发现你单击了鼠标左键!','→崔少云⊙制作',MB_OK+MB_ICONINFORMATION);
       if msg.LParam=WM_RBUTTONDOWN then
         begin
            GetCursorPos(mouse);
            PopupMenu1.Popup(mouse.X,mouse.Y);
         end;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    //最终退出程序时删除托盘小图标。
      NotifyIcon.cbSize:=SizeOf(TNotifyIconData);   //变量的字节数
      NotifyIcon.Wnd:=Handle;  //主窗口句柄
      NotifyIcon.uID := 19; //内部标识,与加入小图标时的数一致
      Shell_NotifyIcon(NIM_DELETE,@NotifyIcon);//去掉托盘小图标
    end;procedure TForm1.N1Click(Sender: TObject);
    begin
    form1.Visible:=Not form1.Visible;
    end;procedure TForm1.N2Click(Sender: TObject);
    begin
    close;
    end;end.再用记事本打开Unit1.DFM文件,输入下面的内容:
    object Form1: TForm1
      Left = 192
      Top = 114
      Width = 467
      Height = 252
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      OnClose = FormClose
      OnCreate = FormCreate
      PixelsPerInch = 96
      TextHeight = 13
      object PopupMenu1: TPopupMenu
        Left = 64
        Top = 48
        object N1: TMenuItem
          Caption = #26174#31034'/'#38544#34255
          OnClick = N1Click
        end
        object N2: TMenuItem
          Caption = #36864#20986#31243#24207
          OnClick = N2Click
        end
      end
    end
    全部关闭保存,然后双击Project1.DPR默认会以DELPHI启动工程。编译一下看看效果吧。
    当你是DELPHI新手来讲述的,别介意!
      

  8.   

    我不介意,只要有答案就行哈哈。
    我试了下楼主的代码,不行啊?程序一起窗口不隐藏,且不自动在系统托盘中啊。而且我试过了,
    ShowWindow(frmMain.Handle,SW_HIDE); 
    SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW or 
                      GetWindowLong(Handle,GWL_EXSTYLE)); 

    将主Form的windowstate设为最小化 都不行。
      

  9.   

    9楼的代码在formcreate里加一句:Application.ShowMainForm := False;就可以满足我的要求了。
    谢谢大家给的各种方案,我都收下了,留着以后慢慢用