unit Util; interface uses Vcl.Controls, // Free control children System.Types, Vcl.Graphics; // Color lightener type TUtil = class class procedure VervangControl(OudeControl: TControl; NieuweControl: TControl); class procedure FreeControlChildrenRec(AControl: TControl); class function LightenColor(RGB: Cardinal; Percentage: Integer): Cardinal; static; end; implementation // VERVANG CONTROL class procedure TUtil.VervangControl(OudeControl: TControl; NieuweControl: TControl); begin // Positie NieuweControl.Left := OudeControl.Left; NieuweControl.Top := OudeControl.Top; NieuweControl.Anchors := OudeControl.Anchors; // Dimensies NieuweControl.Width := OudeControl.Width; NieuweControl.Height := OudeControl.Height; // Properties NieuweControl.parent := OudeControl.parent; NieuweControl.Enabled := OudeControl.Enabled; NieuweControl.visible := OudeControl.visible; // Oude control verbergen OudeControl.visible := False; end; // FREE CONTROL CHILDREN // Recursieve methode om de kinderen van een TWinControl te free-en (hanging pointers voorkomen) // Gebaseerd op: https://stackoverflow.com/questions/414928/is-there-any-way-to-get-all-the-controls-on-a-container-control class procedure TUtil.FreeControlChildrenRec(AControl: TControl); var i: Integer; begin if AControl = nil then exit; if AControl is TWinControl then begin i := 0; // Tijden het free-en kan zijn dat er elementen verdwijnen uit de lijst. // Het aantal elementen moet dus steeds opnieuw gecontroleerd worden (een for-lus berekent dit eenmalig) while TWinControl(AControl).ControlCount < i do begin FreeControlChildrenRec(TWinControl(AControl).Controls[i]); end; end; AControl.Free(); end; // COLOR LIGHTENER // https://stackoverflow.com/questions/39569710/how-to-lighten-or-darken-a-specified-tcolor-in-inno-setup-pascal-script function GetRValue(RGB: Cardinal): Byte; begin Result := Byte(RGB); end; function GetGValue(RGB: Cardinal): Byte; begin Result := Byte(RGB shr 8); end; function GetBValue(RGB: Cardinal): Byte; begin Result := Byte(RGB shr 16); end; function Max(A, B: Integer): Integer; begin if A > B then Result := A else Result := B; end; function Min(A, B: Integer): Integer; begin if A < B then Result := A else Result := B; end; const HLSMAX = 240; RGBMAX = 255; HLSUndefined = (HLSMAX * 2 / 3); procedure ColorRGBToHLS(RGB: Cardinal; var Hue, Luminance, Saturation: Word); var H, L, S: Double; R, G, B: Word; cMax, cMin: Double; Rdelta, Gdelta, Bdelta: Word; { intermediate value: % of spread from max } begin R := GetRValue(RGB); G := GetGValue(RGB); B := GetBValue(RGB); { calculate lightness } cMax := Max(Max(R, G), B); cMin := Min(Min(R, G), B); L := (((cMax + cMin) * HLSMAX) + RGBMAX) / (2 * RGBMAX); Luminance := Trunc(L); if cMax = cMin then { r=g=b --> achromatic case } begin Hue := Trunc(HLSUndefined); Saturation := 0; end else { chromatic case } begin { saturation } if Luminance <= HLSMAX / 2 then S := (((cMax - cMin) * HLSMAX) + ((cMax + cMin) / 2)) / (cMax + cMin) else S := (((cMax - cMin) * HLSMAX) + ((2 * RGBMAX - cMax - cMin) / 2)) / (2 * RGBMAX - cMax - cMin); { hue } Rdelta := Trunc((((cMax - R) * (HLSMAX / 6)) + ((cMax - cMin) / 2)) / (cMax - cMin)); Gdelta := Trunc((((cMax - G) * (HLSMAX / 6)) + ((cMax - cMin) / 2)) / (cMax - cMin)); Bdelta := Trunc((((cMax - B) * (HLSMAX / 6)) + ((cMax - cMin) / 2)) / (cMax - cMin)); if (R = cMax) then begin H := Bdelta - Gdelta end else if (G = cMax) then begin H := (HLSMAX / 3) + Rdelta - Bdelta end else // B == cMax begin H := ((2 * HLSMAX) / 3) + Gdelta - Rdelta; end; if (H < 0) then H := H + HLSMAX; if (H > HLSMAX) then H := H - HLSMAX; Hue := Round(H); Saturation := Trunc(S); end; end; function HueToRGB(Lum, Sat, Hue: Double): Integer; var ResultEx: Double; begin { range check: note values passed add/subtract thirds of range } if (Hue < 0) then Hue := Hue + HLSMAX; if (Hue > HLSMAX) then Hue := Hue - HLSMAX; { return r,g, or b value from this tridrant } if (Hue < (HLSMAX / 6)) then ResultEx := Lum + (((Sat - Lum) * Hue + (HLSMAX / 12)) / (HLSMAX / 6)) else if (Hue < (HLSMAX / 2)) then ResultEx := Sat else if (Hue < ((HLSMAX * 2) / 3)) then ResultEx := Lum + (((Sat - Lum) * (((HLSMAX * 2) / 3) - Hue) + (HLSMAX / 12)) / (HLSMAX / 6)) else ResultEx := Lum; Result := Round(ResultEx); end; function RoundColor(Value: Double): Integer; begin if Value > 255 then Result := 255 else Result := Round(Value); end; function RGB(R, G, B: Byte): Cardinal; begin Result := (Cardinal(R) or (Cardinal(G) shl 8) or (Cardinal(B) shl 16)); end; function ColorHLSToRGB(Hue, Luminance, Saturation: Word): Cardinal; var R, G, B: Double; { RGB component values } Magic1, Magic2: Double; { calculated magic numbers (really!) } begin if (Saturation = 0) then begin { achromatic case } R := (Luminance * RGBMAX) / HLSMAX; G := R; B := R; if (Hue <> HLSUndefined) then; { ERROR } end else begin { chromatic case } { set up magic numbers } if (Luminance <= (HLSMAX / 2)) then begin Magic2 := (Luminance * (HLSMAX + Saturation) + (HLSMAX / 2)) / HLSMAX; end else begin Magic2 := Luminance + Saturation - ((Luminance * Saturation) + (HLSMAX / 2)) / HLSMAX; end; Magic1 := 2 * Luminance - Magic2; { get RGB, change units from HLSMAX to RGBMAX } R := (HueToRGB(Magic1, Magic2, Hue + (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX; G := (HueToRGB(Magic1, Magic2, Hue) * RGBMAX + (HLSMAX / 2)) / HLSMAX; B := (HueToRGB(Magic1, Magic2, Hue - (HLSMAX / 3)) * RGBMAX + (HLSMAX / 2)) / HLSMAX; end; Result := RGB(RoundColor(R), RoundColor(G), RoundColor(B)); end; class function TUtil.LightenColor(RGB: Cardinal; Percentage: Integer): Cardinal; var H, S, L: Word; begin ColorRGBToHLS(RGB, H, L, S); L := (Integer(L) * Percentage) div 100; Result := ColorHLSToRGB(H, L, S); end; // ----- COLOR LIGHTENER end.