使用
var ari: TAriTrayIcon;
procedure TForm1.msg11Click(Sender: TObject);
begin
showmessage('msg1');
end;
procedure TForm1.msg21Click(Sender: TObject);
begin
showmessage('msg2');
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Ari := nil;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Ari := TariTrayIcon.GetAriTrayIcon(Self);
Ari.PopupMenu := PopupMenu1;
btnMoving.Enabled := true;
end;
procedure TForm1.btnMovingClick(Sender: TObject);
begin
if not Assigned(Ari) then exit;
Ari.IconList := ImageList1;
Ari.CycleIcons := not Ari.CycleIcons;
end;
var
Pt: TPoint;
Shift: TShiftState;
I: Integer;
M: TMenuItem;
begin
if Msg.Msg = WM_TRAYNOTIFY then
begin
case Msg.lParam of
WM_LBUTTONDOWN:
if FEnabled then
begin
Shift := ShiftState + [ssLeft];
GetCursorPos(Pt);
FClickStart := True;
// if FLeftPopup then PopupAtCursor;
end;
WM_RBUTTONDOWN:
if FEnabled then
begin
Shift := ShiftState + [ssRight];
GetCursorPos(Pt);
PopupAtCursor;
end;
WM_LBUTTONUP:
if FEnabled then
begin
Shift := ShiftState + [ssLeft];
GetCursorPos(Pt);
if FClickStart then
begin
FClickStart := False;
Click;
end;
end;
WM_LBUTTONDBLCLK:
if FEnabled then
begin
M := nil;
if Assigned(FPopupMenu) then
if (FPopupMenu.AutoPopup) then //and (not FLeftPopup)
for I := PopupMenu.Items.Count -1 downto 0 do
begin
if PopupMenu.Items[I].Default then
M := PopupMenu.Items[I];
end;
if M <> nil then
M.Click;
end;
end;
end
else
case Msg.Msg of
WM_QUERYENDSESSION: begin
Msg.Result := 1;
end;
else
Msg.Result := DefWindowProc(IconData.Wnd, Msg.Msg, Msg.wParam, Msg.lParam);
end;
end;
procedure TAriTrayIcon.SetIcon(Value: TIcon);
begin
FIcon.Assign(Value);
ModifyIcon;
end;
procedure TAriTrayIcon.SetIconVisible(Value: Boolean);
begin
if Value then
ShowIcon
else
HideIcon;
end;
procedure TAriTrayIcon.SetCycleIcons(Value: Boolean);
begin
FCycleIcons := Value;
if Value then
SetIconIndex(0);
CycleTimer.Enabled := Value;
end;
procedure TAriTrayIcon.SetIconList(Value: TImageList);
begin
FIconList := Value;
SetIconIndex(0);
end;
procedure TAriTrayIcon.SetIconIndex(Value: Integer);
begin
if FIconList <> nil then
begin
FIconIndex := Value;
if Value >= FIconList.Count then
FIconIndex := FIconList.Count -1;
FIconList.GetIcon(FIconIndex, FIcon);
end
else
FIconIndex := 0;
ModifyIcon;
end;
procedure TAriTrayIcon.SetHint(Value: String);
begin
FHint := Value;
ModifyIcon;
end;
procedure TAriTrayIcon.SetShowHint(Value: Boolean);
begin
FShowHint := Value;
ModifyIcon;
end;
function TAriTrayIcon.InitIcon: Boolean;
begin
Result := False;
IconData.hIcon := FIcon.Handle;
if (FHint <> '') and (FShowHint) then
StrLCopy(IconData.szTip, PChar(FHint), SizeOf(IconData.szTip)-1)
else
IconData.szTip := '';
Result := True;
end;
function TAriTrayIcon.ShowIcon: Boolean;
begin
Result := False;
FIconVisible := True;
begin
if InitIcon then
Result := Shell_NotifyIcon(NIM_ADD, @IconData);
end;
end;
function TAriTrayIcon.HideIcon: Boolean;
begin
Result := False;
FIconVisible := False;
begin
if InitIcon then
Result := Shell_NotifyIcon(NIM_DELETE, @IconData);
end;
end;
function TAriTrayIcon.ModifyIcon: Boolean;
begin
Result := False;
if InitIcon then
Result := Shell_NotifyIcon(NIM_MODIFY, @IconData);
end;
procedure TAriTrayIcon.TimerCycle(Sender: TObject);
begin
if Assigned(FIconList) then
begin
FIconList.GetIcon(FIconIndex, FIcon);
// CycleIcon;
ModifyIcon;
if FIconIndex < FIconList.Count-1 then
SetIconIndex(FIconIndex+1)
else
SetIconIndex(0);
end;
end;
function TAriTrayIcon.ShowBalloonHint(Title: String; Text: String;
IconType: TBalloonHintIcon; TimeoutSecs: TBalloonHintTimeOut): Boolean;
const
aBalloonIconTypes: array[TBalloonHintIcon] of Byte =
(NIIF_NONE, NIIF_INFO, NIIF_WARNING, NIIF_ERROR);
begin
if FEnabled then
begin
with IconData do
begin
uFlags := uFlags or NIF_INFO;
StrPCopy(szInfo, '');
end;
ModifyIcon;
with IconData do
begin
uFlags := uFlags or NIF_INFO;
StrPCopy(szInfo, Text);
StrPCopy(szInfoTitle, Title);
uTimeout := TimeoutSecs * 1000;
dwInfoFlags := aBalloonIconTypes[IconType];
end;
Result := ModifyIcon;
with IconData do
uFlags := NIF_ICON + NIF_MESSAGE + NIF_TIP;
end
else
Result := True;
end;
function TAriTrayIcon.Refresh: Boolean;
begin
Result := ModifyIcon;
end;
procedure TAriTrayIcon.PopupAtCursor;
var
CursorPos: TPoint;
begin
if Assigned(PopupMenu) then
if PopupMenu.AutoPopup then
if GetCursorPos(CursorPos) then
begin
Application.ProcessMessages;
SetForegroundWindow(Handle);
if Owner is TWinControl then
SetForegroundWindow((Owner as TWinControl).Handle);
if Owner is TWinControl then
PostMessage((Owner as TWinControl).Handle, WM_NULL, 0, 0)
end;
end;
procedure TAriTrayIcon.Click;
begin
ShowMainForm;
// if Assigned(FOnClick) then FOnClick(Self);
end;
procedure TAriTrayIcon.DoMinimizeToTray;
begin
HideMainForm;
IconVisible := True;
end;
procedure TAriTrayIcon.ShowMainForm;
begin
if Owner is TWinControl then
if Application.MainForm <> nil then
begin
ShowWindow(Application.Handle, SW_RESTORE);
Application.MainForm.Visible := True;
end;
end;
procedure TAriTrayIcon.HideMainForm;
begin
if Owner is TWinControl then
if Application.MainForm <> nil then
begin
Application.MainForm.Visible := False;
ShowWindow(Application.Handle, SW_HIDE);
end;
end;
{
procedure TAriTrayIcon.FreeInstance;
begin
nCount := 0;
inherited FreeInstance;
Instance := nil;
end;
class function TAriTrayIcon.NewInstance: TObject;
begin
if not Assigned(Instance) then
Instance := inherited NewInstance;
Inc(nCount);
Result := Instance;
end;
}
class function TAriTrayIcon.GetAriTrayIcon(AOwner: TComponent): TAriTrayIcon;
begin
if not Assigned(AriTrayIcon1) then
AriTrayIcon1 := TAriTrayIcon.Create(AOwner);
Inc(nCount);
result := AriTrayIcon1;
end;
class procedure TAriTrayIcon.FreeAriTrayIcon;
begin
Dec(nCount);
if nCount > 0 then exit;
if Assigned(AriTrayIcon1) then FreeAndNil(AriTrayIcon1);
end;
class procedure TAriTrayIcon.FreeAllATI;
begin
nCount := 0;
if Assigned(AriTrayIcon1) then FreeAndNil(AriTrayIcon1);
end;
if not (csDesigning in ComponentState) then
begin
HookApp;
if Owner is TWinControl then
HookForm;
end;
ShowIcon;
end;
destructor TAriTrayIcon.Destroy;
begin
SetIconVisible(False);
FIcon.Free;
DeallocateHWnd(IconData.Wnd);
CycleTimer.Free;
if not (csDesigning in ComponentState) then
begin
UnhookApp;
if Owner is TWinControl then
UnhookForm;
end;
inherited Destroy;
end;
procedure TAriTrayIcon.Loaded;
begin
inherited Loaded;
ModifyIcon;
SetIconVisible(FIconVisible);
end;
procedure TAriTrayIcon.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = IconList) and (Operation = opRemove) then
begin
FIconList := nil;
IconList := nil;
end;
if (AComponent = PopupMenu) and (Operation = opRemove) then
begin
FPopupMenu := nil;
PopupMenu := nil;
end;
end;
procedure TAriTrayIcon.UnhookApp;
begin
if Assigned(OldAppProc) then
SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(OldAppProc));
if Assigned(NewAppProc) then
FreeObjectInstance(NewAppProc);
NewAppProc := nil;
OldAppProc := nil;
end;
procedure TAriTrayIcon.HookAppProc(var Msg: TMessage);
begin
case Msg.Msg of
WM_SIZE:
if Msg.wParam = SIZE_MINIMIZED then
begin
DoMinimizeToTray;
end;
end;
if Msg.Msg = WM_TASKBARCREATED then
if FIconVisible then
ShowIcon;
procedure TAriTrayIcon.HookForm;
begin
if (Owner as TWinControl) <> nil then
begin
OldWndProc := Pointer(GetWindowLong((Owner as TWinControl).Handle, GWL_WNDPROC));
NewWndProc := MakeObjectInstance(HookFormProc);
SetWindowLong((Owner as TWinControl).Handle, GWL_WNDPROC, LongInt(NewWndProc));
end;
end;
procedure TAriTrayIcon.UnhookForm;
begin
if ((Owner as TWinControl) <> nil) and (Assigned(OldWndProc)) then
SetWindowLong((Owner as TWinControl).Handle, GWL_WNDPROC, LongInt(OldWndProc));
if Assigned(NewWndProc) then
FreeObjectInstance(NewWndProc);
NewWndProc := nil;
OldWndProc := nil;
end;
procedure TAriTrayIcon.HookFormProc(var Msg: TMessage);
begin
case Msg.Msg of
WM_SHOWWINDOW: begin
if (Msg.lParam = 0) and (Msg.wParam = 1) then
begin
ShowWindow(Application.Handle, SW_RESTORE);
SetForegroundWindow(Application.Handle);
SetForegroundWindow((Owner as TWinControl).Handle);
end;
end;
WM_ACTIVATE: begin
if Assigned(Screen.ActiveControl) then
if (Msg.WParamLo = WA_ACTIVE) or (Msg.WParamLo = WA_CLICKACTIVE) then
if Assigned(Screen.ActiveControl.Parent) then
begin
if HWND(Msg.lParam) <> Screen.ActiveControl.Parent.Handle then
SetFocus(Screen.ActiveControl.Handle);
end
else
begin
if HWND(Msg.lParam) <> Screen.ActiveControl.Handle then
SetFocus(Screen.ActiveControl.Handle);
end;
end;
end;
Msg.Result := CallWindowProc(OldWndProc, (Owner as TWinControl).Handle,
Msg.Msg, Msg.wParam, Msg.lParam);
end;
function ShiftState: TShiftState;
begin
Result := [];
if GetAsyncKeyState(VK_SHIFT) < 0 then
Include(Result, ssShift);
if GetAsyncKeyState(VK_CONTROL) < 0 then
Include(Result, ssCtrl);
if GetAsyncKeyState(VK_MENU) < 0 then
Include(Result, ssAlt);
end;