home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 October / Chip_2001-10_cd1.bin / zkuste / delphi / kolekce / d456 / DCSLIB25.ZIP / DCTray.pas < prev    next >
Pascal/Delphi Source File  |  2001-06-25  |  19KB  |  681 lines

  1. {
  2.  BUSINESS CONSULTING
  3.  s a i n t - p e t e r s b u r g
  4.  
  5.          Components Library for Borland Delphi 4.x, 5.x
  6.          Copyright (c) 1998-2000 Alex'EM
  7.  
  8. }
  9. unit DCTray;
  10. {$I DCConst.inc}
  11.  
  12. interface
  13.  
  14. uses Windows, Messages,
  15.      Classes, Graphics, SysUtils, Forms, Controls, Menus, ShellAPI, DCConst;
  16.  
  17. const
  18.   NIF_INFO     = $00000010;
  19.  
  20.   NIIF_NONE    = $00000000;
  21.   NIIF_INFO    = $00000001;
  22.   NIIF_WARNING = $00000002;
  23.   NIIF_ERROR   = $00000003;
  24.  
  25.   NOTIFYICONDATA_V1_SIZE = 88;
  26.  
  27. type
  28.  
  29.   PNotifyIconDataEx = ^TNotifyIconDataEx;
  30.   TNotifyIconDataEx = record
  31.     cbSize: DWORD;
  32.     Wnd: HWND;
  33.     uID: UINT;
  34.     uFlags: UINT;
  35.     uCallbackMessage: UINT;
  36.     hIcon: HICON;
  37.     szTip: array [0..MAXCHAR] of AnsiChar;
  38.     {Windows 5.x support}
  39.     dwState: DWORD;
  40.     dwStateMask: DWORD;
  41.     szInfo: array[0..MAXBYTE] of AnsiChar;
  42.     uTimeout: UINT;
  43.     szInfoTitle: array [0..63] of AnsiChar;
  44.     dwInfoFlags: DWORD;
  45.   end;
  46.  
  47.   TBaloonTimeout  = 10..30;
  48.   TBaloonInfoType = (biNone, biInfo, biWarning, biError);
  49.   TMouseButtons   = set of TMouseButton;
  50.  
  51.   TDCTrayIcon = class(TComponent)
  52.   private
  53.     FHandle: HWnd;
  54.     FActive: Boolean;
  55.     FAdded: Boolean;
  56.     FClicked: TMouseButtons;
  57.     FIconData: TNotifyIconDataEx;
  58.     FIcon: TIcon;
  59.     FDestroying: Boolean;
  60.     FHint: string;
  61.     FShowDesign: Boolean;
  62.     FPopupMenu: TPopupMenu;
  63.     FOnClick: TMouseEvent;
  64.     FOnDblClick: TNotifyEvent;
  65.     FOnMouseMove: TMouseMoveEvent;
  66.     FOnMouseDown: TMouseEvent;
  67.     FOnMouseUp: TMouseEvent;
  68.     FStartMinimized: boolean;
  69.     procedure ChangeIcon;
  70.     procedure SendCancelMode;
  71.     function CheckMenuPopup(X, Y: Integer): Boolean;
  72.     function CheckDefaultMenuItem: Boolean;
  73.     procedure SetHint(const Value: string);
  74.     procedure SetIcon(Value: TIcon);
  75.     procedure SetPopupMenu(Value: TPopupMenu);
  76.     procedure Activate;
  77.     procedure Deactivate;
  78.     procedure SetActive(Value: Boolean);
  79.     procedure SetShowDesign(Value: Boolean);
  80.     procedure IconChanged(Sender: TObject);
  81.     procedure WndProc(var Message: TMessage);
  82.     function GetActiveIcon: TIcon;
  83.     procedure LoadDefaultIcon;
  84.     function Win2k: boolean;
  85.   protected
  86.     procedure DblClick; dynamic;
  87.     procedure DoClick(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic;
  88.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic;
  89.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic;
  90.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic;
  91.     procedure Loaded; override;
  92.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  93.     procedure UpdateNotifyData; virtual;
  94.     property Handle: HWnd read FHandle;
  95.   public
  96.     constructor Create(AOwner: TComponent); override;
  97.     destructor Destroy; override;
  98.     procedure Hide;
  99.     procedure Show;
  100.     procedure ShowBaloonToolTip(const Info, InfoTitle: string;
  101.       const BaloonType: TBaloonInfoType; const Timeout: TBaloonTimeout);
  102.   published
  103.     property Active: Boolean read FActive write SetActive default True;
  104.     property Hint: string read FHint write SetHint;
  105.     property Icon: TIcon read FIcon write SetIcon;
  106.     property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;
  107.     property ShowDesign: Boolean read FShowDesign write SetShowDesign stored False;
  108.     property OnClick: TMouseEvent read FOnClick write FOnClick;
  109.     property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;
  110.     property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove;
  111.     property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
  112.     property OnMouseUp: TMouseEvent read FOnMouseUp write FOnMouseUp;
  113.     property StartMinimized: boolean read FStartMinimized write FStartMinimized;
  114.   end;
  115.  
  116. type
  117.   TExecState = (esNormal, esMinimized, esMaximized, esHidden);
  118.  
  119. type
  120.   TPreviousInstance = class(TObject)
  121.   private
  122.     FMessageID: DWORD;
  123.     FMutexHandle: THandle;
  124.     FhPrevInst: boolean;
  125.     FNewWndProc: Pointer;
  126.     FDefWndProc: Pointer;
  127.   protected
  128.     procedure NewWndProc(var Message: TMessage);
  129.   public
  130.     destructor Destroy; override;
  131.     procedure SethPrevInst;
  132.     property MutexHandle: THandle read FMutexHandle;
  133.     property hPrevInst: boolean read FhPrevInst write FhPrevInst;
  134.     property MessageID: DWORD read FMessageID;
  135.   end;
  136.  
  137. function CheckToMultyInstance: boolean;
  138. function FileExecute(const FileName, Params, StartDir: string;
  139.   InitialState: TExecState): THandle;
  140. function FileExecuteWait(const FileName, Params, StartDir: string;
  141.   InitialState: TExecState): Integer;
  142.  
  143. var
  144.   PreviousInstance: TPreviousInstance;
  145.  
  146. implementation
  147.  
  148. const
  149.   ShowCommands: array[TExecState] of Integer =
  150.     (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED, SW_HIDE);
  151.  
  152. function FileExecute(const FileName, Params, StartDir: string;
  153.   InitialState: TExecState): THandle;
  154. begin
  155.   Result := ShellExecute(Application.Handle, nil, PChar(FileName),
  156.     PChar(Params), PChar(StartDir), ShowCommands[InitialState]);
  157. end;
  158.  
  159. function FileExecuteWait(const FileName, Params, StartDir: string;
  160.   InitialState: TExecState): Integer;
  161. var
  162.   Info: TShellExecuteInfo;
  163.   ExitCode: DWORD;
  164. begin
  165.   FillChar(Info, SizeOf(Info), 0);
  166.   Info.cbSize := SizeOf(TShellExecuteInfo);
  167.   with Info do begin
  168.     fMask := SEE_MASK_NOCLOSEPROCESS;
  169.     Wnd := Application.Handle;
  170.     lpFile := PChar(FileName);
  171.     lpParameters := PChar(Params);
  172.     lpDirectory := PChar(StartDir);
  173.     nShow := ShowCommands[InitialState];
  174.   end;
  175.   if ShellExecuteEx(@Info) then begin
  176.     repeat
  177.       Application.ProcessMessages;
  178.       GetExitCodeProcess(Info.hProcess, ExitCode);
  179.     until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
  180.     Result := ExitCode;
  181.   end
  182.   else Result := -1;
  183. end;
  184.  
  185. procedure SwitchToWindow(Wnd: HWnd; Restore: Boolean);
  186. begin
  187.   if IsWindowEnabled(Wnd) then begin
  188.     SetForegroundWindow(Wnd);
  189.     if Restore and IsWindowVisible(Wnd) then begin
  190.       if not IsZoomed(Wnd) then
  191.         SendMessage(Wnd, WM_SYSCOMMAND, SC_RESTORE, 0);
  192.       SetFocus(Wnd);
  193.     end;
  194.   end;
  195. end;
  196.  
  197. function GetShiftState: TShiftState;
  198. begin
  199.   Result := [];
  200.   if GetKeyState(VK_SHIFT  ) < 0 then Include(Result, ssShift);
  201.   if GetKeyState(VK_CONTROL) < 0 then Include(Result, ssCtrl);
  202.   if GetKeyState(Vk_MENU   ) < 0 then Include(Result, ssAlt);
  203. end;
  204.  
  205. constructor TDCTrayIcon.Create(AOwner: Tcomponent);
  206. begin
  207.   inherited Create(AOwner);
  208.   {$IFDEF DELPHI_V6}
  209.     FHandle := Classes.AllocateHWnd(WndProc);
  210.   {$ELSE}
  211.     FHandle := AllocateHWnd(WndProc);
  212.   {$ENDIF}
  213.   FIcon := TIcon.Create;
  214.   FIcon.OnChange := IconChanged;
  215.   FActive        := True;
  216.   StartMinimized := False;
  217.   LoadDefaultIcon;
  218. end;
  219.  
  220. destructor TDCTrayIcon.Destroy;
  221. begin
  222.   FDestroying := True;
  223.   FIcon.OnChange := nil;
  224.   Deactivate;
  225.   {$IFDEF DELPHI_V6}
  226.     Classes.DeallocateHWnd(FHandle);
  227.   {$ELSE}
  228.     DeallocateHWnd(FHandle);
  229.   {$ENDIF}
  230.   FIcon.Free;
  231.   FIcon := nil;
  232.   inherited Destroy;
  233. end;
  234.  
  235. procedure TDCTrayIcon.Loaded;
  236. begin
  237.   inherited Loaded;
  238.   if FActive and not (csDesigning in ComponentState) then Activate;
  239.  
  240.   if FStartMinimized then
  241.   begin
  242.     Application.ShowMainForm := False;
  243.     ShowWindow(Application.Handle, SW_HIDE);
  244.   end;
  245.  
  246. end;
  247.  
  248. procedure TDCTrayIcon.Notification(AComponent: TComponent;
  249.   Operation: TOperation);
  250. begin
  251.   inherited Notification(AComponent, Operation);
  252.   if (AComponent = PopupMenu) and (Operation = opRemove) then
  253.     PopupMenu := nil;
  254. end;
  255.  
  256. procedure TDCTrayIcon.SetPopupMenu(Value: TPopupMenu);
  257. begin
  258.   FPopupMenu := Value;
  259.   if Value <> nil then Value.FreeNotification(Self);
  260. end;
  261.  
  262. procedure TDCTrayIcon.SendCancelMode;
  263. var
  264.   F: TForm;
  265. begin
  266.   if not ((csDestroying in ComponentState) or FDestroying) then begin
  267.     F := Screen.ActiveForm;
  268.     if F = nil then F := Application.MainForm;
  269.     if F <> nil then F.SendCancelMode(nil);
  270.   end;
  271. end;
  272.  
  273. function TDCTrayIcon.CheckMenuPopup(X, Y: Integer): Boolean;
  274. begin
  275.   Result := False;
  276.   if not (csDesigning in ComponentState) and Active and
  277.     (PopupMenu <> nil) and PopupMenu.AutoPopup then
  278.   begin
  279.     PopupMenu.PopupComponent := Self;
  280.     SendCancelMode;
  281.     SwitchToWindow(FHandle, False);
  282.     Application.ProcessMessages;
  283.     try
  284.       PopupMenu.Popup(X, Y);
  285.     finally
  286.       SwitchToWindow(FHandle, False);
  287.     end;
  288.     Result := True;
  289.   end;
  290. end;
  291.  
  292. function TDCTrayIcon.CheckDefaultMenuItem: Boolean;
  293. var
  294.   Item: TMenuItem;
  295.   I: Integer;
  296. begin
  297.   Result := False;
  298.   if not (csDesigning in ComponentState) and Active and
  299.     (PopupMenu <> nil) and (PopupMenu.Items <> nil) then
  300.   begin
  301.     I := 0;
  302.     while (I < PopupMenu.Items.Count) do begin
  303.       Item := PopupMenu.Items[I];
  304.       if Item.Default and Item.Enabled then begin
  305.         Item.Click;
  306.         Result := True;
  307.         Break;
  308.       end;
  309.       Inc(I);
  310.     end;
  311.   end;
  312. end;
  313.  
  314. procedure TDCTrayIcon.SetIcon(Value: TIcon);
  315. begin
  316.   FIcon.Assign(Value);
  317. end;
  318.  
  319. function TDCTrayIcon.GetActiveIcon: TIcon;
  320. begin
  321.   Result := FIcon;
  322. end;
  323.  
  324. procedure TDCTrayIcon.SetActive(Value: Boolean);
  325. begin
  326.   if (Value <> FActive) then begin
  327.     FActive := Value;
  328.     if not (csDesigning in ComponentState) then
  329.       if Value then Activate else Deactivate;
  330.   end;
  331. end;
  332.  
  333. procedure TDCTrayIcon.Show;
  334. begin
  335.   Active := True;
  336. end;
  337.  
  338. procedure TDCTrayIcon.Hide;
  339. begin
  340.   Active := False;
  341. end;
  342.  
  343. procedure TDCTrayIcon.SetShowDesign(Value: Boolean);
  344. begin
  345.   if (csDesigning in ComponentState) then begin
  346.     if Value then Activate else Deactivate;
  347.     FShowDesign := FAdded;
  348.   end;
  349. end;
  350.  
  351. procedure TDCTrayIcon.IconChanged(Sender: TObject);
  352. begin
  353.   ChangeIcon;
  354. end;
  355.  
  356. procedure TDCTrayIcon.SetHint(const Value: string);
  357. begin
  358.   if FHint <> Value then begin
  359.     FHint := Value;
  360.     ChangeIcon;
  361.   end;
  362. end;
  363.  
  364. procedure TDCTrayIcon.UpdateNotifyData;
  365.  var
  366.   Ico: TIcon;
  367. begin
  368.   with FIconData do
  369.   begin
  370.     if Win2k then
  371.       cbSize := SizeOf(TNotifyIconDataEx)
  372.     else
  373.       cbSize := NOTIFYICONDATA_V1_SIZE;
  374.     Wnd := FHandle;
  375.     uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
  376.     Ico := GetActiveIcon;
  377.     if Ico <> nil then
  378.       hIcon := Ico.Handle
  379.     else
  380.       hIcon := INVALID_HANDLE_VALUE;
  381.     StrPCopy(szTip, GetShortHint(FHint));
  382.     uCallbackMessage := CM_TRAYICON;
  383.     uID := 0;
  384.   end;
  385. end;
  386.  
  387. procedure TDCTrayIcon.Activate;
  388. var
  389.   Ico: TIcon;
  390. begin
  391.   Deactivate;
  392.   Ico := GetActiveIcon;
  393.   if (Ico <> nil) and not Ico.Empty then
  394.   begin
  395.     FClicked := [];
  396.     UpdateNotifyData;
  397.     FAdded := Shell_NotifyIcon(NIM_ADD, @FIconData);
  398.     if (GetShortHint(FHint) = '') and FAdded then
  399.       Shell_NotifyIcon(NIM_MODIFY, @FIconData);
  400.   end;
  401. end;
  402.  
  403. procedure TDCTrayIcon.Deactivate;
  404. begin
  405.   Shell_NotifyIcon(NIM_DELETE, @FIconData);
  406.   FAdded := False;
  407.   FClicked := [];
  408. end;
  409.  
  410. procedure TDCTrayIcon.ChangeIcon;
  411. var
  412.   Ico: TIcon;
  413. begin
  414.   if FAdded then begin
  415.     Ico := GetActiveIcon;
  416.     if (Ico <> nil) and not Ico.Empty then begin
  417.       UpdateNotifyData;
  418.       Shell_NotifyIcon(NIM_MODIFY, @FIconData);
  419.     end
  420.     else Deactivate;
  421.   end
  422.   else begin
  423.     if ((csDesigning in ComponentState) and FShowDesign) or
  424.       (not (csDesigning in ComponentState) and FActive) then Activate;
  425.   end;
  426. end;
  427.  
  428. procedure TDCTrayIcon.MouseMove(Shift: TShiftState; X, Y: Integer);
  429. begin
  430.   if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y);
  431. end;
  432.  
  433. procedure TDCTrayIcon.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  434. begin
  435.   if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
  436. end;
  437.  
  438. procedure TDCTrayIcon.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  439. begin
  440.   if Assigned(FOnMouseUp) then FOnMouseUp(Self, Button, Shift, X, Y);
  441. end;
  442.  
  443. procedure TDCTrayIcon.DblClick;
  444. begin
  445.   if not CheckDefaultMenuItem and Assigned(FOnDblClick) then
  446.     FOnDblClick(Self);
  447. end;
  448.  
  449. procedure TDCTrayIcon.DoClick(Button: TMouseButton; Shift: TShiftState;
  450.   X, Y: Integer);
  451. begin
  452.   if (Button = mbRight) and CheckMenuPopup(X, Y) then Exit;
  453.   if Assigned(FOnClick) then FOnClick(Self, Button, Shift, X, Y);
  454. end;
  455.  
  456. procedure TDCTrayIcon.WndProc(var Message: TMessage);
  457.  var
  458.   P: TPoint;
  459.   Shift: TShiftState;
  460. begin
  461.   try
  462.     with Message do
  463.     begin
  464.       if Msg = CM_TRAYICON then begin
  465.         case lParam of
  466.           WM_LBUTTONDBLCLK:
  467.             begin
  468.               GetCursorPos(P);
  469.               MouseDown(mbLeft, GetShiftState + [ssDouble], P.X, P.Y);
  470.               DblClick;
  471.             end;
  472.           WM_RBUTTONDBLCLK:
  473.             begin
  474.               GetCursorPos(P);
  475.               MouseDown(mbRight, GetShiftState + [ssDouble], P.X, P.Y);
  476.             end;
  477.           WM_MBUTTONDBLCLK:
  478.             begin
  479.               GetCursorPos(P);
  480.               MouseDown(mbMiddle, GetShiftState + [ssDouble], P.X, P.Y);
  481.             end;
  482.           WM_MOUSEMOVE:
  483.             begin
  484.               GetCursorPos(P);
  485.               MouseMove(GetShiftState, P.X, P.Y);
  486.             end;
  487.           WM_LBUTTONDOWN:
  488.             begin
  489.               GetCursorPos(P);
  490.               MouseDown(mbLeft, GetShiftState + [ssLeft], P.X, P.Y);
  491.               Include(FClicked, mbLeft);
  492.             end;
  493.           WM_LBUTTONUP:
  494.             begin
  495.               Shift := GetShiftState + [ssLeft];
  496.               GetCursorPos(P);
  497.               if (mbLeft in FClicked) then begin
  498.                 Exclude(FClicked, mbLeft);
  499.                 DoClick(mbLeft, Shift, P.X, P.Y);
  500.               end;
  501.               MouseUp(mbLeft, Shift, P.X, P.Y);
  502.             end;
  503.           WM_RBUTTONDOWN:
  504.             begin
  505.               GetCursorPos(P);
  506.               MouseDown(mbRight, GetShiftState + [ssRight], P.X, P.Y);
  507.               Include(FClicked, mbRight);
  508.             end;
  509.           WM_RBUTTONUP:
  510.             begin
  511.               Shift := GetShiftState + [ssRight];
  512.               GetCursorPos(P);
  513.               if (mbRight in FClicked) then begin
  514.                 Exclude(FClicked, mbRight);
  515.                 DoClick(mbRight, Shift, P.X, P.Y);
  516.               end;
  517.               MouseUp(mbRight, Shift, P.X, P.Y);
  518.             end;
  519.           WM_MBUTTONDOWN:
  520.             begin
  521.               GetCursorPos(P);
  522.               MouseDown(mbMiddle, GetShiftState + [ssMiddle], P.X, P.Y);
  523.             end;
  524.           WM_MBUTTONUP:
  525.             begin
  526.               GetCursorPos(P);
  527.               MouseUp(mbMiddle, GetShiftState + [ssMiddle], P.X, P.Y);
  528.             end;
  529.         end;
  530.       end
  531.       else Result := DefWindowProc(FHandle, Msg, wParam, lParam);
  532.     end
  533.   except
  534.     Application.HandleException(Self);
  535.   end;
  536. end;
  537.  
  538. destructor TPreviousInstance.Destroy;
  539. begin
  540.   CloseHandle(PreviousInstance.MutexHandle);
  541.   if FDefWndProc <> nil then
  542.     SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(FDefWndProc));
  543.   {$IFDEF DELPHI_V6}
  544.     Classes.FreeObjectInstance(FNewWndProc);
  545.   {$ELSE}
  546.     FreeObjectInstance(FNewWndProc);
  547.   {$ENDIF}
  548.   inherited;
  549. end;
  550.  
  551. procedure TPreviousInstance.NewWndProc(var Message: TMessage);
  552. begin
  553.   with Message do
  554.   begin
  555.     if Msg = FMessageID then
  556.     begin
  557.       if IsIconic(Application.Handle) then
  558.       begin
  559.         Application.MainForm.WindowState := wsNormal;
  560.         Application.Restore;
  561.       end;
  562.       SetForegroundWindow(Application.Handle);
  563.     end
  564.     else
  565.       Result := CallWindowProc(FDefWndProc, Application.Handle, Msg, WParam, LParam);
  566.   end;
  567. end;
  568.  
  569. procedure TPreviousInstance.SethPrevInst;
  570. begin
  571.   FMessageID   := RegisterWindowMessage(PChar(Application.Title));
  572.   FMutexHandle := CreateMutex(nil, TRUE, PChar(Application.Title));
  573.   if MutexHandle <> 0 then
  574.   begin
  575.     if GetLastError = ERROR_ALREADY_EXISTS then
  576.       hPrevInst := True
  577.     else begin
  578.       hPrevInst := False;
  579.       {$IFDEF DELPHI_V6}
  580.         FNewWndProc := Classes.MakeObjectInstance(NewWndProc);
  581.       {$ELSE}
  582.         FNewWndProc := MakeObjectInstance(NewWndProc);
  583.       {$ENDIF}
  584.       FDefWndProc := Pointer(SetWindowLong(Application.Handle, GWL_WNDPROC,
  585.         LongInt(FNewWndProc)));
  586.     end;
  587.   end
  588.   else
  589.     hPrevInst := FALSE;
  590. end;
  591.  
  592. function CheckToMultyInstance: boolean;
  593.  type
  594.    TBroadcastSystemMessage = function(Flags: DWORD; Recipients: PDWORD;
  595.      uiMessage: UINT; wParam: WPARAM; lParam: LPARAM): Longint;
  596.  var
  597.   BSMReceptions: DWORD;
  598.   User32Dll: THandle;
  599.   BroadCastSystemMessageAW: TBroadcastSystemMessage;
  600. begin
  601.   if PreviousInstance.hPrevInst then
  602.   begin
  603.     Application.ShowMainForm := False;
  604.     BSMReceptions := BSM_APPLICATIONS;
  605.     User32Dll := GetModuleHandle(user32);
  606.     if User32Dll <> 0 then
  607.     begin
  608.       {Under Win95 fixed bug with BroadCastSystemMessage}
  609.       if (Win32Platform <> VER_PLATFORM_WIN32_NT) and (Win32MajorVersion <= 4)
  610.         or ((Win32MajorVersion = 4) and (Win32MinorVersion < 10)) then
  611.         @BroadCastSystemMessageAW := GetProcAddress(User32Dll, 'BroadcastSystemMessageW')
  612.       else
  613.         @BroadCastSystemMessageAW := GetProcAddress(User32Dll, 'BroadcastSystemMessageA');
  614.  
  615.       if @BroadCastSystemMessageAW <> nil then
  616.         BroadCastSystemMessageAW(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE,
  617.           @BSMReceptions, PreviousInstance.MessageID, 0 ,0);
  618.     end;
  619.     Result := True
  620.   end
  621.   else
  622.     Result := False;
  623. end;
  624.  
  625. procedure TDCTrayIcon.LoadDefaultIcon;
  626. begin
  627.   FIcon.Handle := LoadIcon(hInstance, 'MAINICONX16');
  628.   if FIcon.Handle = 0 then
  629.     FIcon.Handle := LoadIcon(0, IDI_WINLOGO);
  630. end;
  631.  
  632. function TDCTrayIcon.Win2k: boolean;
  633. begin
  634.   Result := (Win32MajorVersion > 4) and (Win32Platform = VER_PLATFORM_WIN32_NT);
  635. end;
  636.  
  637. procedure TDCTrayIcon.ShowBaloonToolTip(const Info, InfoTitle: string;
  638.   const BaloonType: TBaloonInfoType; const Timeout: TBaloonTimeout);
  639.  const
  640.    aBaloonInfoType: array[TBaloonInfoType] of DWORD =
  641.      (NIIF_NONE, NIIF_INFO, NIIF_WARNING, NIIF_ERROR);
  642.  var
  643.   Ico: TIcon;
  644. begin
  645.   with FIconData do
  646.   begin
  647.     if Win2k then
  648.       cbSize := SizeOf(TNotifyIconDataEx)
  649.     else
  650.       cbSize := NOTIFYICONDATA_V1_SIZE;
  651.     Wnd := FHandle;
  652.     uFlags := NIF_INFO;
  653.     Ico := GetActiveIcon;
  654.     if Ico <> nil then
  655.       hIcon := Ico.Handle
  656.     else
  657.       hIcon := INVALID_HANDLE_VALUE;
  658.     uID := 0;
  659.     uTimeout := 1000 * Timeout;
  660.  
  661.     {Hide previous tooltip}
  662.     StrPCopy(szInfoTitle, '');
  663.     StrPCopy(szInfo, '');
  664.     Shell_NotifyIcon(NIM_MODIFY, @FIconData);
  665.  
  666.     StrPCopy(szInfoTitle, InfoTitle);
  667.     StrPCopy(szInfo, Info);
  668.     dwInfoFlags := aBaloonInfoType[BaloonType];
  669.     Shell_NotifyIcon(NIM_MODIFY, @FIconData);
  670.   end;
  671. end;
  672.  
  673. initialization
  674.   PreviousInstance := TPreviousInstance.Create;
  675.   PreviousInstance.SethPrevInst;
  676.  
  677. finalization
  678.   PreviousInstance.Free;
  679.  
  680. end.
  681.