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

时间:2016-09-19 09:28:38

标签: inno-setup percentage pascalscript tcolor

我需要根据用户当前的系统规格自动更改状态栏的颜色(TPanel)更改(变亮或变暗),{{1向导页面。

我希望有两个函数可以通过输入wpInfoBefore作为值来正确执行此操作。但是,我多次尝试通过阅读this等帖子来编写这些函数,甚至使用TColor函数,但没有成功。

例如,如果我需要使给定的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%

先谢谢。

1 个答案:

答案 0 :(得分:2)

您必须将颜色转换为HSL or 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
      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 (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
        Magic2 := (Luminance * (HLSMAX + Saturation) + (HLSMAX/2)) / HLSMAX
     else
        Magic2 := Luminance + Saturation - ((Luminance * Saturation) + (HLSMAX/2)) / HLSMAX;
     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 'GetSysColor@User32.dll 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

参考文献: