我的意思是你启动程序的方法要参照这里的 FileExecute,因为它使用了<br>CreateProcess,然后你就可以利用这个句柄调用 TerminateProcess 关闭<br>程序。<br>{*******************************************************}<br>{ }<br>{ Delphi VCL Extensions (RX) }<br>{ }<br>{ Copyright (c) 1995, 1996 AO ROSNO }<br>{ Copyright (c) 1997 Master-Bank }<br>{ }<br>{*******************************************************}<br><br>{.$DEFINE USE_TIMER}<br>{ - Use Windows timer instead thread to the animated TrayIcon }<br><br>{$IFNDEF WIN32}<br> {$DEFINE USE_TIMER} { - Always use timer in 16-bit version }<br>{$ENDIF}<br><br>unit RXShell;<br><br>{$I RX.INC}<br>{$P+,W-,R-}<br><br>interface<br><br>uses {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF} Messages,<br> Classes, Graphics, SysUtils, Forms, Controls, Menus, ShellAPI,<br> {$IFDEF USE_TIMER} ExtCtrls, {$ENDIF} IcoList;<br><br>type<br>{$IFNDEF WIN32}<br> PNotifyIconData = ^TNotifyIconData;<br> TNotifyIconData = record<br> cbSize: Longint;<br> Wnd: Longint;<br> uID: Longint;<br> uFlags: Longint;<br> uCallbackMessage: Longint;<br> hIcon: Longint;<br> szTip: array [0..63] of Char;<br> end;<br>{$ENDIF}<br><br> TMouseButtons = set of TMouseButton;<br><br>{ TRxTrayIcon }<br><br> TRxTrayIcon = class(TComponent)<br> private<br> FHandle: HWnd;<br> FActive: Boolean;<br> FAdded: Boolean;<br> FAnimated: Boolean;<br> FEnabled: Boolean;<br> FClicked: TMouseButtons;<br> FIconIndex: Integer;<br> FInterval: Word;<br> FIconData: TNotifyIconData;<br> FIcon: TIcon;<br> FIconList: TIconList;<br>{$IFDEF USE_TIMER}<br> FTimer: TTimer;<br>{$ELSE}<br> FTimer: TThread;<br>{$ENDIF}<br> FHint: string;<br> FShowDesign: Boolean;<br> FPopupMenu: TPopupMenu;<br> FOnClick: TMouseEvent;<br> FOnDblClick: TNotifyEvent;<br> FOnMouseMove: TMouseMoveEvent;<br> FOnMouseDown: TMouseEvent;<br> FOnMouseUp: TMouseEvent;<br> procedure ChangeIcon;<br>{$IFDEF USE_TIMER}<br> procedure Timer(Sender: TObject);<br>{$ELSE}<br> procedure Timer;<br>{$ENDIF}<br> procedure SendCancelMode;<br> function CheckMenuPopup(X, Y: Integer): Boolean;<br> function CheckDefaultMenuItem: Boolean;<br> procedure SetHint(const Value: string);<br> procedure SetIcon(Value: TIcon);<br> procedure SetIconList(Value: TIconList);<br> procedure SetPopupMenu(Value: TPopupMenu);<br> procedure Activate;<br> procedure Deactivate;<br> procedure SetActive(Value: Boolean);<br> function GetAnimated: Boolean;<br> procedure SetAnimated(Value: Boolean);<br> procedure SetShowDesign(Value: Boolean);<br> procedure SetInterval(Value: Word);<br> procedure IconChanged(Sender: TObject);<br> procedure WndProc(var Message: TMessage);<br> function GetActiveIcon: TIcon;<br> protected<br> procedure DblClick; dynamic;<br> procedure DoClick(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic;<br> procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic;<br> procedure MouseMove(Shift: TShiftState; X, Y: Integer); dynamic;<br> procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic;<br> procedure Loaded; override;<br> procedure Notification(AComponent: TComponent; Operation: TOperation); override;<br> procedure UpdateNotifyData; virtual;<br> public<br> constructor Create(AOwner: TComponent); override;<br> destructor Destroy; override;<br> procedure Hide;<br> procedure Show;<br> property Handle: HWnd read FHandle;<br> published<br> property Active: Boolean read FActive write SetActive default True;<br> property Enabled: Boolean read FEnabled write FEnabled default True;<br> property Hint: string read FHint write SetHint;<br> property Icon: TIcon read FIcon write SetIcon;<br> property Icons: TIconList read FIconList write SetIconList;<br> { Ensure Icons is declared before Animated }<br> property Animated: Boolean read GetAnimated write SetAnimated default False;<br> property Interval: Word read FInterval write SetInterval default 150;<br> property PopupMenu: TPopupMenu read FPopupMenu write SetPopupMenu;<br> property ShowDesign: Boolean read FShowDesign write SetShowDesign stored False;<br> property OnClick: TMouseEvent read FOnClick write FOnClick;<br> property OnDblClick: TNotifyEvent read FOnDblClick write FOnDblClick;<br> property OnMouseMove: TMouseMoveEvent read FOnMouseMove write FOnMouseMove;<br> property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;<br> property OnMouseUp: TMouseEvent read FOnMouseUp write FOnMouseUp;<br> end;<br><br>function IconExtract(const FileName: string; Id: Integer): TIcon;<br>procedure WinAbout(const AppName, Stuff: string);<br><br>type<br> TExecState = (esNormal, esMinimized, esMaximized, esHidden);<br><br>function FileExecute(const FileName, Params, StartDir: string;<br> InitialState: TExecState): THandle;<br>function FileExecuteWait(const FileName, Params, StartDir: string;<br> InitialState: TExecState): Integer;<br><br>implementation<br><br>uses RxConst, RxCConst, VCLUtils, MaxMin;<br><br>{$IFNDEF WIN32}<br>const<br> Shell = 'shell';<br><br>function ExtractAssociatedIcon(hInst: THandle; lpIconPath: PChar;<br> var lpiIcon: Word): HIcon; far; external Shell;<br>function ShellAbout(Wnd: HWnd; App, Stuff: PChar; Icon: HIcon): Integer;<br> far; external Shell;<br>{$ENDIF WIN32}<br><br>procedure WinAbout(const AppName, Stuff: string);<br>var<br>{$IFNDEF WIN32}<br> szApp, szStuff: array[0..255] of Char;<br>{$ENDIF}<br> Wnd: HWnd;<br> Icon: HIcon;<br>begin<br> if Application.MainForm <> nil then Wnd := Application.MainForm.Handle<br> else Wnd := 0;<br> Icon := Application.Icon.Handle;<br> if Icon = 0 then Icon := LoadIcon(0, IDI_APPLICATION);<br>{$IFDEF WIN32}<br> ShellAbout(Wnd, PChar(AppName), PChar(Stuff), Icon);<br>{$ELSE}<br> StrPLCopy(szApp, AppName, SizeOf(szApp) - 1);<br> StrPLCopy(szStuff, Stuff, SizeOf(szStuff) - 1);<br> ShellAbout(Wnd, szApp, szStuff, Icon);<br>{$ENDIF}<br>end;<br><br>function IconExtract(const FileName: string; Id: Integer): TIcon;<br>var<br> S: array[0..255] of char;<br> IconHandle: HIcon;<br> Index: Word;<br>begin<br> Result := TIcon.Create;<br> try<br> StrPLCopy(S, FileName, SizeOf(S) - 1);<br> IconHandle := ExtractIcon(hInstance, S, Id);<br> if IconHandle < 2 then begin<br> Index := Id;<br> IconHandle := ExtractAssociatedIcon(hInstance, S, Index);<br> end;<br> if IconHandle < 2 then begin<br> if IconHandle = 1 then<br> raise EResNotFound.Create(LoadStr(SFileNotExec))<br> else begin<br> Result.Free;<br> Result := nil;<br> end;<br> end else Result.Handle := IconHandle;<br> except<br> Result.Free;<br> raise;<br> end;<br>end;<br><br>const<br> ShowCommands: array[TExecState] of Integer =<br> (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED, SW_HIDE);<br><br>function FileExecute(const FileName, Params, StartDir: string;<br> InitialState: TExecState): THandle;<br>{$IFDEF WIN32}<br>begin<br> Result := ShellExecute(Application.Handle, nil, PChar(FileName),<br> PChar(Params), PChar(StartDir), ShowCommands[InitialState]);<br>end;<br>{$ELSE}<br>var<br> cFileName, cParams, cPath: array [0..80] of Char;<br>begin<br> Result := ShellExecute(Application.Handle, nil, StrPCopy(cFileName,<br> FileName), StrPCopy(cParams, Params), StrPCopy(cPath, StartDir),<br> ShowCommands[InitialState]);<br>end;<br>{$ENDIF}<br><br>function FileExecuteWait(const FileName, Params, StartDir: string;<br> InitialState: TExecState): Integer;<br>{$IFDEF WIN32}<br>var<br> Info: TShellExecuteInfo;<br> ExitCode: DWORD;<br>begin<br> FillChar(Info, SizeOf(Info), 0);<br> Info.cbSize := SizeOf(TShellExecuteInfo);<br> with Info do begin<br> fMask := SEE_MASK_NOCLOSEPROCESS;<br> Wnd := Application.Handle;<br> lpFile := PChar(FileName);<br> lpParameters := PChar(Params);<br> lpDirectory := PChar(StartDir);<br> nShow := ShowCommands[InitialState];<br> end;<br> if ShellExecuteEx(@Info) then begin<br> repeat<br> Application.ProcessMessages;<br> GetExitCodeProcess(Info.hProcess, ExitCode);<br> until (ExitCode <> STILL_ACTIVE) or Application.Terminated;<br> Result := ExitCode;<br> end<br> else Result := -1;<br>end;<br>{$ELSE}<br>var<br> Task: THandle;<br>begin<br> Result := 0;<br> Task := FileExecute(FileName, Params, StartDir, InitialState);<br> if Task >= HINSTANCE_ERROR then begin<br> repeat<br> Application.ProcessMessages;<br> until (GetModuleUsage(Task) = 0) or Application.Terminated;<br> end<br> else Result := -1;<br>end;<br>{$ENDIF}<br><br>{$IFNDEF USE_TIMER}<br><br>{ TTimerThread }<br><br>type<br> TTimerThread = class(TThread)<br> private<br> FOwnerTray: TRxTrayIcon;<br> protected<br> procedure Execute; override;<br> public<br> constructor Create(TrayIcon: TRxTrayIcon; CreateSuspended: Boolean);<br> end;<br><br>constructor TTimerThread.Create(TrayIcon: TRxTrayIcon; CreateSuspended: Boolean);<br>begin<br> FOwnerTray := TrayIcon;<br> inherited Create(CreateSuspended);<br> FreeOnTerminate := True;<br>end;<br><br>procedure TTimerThread.Execute;<br><br> function ThreadClosed: Boolean;<br> begin<br> Result := Terminated or Application.Terminated or (FOwnerTray = nil);<br> end;<br><br>begin<br> while not Terminated do begin<br> if not ThreadClosed then<br> if SleepEx(FOwnerTray.FInterval, False) = 0 then begin<br> if not ThreadClosed and FOwnerTray.Animated then<br> FOwnerTray.Timer;<br> end;<br> end;<br>end;<br><br>{$ENDIF USE_TIMER}<br><br>{$IFNDEF WIN32}<br><br>type<br> TLoadLibrary32 = function (FileName: PChar; Handle, Special: Longint): Longint;<br> TFreeLibrary32 = function (Handle: Longint): Bool;<br> TGetAddress32 = function (Handle: Longint; ProcName: PChar): Pointer;<br> TCallProc32 = function (Msg: Longint; Data: PNotifyIconData; ProcHandle: Pointer;<br> AddressConvert, Params: Longint): Longint;<br><br>const<br> NIM_ADD = $00000000;<br> NIM_MODIFY = $00000001;<br> NIM_DELETE = $00000002;<br><br> NIF_MESSAGE = $00000001;<br> NIF_ICON = $00000002;<br> NIF_TIP = $00000004;<br><br>const<br> Shell32: Longint = 0;<br> ProcAddr: Pointer = nil;<br> FreeLib32: TFreeLibrary32 = nil;<br> CallPrc32: TCallProc32 = nil;<br><br>procedure FreeHandles; far;<br>begin<br> if (ProcAddr <> nil) and Assigned(FreeLib32) then FreeLib32(Shell32);<br>end;<br><br>procedure InitHandles;<br>var<br> Kernel16: THandle;<br> LoadLib32: TLoadLibrary32;<br> GetAddr32: TGetAddress32;<br>begin<br> Kernel16 := GetModuleHandle('kernel');<br> @LoadLib32 := GetProcAddress(Kernel16, 'LoadLibraryEx32W');<br> @FreeLib32 := GetProcAddress(Kernel16, 'FreeLibrary32W');<br> @GetAddr32 := GetProcAddress(Kernel16, 'GetProcAddress32W');<br> @CallPrc32 := GetProcAddress(Kernel16, 'CallProc32W');<br> if (@LoadLib32 <> nil) and (@FreeLib32 <> nil) and (@GetAddr32 <> nil)<br> and (@CallPrc32 <> nil) then<br> begin<br> Shell32 := LoadLib32('shell32', 0, 0);<br> if Shell32 >= HINSTANCE_ERROR then begin<br> ProcAddr := GetAddr32(Shell32, 'Shell_NotifyIcon');<br> if ProcAddr = nil then begin<br> FreeLib32(Shell32);<br> Shell32 := 1;<br> end<br> else AddExitProc(FreeHandles);<br> end<br> else Shell32 := 1;<br> end;<br>end;<br><br>function Shell_NotifyIcon(dwMessage: Longint; lpData: PNotifyIconData): Bool;<br>begin<br> if (ProcAddr = nil) and (Shell32 <> 1) then InitHandles;<br> if ProcAddr <> nil then<br> Result := Bool(CallPrc32(dwMessage, lpData, ProcAddr, $01, 2));<br>end;<br><br>{$ENDIF WIN32}<br><br>{ TRxTrayIcon }<br><br>constructor TRxTrayIcon.Create(AOwner: Tcomponent);<br>begin<br> inherited Create(AOwner);<br> FHandle := AllocateHWnd(WndProc);<br> FIcon := TIcon.Create;<br> FIcon.OnChange := IconChanged;<br> FIconList := TIconList.Create;<br> FIconList.OnChange := IconChanged;<br> FIconIndex := -1;<br> FEnabled := True;<br> FInterval := 150;<br> FActive := True;<br>end;<br><br>destructor TRxTrayIcon.Destroy;<br>begin<br> Destroying;<br> FEnabled := False;<br> FIconList.OnChange := nil;<br> FIcon.OnChange := nil;<br> SetAnimated(False);<br> Deactivate;<br> DeallocateHWnd(FHandle);<br> FIcon.Free;<br> FIcon := nil;<br> FIconList.Free;<br> FIconList := nil;<br> inherited Destroy;<br>end;<br><br>procedure TRxTrayIcon.Loaded;<br>begin<br> inherited Loaded;<br> if FActive and not (csDesigning in ComponentState) then Activate;<br>end;<br><br>procedure TRxTrayIcon.Notification(AComponent: TComponent;<br> Operation: TOperation);<br>begin<br> inherited Notification(AComponent, Operation);<br> if (AComponent = PopupMenu) and (Operation = opRemove) then<br> PopupMenu := nil;<br>end;<br><br>procedure TRxTrayIcon.SetPopupMenu(Value: TPopupMenu);<br>begin<br> FPopupMenu := Value;<br>{$IFDEF WIN32}<br> if Value <> nil then Value.FreeNotification(Self);<br>{$ENDIF}<br>end;<br><br>procedure TRxTrayIcon.SendCancelMode;<br>var<br> F: TForm;<br>begin<br> if not (csDestroying in ComponentState) then begin<br> F := Screen.ActiveForm;<br> if F = nil then F := Application.MainForm;<br> if F <> nil then F.SendCancelMode(nil);<br> end;<br>end;<br><br>function TRxTrayIcon.CheckMenuPopup(X, Y: Integer): Boolean;<br>begin<br> Result := False;<br> if not (csDesigning in ComponentState) and Active and<br> (PopupMenu <> nil) and PopupMenu.AutoPopup then<br> begin<br> PopupMenu.PopupComponent := Self;<br> SendCancelMode;<br> SwitchToWindow(FHandle, False);<br> Application.ProcessMessages;<br> try<br> PopupMenu.Popup(X, Y);<br> finally<br>{$IFDEF WIN32}<br> SwitchToWindow(FHandle, False);<br>{$ENDIF}<br> end;<br> Result := True;<br> end;<br>end;<br><br>function TRxTrayIcon.CheckDefaultMenuItem: Boolean;<br>{$IFDEF WIN32}<br>var<br> Item: TMenuItem;<br> I: Integer;<br>{$ENDIF}<br>begin<br> Result := False;<br>{$IFDEF WIN32}<br> if not (csDesigning in ComponentState) and Active and<br> (PopupMenu <> nil) and (PopupMenu.Items <> nil) then<br> begin<br> I := 0;<br> while (I < PopupMenu.Items.Count) do begin<br> Item := PopupMenu.Items;<br> if Item.Default and Item.Enabled then begin<br> Item.Click;<br> Result := True;<br> Break;<br> end;<br> Inc(I);<br> end;<br> end;<br>{$ENDIF}<br>end;<br><br>procedure TRxTrayIcon.SetIcon(Value: TIcon);<br>begin<br> FIcon.Assign(Value);<br>end;<br><br>procedure TRxTrayIcon.SetIconList(Value: TIconList);<br>begin<br> FIconList.Assign(Value);<br>end;<br><br>function TRxTrayIcon.GetActiveIcon: TIcon;<br>begin<br> Result := FIcon;<br> if (FIconList <> nil) and (FIconList.Count > 0) and Animated then<br> Result := FIconList[Max(Min(FIconIndex, FIconList.Count - 1), 0)];<br>end;<br><br>function TRxTrayIcon.GetAnimated: Boolean;<br>begin<br> Result := FAnimated;<br>end;<br><br>procedure TRxTrayIcon.SetAnimated(Value: Boolean);<br>begin<br> Value := Value and Assigned(FIconList) and (FIconList.Count > 0);<br> if Value <> Animated then begin<br> if Value then begin<br>{$IFDEF USE_TIMER}<br> FTimer := TTimer.Create(Self);<br> FTimer.Enabled := FAdded;<br> FTimer.Interval := FInterval;<br> FTimer.OnTimer := Timer;<br>{$ELSE}<br> FTimer := TTimerThread.Create(Self, not FAdded);<br>{$ENDIF}<br> FAnimated := True;<br> end<br> else begin<br> FAnimated := False;<br>{$IFDEF USE_TIMER}<br> FTimer.Free;<br> FTimer := nil;<br>{$ELSE}<br> TTimerThread(FTimer).FOwnerTray := nil;<br> while FTimer.Suspended do FTimer.Resume;<br> FTimer.Terminate;<br>{$ENDIF}<br> end;<br> FIconIndex := 0;<br> ChangeIcon;<br> end;<br>end;<br><br>procedure TRxTrayIcon.SetActive(Value: Boolean);<br>begin<br> if (Value <> FActive) then begin<br> FActive := Value;<br> if not (csDesigning in ComponentState) then<br> if Value then Activate else Deactivate;<br> end;<br>end;<br><br>procedure TRxTrayIcon.Show;<br>begin<br> Active := True;<br>end;<br><br>procedure TRxTrayIcon.Hide;<br>begin<br> Active := False;<br>end;<br><br>procedure TRxTrayIcon.SetShowDesign(Value: Boolean);<br>begin<br> if (csDesigning in ComponentState) then begin<br> if Value then Activate else Deactivate;<br> FShowDesign := FAdded;<br> end;<br>end;<br><br>procedure TRxTrayIcon.SetInterval(Value: Word);<br>begin<br> if FInterval <> Value then begin<br> FInterval := Value;<br>{$IFDEF USE_TIMER}<br> if Animated then FTimer.Interval := FInterval;<br>{$ENDIF}<br> end;<br>end;<br><br>{$IFDEF USE_TIMER}<br>procedure TRxTrayIcon.Timer(Sender: TObject);<br>{$ELSE}<br>procedure TRxTrayIcon.Timer;<br>{$ENDIF}<br>begin<br> if not (csDestroying in ComponentState) and Animated then begin<br> Inc(FIconIndex);<br> if (FIconList = nil) or (FIconIndex >= FIconList.Count) then<br> FIconIndex := 0;<br> ChangeIcon;<br> end;<br>end;<br><br>procedure TRxTrayIcon.IconChanged(Sender: TObject);<br>begin<br> ChangeIcon;<br>end;<br><br>procedure TRxTrayIcon.SetHint(const Value: string);<br>begin<br> if FHint <> Value then begin<br> FHint := Value;<br> ChangeIcon;<br> end;<br>end;<br><br>procedure TRxTrayIcon.UpdateNotifyData;<br>var<br> Ico: TIcon;<br>begin<br> with FIconData do begin<br> cbSize := SizeOf(TNotifyIconData);<br> Wnd := FHandle;<br> uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;<br> Ico := GetActiveIcon;<br> if Ico <> nil then hIcon := Ico.Handle<br>{$IFDEF WIN32}<br> else hIcon := INVALID_HANDLE_VALUE;<br>{$ELSE}<br> else hIcon := 0;<br>{$ENDIF}<br> StrPLCopy(szTip, GetShortHint(FHint), SizeOf(szTip) - 1);<br> uCallbackMessage := CM_TRAYICON;<br> uID := 0;<br> end;<br>end;<br><br>procedure TRxTrayIcon.Activate;<br>var<br> Ico: TIcon;<br>begin<br> Deactivate;<br> Ico := GetActiveIcon;<br> if (Ico <> nil) and not Ico.Empty then begin<br> FClicked := [];<br> UpdateNotifyData;<br> FAdded := Shell_NotifyIcon(NIM_ADD, @FIconData);<br> if (GetShortHint(FHint) = '') and FAdded then<br> Shell_NotifyIcon(NIM_MODIFY, @FIconData);<br>{$IFDEF USE_TIMER}<br> if Animated then FTimer.Enabled := True;<br>{$ELSE}<br> if Animated then<br> while FTimer.Suspended do FTimer.Resume;<br>{$ENDIF}<br> end;<br>end;<br><br>procedure TRxTrayIcon.Deactivate;<br>begin<br> Shell_NotifyIcon(NIM_DELETE, @FIconData);<br> FAdded := False;<br> FClicked := [];<br>{$IFDEF USE_TIMER}<br> if Animated then FTimer.Enabled := False;<br>{$ELSE}<br> if Animated and not FTimer.Suspended then FTimer.Suspend;<br>{$ENDIF}<br>end;<br><br>procedure TRxTrayIcon.ChangeIcon;<br>var<br> Ico: TIcon;<br>begin<br> if (FIconList = nil) or (FIconList.Count = 0) then SetAnimated(False);<br> if FAdded then begin<br> Ico := GetActiveIcon;<br> if (Ico <> nil) and not Ico.Empty then begin<br> UpdateNotifyData;<br> Shell_NotifyIcon(NIM_MODIFY, @FIconData);<br> end<br> else Deactivate;<br> end<br> else begin<br> if ((csDesigning in ComponentState) and FShowDesign) or<br> (not (csDesigning in ComponentState) and FActive) then Activate;<br> end;<br>end;<br><br>procedure TRxTrayIcon.MouseMove(Shift: TShiftState; X, Y: Integer);<br>begin<br> if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y);<br>end;<br><br>procedure TRxTrayIcon.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);<br>begin<br> if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);<br>end;<br><br>procedure TRxTrayIcon.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);<br>begin<br> if Assigned(FOnMouseUp) then FOnMouseUp(Self, Button, Shift, X, Y);<br>end;<br><br>procedure TRxTrayIcon.DblClick;<br>begin<br> if not CheckDefaultMenuItem and Assigned(FOnDblClick) then<br> FOnDblClick(Self);<br>end;<br><br>procedure TRxTrayIcon.DoClick(Button: TMouseButton; Shift: TShiftState;<br> X, Y: Integer);<br>begin<br> if (Button = mbRight) and CheckMenuPopup(X, Y) then Exit;<br> if Assigned(FOnClick) then FOnClick(Self, Button, Shift, X, Y);<br>end;<br><br>procedure TRxTrayIcon.WndProc(var Message: TMessage);<br><br> function GetShiftState: TShiftState;<br> begin<br> Result := [];<br> if GetKeyState(VK_SHIFT) < 0 then Include(Result, ssShift);<br> if GetKeyState(VK_CONTROL) < 0 then Include(Result, ssCtrl);<br> if GetKeyState(VK_MENU) < 0 then Include(Result, ssAlt);<br> end;<br><br>var<br> P: TPoint;<br> Shift: TShiftState;<br>begin<br> try<br> with Message do<br> if (Msg = CM_TRAYICON) and Self.FEnabled then begin<br> case lParam of<br> WM_LBUTTONDBLCLK:<br> begin<br> DblClick;<br> GetCursorPos(P);<br> MouseDown(mbLeft, GetShiftState + [ssDouble], P.X, P.Y);<br> end;<br> WM_RBUTTONDBLCLK:<br> begin<br> GetCursorPos(P);<br> MouseDown(mbRight, GetShiftState + [ssDouble], P.X, P.Y);<br> end;<br> WM_MBUTTONDBLCLK:<br> begin<br> GetCursorPos(P);<br> MouseDown(mbMiddle, GetShiftState + [ssDouble], P.X, P.Y);<br> end;<br> WM_MOUSEMOVE:<br> begin<br> GetCursorPos(P);<br> MouseMove(GetShiftState, P.X, P.Y);<br> end;<br> WM_LBUTTONDOWN:<br> begin<br> GetCursorPos(P);<br> MouseDown(mbLeft, GetShiftState + [ssLeft], P.X, P.Y);<br> Include(FClicked, mbLeft);<br> end;<br> WM_LBUTTONUP:<br> begin<br> Shift := GetShiftState + [ssLeft];<br> GetCursorPos(P);<br> if mbLeft in FClicked then begin<br> Exclude(FClicked, mbLeft);<br> DoClick(mbLeft, Shift, P.X, P.Y);<br> end;<br> MouseUp(mbLeft, Shift, P.X, P.Y);<br> end;<br> WM_RBUTTONDOWN:<br> begin<br> GetCursorPos(P);<br> MouseDown(mbRight, GetShiftState + [ssRight], P.X, P.Y);<br> Include(FClicked, mbRight);<br> end;<br> WM_RBUTTONUP:<br> begin<br> Shift := GetShiftState + [ssRight];<br> GetCursorPos(P);<br> if mbRight in FClicked then begin<br> Exclude(FClicked, mbRight);<br> DoClick(mbRight, Shift, P.X, P.Y);<br> end;<br> MouseUp(mbRight, Shift, P.X, P.Y);<br> end;<br> WM_MBUTTONDOWN:<br> begin<br> GetCursorPos(P);<br> MouseDown(mbMiddle, GetShiftState + [ssMiddle], P.X, P.Y);<br> end;<br> WM_MBUTTONUP:<br> begin<br> GetCursorPos(P);<br> MouseUp(mbMiddle, GetShiftState + [ssMiddle], P.X, P.Y);<br> end;<br> end;<br> end<br> else Result := DefWindowProc(FHandle, Msg, wParam, lParam);<br> except<br> Application.HandleException(Self);<br> end;<br>end;<br><br>end.