首页 > 编程 > Delphi > 正文

简易托盘图标控件-TTrayIcon

2019-09-08 23:09:09
字体:
来源:转载
供稿:网友
                                                                                                                                                       
                       

{------------------------------------------------------------------------------}
{ 单元名称: TrayIcon.pas/t/t/t/t/t/t       }
{/t/t/t/t/t/t/t/t/t      }
{ 单元作者: savetime (savetime2k@hotmail.com, http://savetime.delphibbs.com)   }
{ 创建日期: 2004-11-13 12:20:54/t/t/t/t/t/t}
{/t/t/t/t/t/t/t/t/t      }
{ 功能介绍:/t/t/t/t/t/t/t/t    }
{   封装 Shell_NotifyIcon 的大部分功能,并增加部分常见应用/t/t      }
{/t/t/t/t/t/t/t/t/t      }
{ 使用说明:/t/t/t/t/t/t/t/t    }
{   如果设置了 OnDblClick 事件,则 onClick 的响应时间会增加 GetDoubleClickTime. }
{   否则, onClick 将会立即执行./t/t/t/t/t/t}
{   如果没有设置 Icon, 将使用 Application 的图标./t/t/t      }
{/t/t/t/t/t/t/t/t/t      }
{ 更新历史:/t/t/t/t/t/t/t/t    }
{   弹出右键菜单时,点击其他位置不能关闭该菜单.解决方法:/t/t/t}
{     在弹出菜单之前加上: SetForegroundWindow(FWindow); 即可./t/t  }
{/t/t/t/t/t/t/t/t/t      }
{ 尚存问题:/t/t/t/t/t/t/t/t    }
{   暂时只支持 Win95 Shell 风格, Version 5.0 新功能以后加入/t/t    }
{   DoubleClick 的间隔时间应可随系统设置更改而更新./t/t/t    }
{   点击 TrayIcon 时,应可设置是否将应用程序提至前台./t/t/t   }
{/t/t/t/t/t/t/t/t/t      }
{------------------------------------------------------------------------------}
unit TrayIcon;

interface

uses SysUtils, Classes, Graphics, Controls, Windows, Messages, Forms, Menus,
 ExtCtrls, ShellAPI;

type

//==============================================================================
// TTrayIcon class
//==============================================================================

 TTrayIcon = class(TComponent)
 private
   FWindow: HWND;
   FHint: string;
   FIcon: TIcon;
   FActive: Boolean;
   FonClick: TNotifyEvent;
   FOnDblClick: TNotifyEvent;
   FPopupMenu: TPopupMenu;
   FClickTimer: TTimer;
   FIconData: TNotifyIconData;
   procedure CheckClickTimer(Sender: TObject);
   procedure SendTrayMessage(MsgID: DWORD; Flags: UINT);
   procedure TrayWndProc(var Message: TMessage);
   procedure SetActive(const Value: Boolean);
   procedure SetIcon(const Value: TIcon);
   procedure SetHint(const Value: string);
   procedure SetPopupMenu(const Value: TPopupMenu);
 protected
   procedure Loaded; override;
   procedure Notification(AComponent: TComponent; Operation: TOperation); override;
 public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
 published
   property Active: Boolean read FActive write SetActive default False;
   property Hint: string read FHint write SetHint;
   property Icon: TIcon read FIcon write SetIcon;
   property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
   property onClick: TNotifyEvent read FonClick write FonClick;
   property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;
 end;

 procedure Register;

implementation

procedure Register;
begin
 RegisterComponents(''Savetime'', [TTrayIcon]);
end;

{ TTrayIcon }

const
 WM_CALLBACKMESSAGE = WM_USER + 100;     // 托盘图标回调消息常量

procedure TTrayIcon.CheckClickTimer(Sender: TObject);
begin
 FClickTimer.Enabled := False;
 if Assigned(FonClick) then FonClick(Self);
end;

constructor TTrayIcon.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);

 FWindow := Classes.AllocateHWnd(TrayWndProc); // 处理 TrayIcon 消息的窗口

 FIcon := TIcon.Create;

 FClickTimer := TTimer.Create(Self);/t   // 处理单击和双击间隔时间的定时器
 FClickTimer.Enabled := False;
 FClickTimer.Interval := GetDoubleClickTime;   // 控制面板中鼠标双击间隔时间
 FClickTimer.OnTimer := CheckClickTimer;

 FIconData.cbSize := SizeOf(FIconData);/t// 初始化 NotifyIconData 结构
 FIconData.Wnd := FWindow;
 FIconData.uID := UINT(Self);
 FIconData.uCallbackMessage := WM_CALLBACKMESSAGE;
end;

destructor TTrayIcon.Destroy;
begin
 Active := False;

 FClickTimer.Free;
 FIcon.Free;
 Classes.DeallocateHWnd(FWindow);

 inherited;
end;

procedure TTrayIcon.Loaded;
begin
 inherited;
 if FActive then
   SendTrayMessage(NIM_ADD, NIF_MESSAGE or NIF_ICON or NIF_TIP);
end;

procedure TTrayIcon.Notification(AComponent: TComponent; Operation: TOperation);
begin
 inherited Notification(AComponent, Operation);
 if (Operation = opRemove) and (AComponent = PopupMenu) then
   PopupMenu := nil;
end;

procedure TTrayIcon.SendTrayMessage(MsgID: DWORD; Flags: UINT);
begin
 if (Flags and NIF_ICON) <> 0 then
 begin
   if FIcon.Handle = 0 then/t/t      // 如果未设置图标,则使用缺省图标
     FIconData.hIcon := Application.Icon.Handle
   else
     FIconData.hIcon := FIcon.Handle;
 end;

 FIconData.uFlags := Flags;
 Shell_NotifyIcon(MsgID, @FIconData);
end;

procedure TTrayIcon.SetActive(const Value: Boolean);
begin
 FActive := Value;

 if (not (csDesigning in ComponentState)) and
    (not (csLoading in ComponentState))  then
 begin
   if Value then
     SendTrayMessage(NIM_ADD, NIF_MESSAGE or NIF_ICON or NIF_TIP)
   else
     SendTrayMessage(NIM_DELETE, 0)
 end;
end;

procedure TTrayIcon.SetHint(const Value: string);
begin
 FHint := Value;
 StrPLCopy(FIconData.szTip, PChar(FHint), SizeOf(FIconData.szTip));

 if (not (csDesigning in ComponentState)) and
    (not (csLoading in ComponentState)) and
    FActive then
 begin
   SendTrayMessage(NIM_MODIFY, NIF_TIP);
 end;
end;

procedure TTrayIcon.SetIcon(const Value: TIcon);
begin
 FIcon.Assign(Value);

 if (FActive and not (csDesigning in ComponentState)) then
   SendTrayMessage(NIM_MODIFY, NIF_ICON);
end;

procedure TTrayIcon.SetPopupMenu(const Value: TPopupMenu);
begin
 FPopupMenu := Value;
 if Value <> nil then Value.FreeNotification(Self);
end;

procedure TTrayIcon.TrayWndProc(var Message: TMessage);
var
 PT: TPoint;
begin
 with Message do
 begin
   if Msg = WM_CALLBACKMESSAGE then
   begin
     case LParam of

/tWM_LBUTTONDOWN:
/tbegin
/t  // 如果没设置 OnDblClick 事件,则直接调用 onclick
/t  if not Assigned(FOnDblClick) then
/t  begin
/t    if Assigned(FonClick) then FonClick(Self);
/t  end
/t  else  // 否则使用时间判断双击时间是否到达
/t    FClickTimer.Enabled := True;
/tend;

/tWM_LBUTTONDBLCLK:
/tbegin
/t  FClickTimer.Enabled := False;
/t  if Assigned(FOnDblClick) then FOnDblClick(Self);
/tend;

/tWM_RBUTTONDOWN:
/tbegin
/t  if Assigned(FPopupMenu) then
/t  begin
/t    SetForegroundWindow(FWindow); // 这句一定要加,否则弹出菜单不会自动隐藏
/t    GetCursorPos(PT);
/t    FPopupMenu.Popup(PT.X, PT.Y);
/t  end;
/tend;
     end;
   end
   else    // 其他消息交由 Windows 处理
     Result := DefWindowProc(FWindow, Msg, WParam, LParam);
 end;
end;

end.


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选