簡體   English   中英

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

[英]How to Lighten or Darken a specified TColor in Inno Setup Pascal Script?

我需要根據我的wpInfoBefore向導頁面中顯示的用戶當前系統規范自動更改狀態欄的顏色(它是TPanel )(變亮或變暗)。

我喜歡有兩個函數可以通過輸入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%

輸出應該是修改后的(變亮或變暗) TColor.

提前致謝。

您必須將顏色轉換為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 '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));

較淺/較深的顏色

參考:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM