constructor TTrayComp.Create(AOwner: TComponent); var i: Integer; Already:Byte; begin inherited Create(AOwner); { for hiding } FHideApp:=True; FShowForm:=True; FShowInTaskBar := False; FRunMinimized:=False; NewWndProc := nil; OldWndProc := nil; Already:=0; if (csDesigning in ComponentState) then if (AOwner is TForm) then with (AOwner as TForm) do begin for i := 0 to ComponentCount - 1 do if Components[i] is TTrayComp then Inc(Already); if Already>1 then raise Exception.Create('You can''t create a second TTrayComp on the same form!'); end else raise Exception.Create('You can create a TTrayComp only on the form!'); { for icon } FIcon := TIcon.Create; FShowIcon:=True; FDefRClick:=False; FDefLClick:=True; if (csDesigning in ComponentState) then SetIcon(Application.Icon); end;
destructor TTrayComp.Destroy; begin { for hiding } RemoveHook; { for icon } if not (csDesigning in ComponentState)then if FShowIcon then EraseIcon; FIcon.Free; inherited Destroy; end;
procedure TTrayComp.Loaded; begin inherited Loaded; FhWnd:=(Owner as TForm).Handle; { terminate if minimized not allowed } if IsIconic(FhWnd)and not FRunMinimized then Application.Terminate; InsertHook; { hide the form at start-up if needed } if not FShowForm then begin (Owner as TForm).Visible:=False; Application.ShowMainForm:=False; end; end;
procedure TTrayComp.DoHiding; begin if not (csDesigning in ComponentState) then if not FShowInTaskBar then ShowWindow(FindWindow(nil, @Application.Title[1]), SW_HIDE); end;
procedure TTrayComp.SetShowInTaskBar(Value:Boolean); begin FShowInTaskBar:=Value; DoHiding; end;
procedure TTrayComp.InsertHook; begin if Owner <> nil then begin OldWndProc := TFarProc(GetWindowLong(FhWnd, GWL_WNDPROC)); NewWndProc := MakeObjectInstance(OurWndProc); SetWindowLong(FhWnd, GWL_WNDPROC,Integer(NewWndProc)); end; end;
procedure TTrayComp.RemoveHook; begin if (Owner <> nil) and Assigned(OldWndProc) then SetWindowLong(FhWnd, GWL_WNDPROC,Integer(OldWndProc)); if Assigned(NewWndProc) then FreeObjectInstance(NewWndProc); NewWndProc := nil; OldWndProc := nil; end;
procedure TTrayComp.OurWndProc(var M: TMessage); begin if Owner <> nil then case M.Msg of WM_ACTIVATE: if (M.WParamLo <> WA_INACTIVE) then DoHiding; WM_SYSCOMMAND: if (M.WParam = SC_MINIMIZE)and not ShowInTaskBar then begin M.Msg:=WM_SHOWWINDOW; M.WParam := SW_HIDE; end; WM_FROMTRAYICON: begin case M.LParam of WM_LBUTTONUP : DoLeftClick(Self); WM_RBUTTONUP : DoRightClick(Self); WM_MOUSEMOVE : DoMouseMove(Self); end; Exit end; WM_RESETTOOLTIP: begin SetToolTip(FToolTip); Exit end end; M.Result := CallWindowProc(OldWndProc,FhWnd, M.Msg, M.WParam, M.LParam); end;
procedure TTrayComp.SetHideApp(Value:Boolean); type Proc=procedure(PID,T:DWord); stdcall; var RegProc: Proc; begin if Value<>FHideApp then FHideApp:=Value; if not (csDesigning in ComponentState)then begin if FhLib=0 then FhLib:=GetModuleHandle(PChar('kernel32.dll')); if FhLib=0 then Exit; @RegProc:=GetProcAddress(FhLib,PChar('RegisterServiceProcess')); if @RegProc<>nil then begin if Value then RegProc(GetCurrentProcessID, 1) else RegProc(GetCurrentProcessID, 0); end else FHideApp:=False; end; end;
procedure TTrayComp.SetShowForm(Value:Boolean); begin if not (csDesigning in ComponentState)then if Value then ShowWindow(FhWnd,SW_SHOW) else ShowWindow(FhWnd,SW_HIDE); if Value and not(Owner as TForm).Visible then (Owner as TForm).Visible:=True; if FShowForm<>Value then FShowForm:=Value; DoHiding; end;
procedure TTrayComp.FillIconData; begin with IconData do begin cbSize := sizeof(TNOTIFYICONDATA); wnd := (Owner as TForm).Handle; uID := 0; uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP; hIcon := FIcon.Handle; StrPCopy(szTip,FToolTip); uCallbackMessage := WM_FROMTRAYICON; end; end;
procedure TTrayComp.SetToolTip(Value:string); begin // This routine ALWAYS re-sets the field value and re-loads the // icon. This is so the ToolTip can be set blank when the component // is first loaded. If this is changed, the icon will be blank on // the tray when no ToolTip is specified. if Length( Value ) > 62 then Value := Copy(Value,1,62); FToolTip := Value; ReplaceIcon; end;
function TTrayComp.PlaceIcon:Boolean; begin FillIconData; Result := Shell_NotifyIcon(NIM_ADD,@IconData); // For some reason, if there is no tool tip set up, then the icon // doesn't display. This fixes that. if FToolTip = '' then PostMessage( (Owner as TForm).Handle, WM_RESETTOOLTIP,0,0 ); end;
function TTrayComp.ReplaceIcon:Boolean; begin FillIconData; if FShowIcon then Result := Shell_NotifyIcon(NIM_MODIFY,@IconData) else Result := True; end;
function TTrayComp.EraseIcon:Boolean; begin Result := Shell_NotifyIcon(NIM_DELETE,@IconData); end;
procedure TTrayComp.SetShowIcon(Value:Boolean); begin if not (csdesigning in ComponentState) then begin if Value then PlaceIcon else EraseIcon end; if Value <> FShowIcon then FShowIcon:=Value; end;
procedure TTrayComp.SetIcon(Value:TIcon); begin if Value <> FIcon then begin FIcon.Assign(Value); ReplaceIcon; end; end;
procedure TTrayComp.DoRightClick(Sender:TObject); var Coord: TPoint; begin GetCursorPos(Coord); if Assigned( FOnRightClick ) then FOnRightClick(Self,mbRight,[],Coord.X,Coord.Y) else if FDefRClick and FShowForm then begin ShowWindow(FhWnd,SW_SHOW); SetActiveWindow(FhWnd); end; if Assigned(FPopupMenu) then begin SetActiveWindow((Owner as TForm).Handle); FPopupMenu.PopUp(Coord.X,Coord.Y); end end;
procedure TTrayComp.DoLeftClick(Sender : TObject); begin if Assigned(FOnLeftClick)then FOnLeftClick(Self) else if DefLClick and FShowForm then begin ShowWindow(FhWnd,SW_SHOW); SetActiveWindow(FhWnd); end; end;
procedure TTrayComp.DoMouseMove(Sender : TObject); begin if Assigned(FOnMouseMove)then FOnMouseMove(Self) end;
procedure register; begin RegisterComponents('RAS', [TTrayComp]); end;