欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

一个托盘图标组件

程序员文章站 2021-12-14 10:42:59
最近在温故Delphi精要,下面是按照其中做的托盘图标组件,记录一下。 工具:Delphi 7+Image Editer 先上图: 组件源码如下:对于图标,百度 unit XsdTrayIcon; interface uses SysUtils, Classes, Windows, Messages ......

最近在温故delphi精要,下面是按照其中做的托盘图标组件,记录一下。

工具:delphi 7+image editer

先上图:

一个托盘图标组件

 

组件源码如下:对于图标,百度 

unit xsdtrayicon;

interface

uses
  sysutils, classes, windows, messages, graphics, menus, shellapi, extctrls,
  forms, registry;

const
  icon_id = 1;
  mi_iconevent = wm_user + 1;    //自定义一个消息

type
  txsdtrayicon = class(tcomponent)
  private
    fhint: string;
    fondblclick: tnotifyevent;
    ftrayicon: ticon;
    fpopmenu: tpopupmenu;
    fnotificationwnd: hwnd;
    fstartatboot: boolean;
    finterval: cardinal;
    timerhandle: longword;
    notifyicondata: tnotifyicondata;
    oldwindowproc: twndmethod;
    procedure notificationwndproc(var message: tmessage);
    procedure settrayicon(const value: ticon);
    procedure setstartatboot(const value: boolean);
    procedure registry(b: boolean);
    procedure newwindowproc(var message: tmessage);
  protected
    procedure dodblclick;
    procedure notification(acomponent: tcomponent; operation: toperation); override;
    (*
    loaded 是tcomponent 的一个虚拟方法。当所有组件被创建,并从dfm 文件读出数据
    初始化这些组件实例后,loaded 方法被自动调用。在loaded 中可以进行额外的初始化
    工作,可以对组件实例的一些成员进行改变、嫁接
    *)
    procedure loaded; override;
  public
    constructor create(aowner: tcomponent); override;
    destructor destroy; override;
    //操作托盘正常显示应用程序
    procedure restoreapp();
    procedure showtrayicon(mode: cardinal = nim_add; animated: boolean = false);
  published
    property hint: string read fhint write fhint;
    property ondodblclick: tnotifyevent read fondblclick write fondblclick;
    property popmenu: tpopupmenu read fpopmenu write fpopmenu;
    property trayicon: ticon read ftrayicon write settrayicon;
    //是否自动启动
    property startatboot: boolean read fstartatboot write setstartatboot;
    property interval: cardinal read finterval write finterval;
  end;

procedure register;

implementation

var
  fxsdtrayicon: txsdtrayicon ;
  
procedure register;
begin
  registercomponents('xsdinfo', [txsdtrayicon]);
end;

{ txsdtrayicon }

constructor txsdtrayicon.create(aowner: tcomponent);
begin
  inherited create(aowner);
  fxsdtrayicon := self;
  ftrayicon := ticon.create;
  finterval := 500;
  timerhandle := 0;
  fnotificationwnd := classes.allocatehwnd(notificationwndproc);
  if aowner is tform then
  begin
    oldwindowproc := tform(aowner).windowproc;
    tform(aowner).windowproc := newwindowproc;
  end;
end;

destructor txsdtrayicon.destroy;
begin
  showtrayicon(nim_delete); //删除托盘图标
  freeandnil(ftrayicon);
  if fnotificationwnd<>0 then
    classes.deallocatehwnd(fnotificationwnd);  //销毁窗口
  if timerhandle<>0 then
    killtimer(0, timerhandle);  //关掉定时器
  inherited destroy;
end;

procedure txsdtrayicon.dodblclick;
begin
  if assigned(ondodblclick) then ondodblclick(self);
end;

