【问题标题】:How to Lighten or Darken a specified TColor in Inno Setup Pascal Script?如何在 Inno Setup Pascal 脚本中使指定的 TColor 变亮或变暗?
【发布时间】:2016-09-19 09:28:37
【问题描述】:

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

我喜欢有两个函数可以通过输入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】:

    您必须将颜色转换为 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
         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 '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));
    

    参考资料:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 2017-02-12
      • 1970-01-01
      • 2013-01-22
      • 1970-01-01
      相关资源
      最近更新 更多