我需要根据我的
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.
提前致谢。
您必须将颜色转换为 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));
参考资料:
ColorRGBToHLS
+ ColorHLSToRGB
– VCL 源代码Min
+ Max
– Inno Setup 在 Pascal 脚本中获取最小和最大整数值ColorToRGB
– 将 Inno Setup WizardForm.Color 转换为 RGBLightenColor
– 使用 Delphi 以编程方式淡化颜色