unit TrayIcon;<br><br>interface<br><br>uses Windows, SysUtils, Messages, ShellAPI, Classes, Graphics, Forms, Menus,<br> StdCtrls, ExtCtrls;<br><br>type<br> ENotifyIconError = class(Exception);<br><br> TTrayNotifyIcon = class(TComponent)<br> private<br> FDefaultIcon: THandle;<br> FIcon: TIcon;<br> FHideTask: Boolean;<br> FHint: string;<br> FIconVisible: Boolean;<br> FPopupMenu: TPopupMenu;<br> FOnClick: TNotifyEvent;<br> FOnDblClick: TNotifyEvent;<br> FNoShowClick: Boolean;<br> FTimer: TTimer;<br> Tnd: TNotifyIconData;<br> procedure SetIcon(Value: TIcon);<br> procedure SetHideTask(Value: Boolean);<br> procedure SetHint(Value: string);<br> procedure SetIconVisible(Value: Boolean);<br> procedure SetPopupMenu(Value: TPopupMenu);<br> procedure SendTrayMessage(Msg: DWORD; Flags: UINT);<br> function ActiveIconHandle: THandle;<br> procedure OnButtonTimer(Sender: TObject);<br> protected<br> procedure Loaded; override;<br> procedure LoadDefaultIcon; virtual;<br> procedure Notification(AComponent: TComponent;<br> Operation: TOperation); override;<br> public<br> constructor Create(AOwner: TComponent); override;<br> destructor Destroy; override;<br> published<br> property Icon: TIcon read FIcon write SetIcon;<br> property HideTask: Boolean read FHideTask write SetHideTask default False;<br> property Hint: String read FHint write SetHint;<br> property IconVisible: Boolean read FIconVisible write SetIconVisible default False;<br> property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;<br> property OnClick: TNotifyEvent read FOnClick write FOnClick;<br> property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;<br> end;<br><br>procedure Register;<br>implementation<br><br>{ TIconManager }<br>{ 处理"托盘消息" }<br>type<br> TIconManager = class<br> private<br> FHWindow: HWnd;<br> procedure TrayWndProc(var Message: TMessage);<br> public<br> constructor Create;<br> destructor Destroy; override;<br> property HWindow: HWnd read FHWindow write FHWindow;<br> end;<br><br>var<br> IconMgr: TIconManager;<br> DDGM_TRAYICON: Cardinal;<br><br>constructor TIconManager.Create;<br>begin<br> FHWindow := Classes.AllocateHWnd(TrayWndProc);<br>end;<br><br>destructor TIconManager.Destroy;<br>begin<br> if FHWindow <> 0 then Classes.DeallocateHWnd(FHWindow);<br> inherited Destroy;<br>end;<br><br>procedure TIconManager.TrayWndProc(var Message: TMessage);<br>{ 用户自定义消息,用来处理托盘图标与组件之间的消息. }<br>var<br> Pt: TPoint;<br> TheIcon: TTrayNotifyIcon;<br>begin<br> with Message do<br> begin<br> if (Msg = DDGM_TRAYICON) then<br> begin<br> TheIcon := TTrayNotifyIcon(WParam);<br> case lParam of<br> WM_LBUTTONDOWN: TheIcon.FTimer.Enabled := True;<br> WM_LBUTTONDBLCLK:<br> begin<br> TheIcon.FNoShowClick := True;<br> if Assigned(TheIcon.FOnDblClick) then TheIcon.FOnDblClick(Self);<br> end;<br> WM_RBUTTONDOWN:<br> begin<br> if Assigned(TheIcon.FPopupMenu) then<br> begin<br> SetForegroundWindow(IconMgr.HWindow);<br> GetCursorPos(Pt);<br> TheIcon.FPopupMenu.Popup(Pt.X, Pt.Y);<br> //TheIcon.FPopupMenu.Popup(LParamLo,LParamHi);<br> PostMessage(IconMgr.HWindow, WM_USER, 0, 0);<br> end;<br> end;<br> end;<br> end<br> else<br> Result := DefWindowProc(FHWindow, Msg, wParam, lParam);<br> end;<br>end;<br><br>{ TTrayNotifyIcon }<br><br>constructor TTrayNotifyIcon.Create(AOwner: TComponent);<br>begin<br> inherited Create(AOwner);<br> FIcon := TIcon.Create;<br> FTimer := TTimer.Create(Self);<br> with FTimer do<br> begin<br> Enabled := False;<br> Interval := GetDoubleClickTime;<br> OnTimer := OnButtonTimer;<br> end;<br> LoadDefaultIcon;<br>end;<br><br>destructor TTrayNotifyIcon.Destroy;<br>begin<br> if FIconVisible then SetIconVisible(False);<br> FIcon.Free;<br> FTimer.Free;<br> inherited Destroy;<br>end;<br><br>function TTrayNotifyIcon.ActiveIconHandle: THandle;<br>begin<br> if (FIcon.Handle <> 0) then<br> Result := FIcon.Handle<br> else<br> Result := FDefaultIcon;<br>end;<br><br>procedure TTrayNotifyIcon.LoadDefaultIcon;<br>begin<br> FDefaultIcon := LoadIcon(0, IDI_WINLOGO);<br>end;<br><br>procedure TTrayNotifyIcon.Loaded;<br>begin<br> inherited Loaded;<br> if FIconVisible then<br> SendTrayMessage(NIM_ADD, NIF_MESSAGE or NIF_ICON or NIF_TIP);<br>end;<br><br>procedure TTrayNotifyIcon.Notification(AComponent: TComponent;<br> Operation: TOperation);<br>begin<br> inherited Notification(AComponent, Operation);<br> if (Operation = opRemove) and (AComponent = PopupMenu) then<br> PopupMenu := nil;<br>end;<br><br>procedure TTrayNotifyIcon.OnButtonTimer(Sender: TObject);<br>begin<br> FTimer.Enabled := False;<br> if (not FNoShowClick) and Assigned(FOnClick) then<br> FOnClick(Self);<br> FNoShowClick := False;<br>end;<br><br>procedure TTrayNotifyIcon.SendTrayMessage(Msg: DWORD; Flags: UINT);<br>begin<br> with Tnd do<br> begin<br> cbSize := SizeOf(Tnd);<br> StrPLCopy(szTip, PChar(FHint), SizeOf(szTip));<br> uFlags := Flags;<br> uID := UINT(Self);<br> Wnd := IconMgr.HWindow;<br> uCallbackMessage := DDGM_TRAYICON;<br> hIcon := ActiveIconHandle;<br> end;<br> Shell_NotifyIcon(Msg, @Tnd);<br>end;<br><br>procedure TTrayNotifyIcon.SetHideTask(Value: Boolean);<br>const<br> ShowArray: array[Boolean] of integer = (sw_ShowNormal, sw_Hide);<br>begin<br> if FHideTask <> Value then<br> begin<br> FHideTask := Value;<br> if not (csDesigning in ComponentState) then<br> ShowWindow(Application.Handle, ShowArray[FHideTask]);<br> end;<br>end;<br><br>procedure TTrayNotifyIcon.SetHint(Value: string);<br>begin<br> if FHint <> Value then<br> begin<br> FHint := Value;<br> if FIconVisible then<br> SendTrayMessage(NIM_MODIFY, NIF_TIP);<br> end;<br>end;<br><br>procedure TTrayNotifyIcon.SetIcon(Value: TIcon);<br>begin<br> FIcon.Assign(Value);<br> if FIconVisible then SendTrayMessage(NIM_MODIFY, NIF_ICON);<br>end;<br><br>procedure TTrayNotifyIcon.SetIconVisible(Value: Boolean);<br>const<br> MsgArray: array[Boolean] of DWORD = (NIM_DELETE, NIM_ADD);<br>begin<br> if FIconVisible <> Value then<br> begin<br> FIconVisible := Value;<br> SendTrayMessage(MsgArray[Value], NIF_MESSAGE or NIF_ICON or NIF_TIP);<br> end;<br>end;<br><br>procedure TTrayNotifyIcon.SetPopupMenu(Value: TPopupMenu);<br>begin<br> FPopupMenu := Value;<br> if Value <> nil then Value.FreeNotification(Self);<br>end;<br><br>procedure Register;<br>begin<br> RegisterComponents('Extend', [TTrayNotifyIcon]);<br>end;<br><br>const<br> TrayMsgStr = 'DDG.TrayNotifyIconMsg';<br><br>initialization<br> DDGM_TRAYICON := RegisterWindowMessage(TrayMsgStr);<br> IconMgr := TIconManager.Create;<br>finalization<br> IconMgr.Free;<br>end.<br>