如何在 Inno Setup Pascal 脚本中变亮或变暗指定的 TColor?

问题描述 投票:0回答:1

我需要根据我的

TPanel
向导页面中显示的用户当前系统规格自动更改状态栏(它是
wpInfoBefore
)的颜色(变亮或变暗)。

我喜欢有两个函数可以通过输入

TColor
作为值来正确执行此操作。但是,我多次尝试通过阅读像 this 这样的帖子来编写这些函数,甚至使用
RGB
函数,但没有成功。

例如,如果我需要使给定的

TColor
变暗或变亮,我可能需要使用如下所示的函数:

var
   RecommendedStatusColor: TColor;

function LightenColor(Colour: TColor, Percentage: Integer): TColor;
begin 
   ...
end;

function DarkenColor(Colour: TColor, Percentage: Integer): TColor;
begin 
   ...
end;    

RecommendedStatusColor := $00D000;

if ... then
StatusBar.Color := LightenColor(RecommendedStatusColor, 75);
//Lighten given color by 75%

if ... then
StatusBar.Color := DarkenColor(RecommendedStatusColor, 50);
//Darken given color by 50%

输出应经过修改(变亮或变暗)

TColor.

提前致谢。

inno-setup percentage pascalscript tcolor
1个回答
5
投票

您必须将颜色转换为 HSL 或 HSV 并更改亮度 (L) 或值 (V),然后转换回 RGB。

以下代码使用 HSL(L = 亮度)。

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
    begin
      S := ( ((cMax-cMin)*HLSMAX) + ((cMax+cMin)/2) ) / (cMax+cMin);
    end
      else
    begin
      S := ( ((cMax-cMin)*HLSMAX) + ((2*RGBMAX-cMax-cMin)/2) ) /
           (2*RGBMAX-cMax-cMin);
    end;

    // 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 (Double(R) = cMax) then
    begin
      H := Bdelta - Gdelta
    end
    else if (Double(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;

function LightenColor(RGB: Cardinal; Percentage: Integer): Cardinal;
var
  H, S, L: Word; 
begin
  ColorRGBToHLS(RGB, H, L, S); 
  L := (Cardinal(L) * Percentage) div 100;
  Result := ColorHLSToRGB(H, L, S); 
end;

function GetSysColor(nIndex: Integer): DWORD;
  external '[email protected] stdcall';

function ColorToRGB(Color: TColor): Cardinal;
begin
  if Color < 0 then
    Result := GetSysColor(Color and $000000FF) else
    Result := Color;
end;

用途:

LighterColor := TColor(LightenColor(ColorToRGB(Color), 150));
DarkerColor := TColor(LightenColor(ColorToRGB(Color), 75));

Lighter/darker color

参考资料:

© www.soinside.com 2019 - 2024. All rights reserved.