procedure txsdtrayicon.loaded;
begin
  inherited;
  if not (csdesigning in componentstate) then
  begin
    if ftrayicon.handle=0 then
      ftrayicon.assign(application.icon);
    //初始化notificationdata;
    fillchar(notifyicondata, sizeof(notifyicondata), 0);
    with notifyicondata do
    begin
      cbsize := sizeof(tnotifyicondata);
      wnd := fnotificationwnd;
      uid := icon_id;
      uflags := nif_message or nif_icon or nif_tip;
      ucallbackmessage := mi_iconevent;
      hicon := ftrayicon.handle;
      strlcopy(sztip, pchar(fhint), sizeof(sztip));
    end;
    showtrayicon();
  end;
end;

procedure txsdtrayicon.newwindowproc(var message: tmessage);
begin
  if assigned(oldwindowproc) then
    oldwindowproc(message);
  with message do
  begin
    if ((msg=wm_syscommand) and (wparam=sc_minimize)) then
      showwindow(application.handle, sw_hide);
  end;
end;

procedure txsdtrayicon.notification(acomponent: tcomponent;
  operation: toperation);
begin
  inherited notification(acomponent, operation);
  if operation=opremove then
  begin
    if acomponent=fpopmenu then fpopmenu := nil;
  end;
end;

procedure txsdtrayicon.notificationwndproc(var message: tmessage);
var
  pt: tpoint;
begin
  if message.msg=mi_iconevent then
  begin
    case message.lparam of
      wm_lbuttondblclk:
      begin
        dodblclick;
        restoreapp;
      end;
      wm_rbuttondown:
      begin
        if assigned(fpopmenu) then
        begin
          getcursorpos(pt);
          fpopmenu.popup(pt.x, pt.y);
        end;
      end;
    end;
  end else //对于其它消息 缺省处理。
    message.result := defwindowproc(fnotificationwnd, message.msg, message.wparam, message.lparam);
end;

procedure setanimatedicon(wnd: hwnd; msg, idevent: uint; dwtime: dword); stdcall;
begin
  if msg=wm_timer then
  with fxsdtrayicon.notifyicondata do
  begin
    if hicon=0 then
      hicon := fxsdtrayicon.ftrayicon.handle
    else
      hicon := 0;
    shell_notifyicon(nim_modify, @fxsdtrayicon.notifyicondata);
  end;
end;

procedure txsdtrayicon.registry(b: boolean);
var
  reg: tregistry;
  keyname: string;
begin
  reg := tregistry.create;
  keyname := extractfilename(application.exename);
  try
    reg.rootkey := hkey_local_machine;
    if reg.openkey('\software\microsoft\windows\currentversion\run', false) then
    begin
      if b then
        reg.writestring(keyname, application.exename)
      else
        reg.deletekey(keyname);
      reg.closekey;
    end;
  finally
    freeandnil(reg);
  end;
end;

procedure txsdtrayicon.restoreapp;
begin
  showtrayicon(nim_modify, false);
  showwindow(application.handle, sw_shownormal);
  showwindow(application.mainform.handle, sw_shownormal);
  setforegroundwindow(application.mainform.handle);
end;

procedure txsdtrayicon.setstartatboot(const value: boolean);
begin
  if fstartatboot<>value then
  begin
    fstartatboot := value;
    if not (csdesigning in componentstate) then
      registry(fstartatboot);
  end;
end;

procedure txsdtrayicon.settrayicon(const value: ticon);
begin
  ftrayicon := value;
end;

procedure txsdtrayicon.showtrayicon(mode: cardinal; animated: boolean);
begin
  if csdesigning in componentstate then exit;
  if mode=nim_modify then
  begin
    if animated then
    begin
      if timerhandle=0 then
        timerhandle := settimer(0, 0, finterval, @setanimatedicon);
    end else begin
      if timerhandle<>0 then
      begin
        killtimer(0, timerhandle);
        timerhandle := 0;
        notifyicondata.hicon := ftrayicon.handle;
      end;
    end;
  end;
  shell_notifyicon(mode, @notifyicondata);
end;

end.