我需要根据用户当前的系统规格自动更改状态栏的颜色(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%
先谢谢。
答案 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));
参考文献:
ColorRGBToHLS
+ ColorHLSToRGB
- VCL源代码; Min
+ Max
- Inno Setup get Min and Max Integer values in Pascal Script; ColorToRGB
- Converting Inno Setup WizardForm.Color to RGB; LightenColor
- Lighten colors programmatically with Delphi