procedure TForm1.PanelVolume(const APanel: TPanel; const AMin, AMax, ACurrent, ABorderSpace: Integer; const AStartColor, AEndColor: TColor; const ASolidColor, ADrawHorizontal, AShowText: Boolean);
var
BufferBitmap: TBitmap;
VolumeRect: TRect;
ClearRect: TRect;
VolumeColor: TColor;
Progress: Double;
PercText: string;
begin
// sanity checks
if ((AMin < 0) or (AMax <= AMin) or (ACurrent > AMax)) then
Exit;
BufferBitmap := TBitmap.Create;
try
BufferBitmap.Width := APanel.Width;
BufferBitmap.Height := APanel.Height;
// begin creating the rectangle for drawing
VolumeRect := BufferBitmap.Canvas.ClipRect;
// respect a maybe needed border
if (ABorderSpace > 0) then
InflateRect(VolumeRect, (ABorderSpace - (2 * ABorderSpace)), (ABorderSpace - (2 * ABorderSpace)));
// begin creating the rectangle for clearing
ClearRect := VolumeRect;
// calculate the current progress
Progress := (ACurrent - AMin) / (AMax - AMin);
if ADrawHorizontal then
begin
// apply the current progress to the rectangle
VolumeRect.Right := VolumeRect.Left + Round(Progress * VolumeRect.Width);
// subtract the clearing space
ClearRect.Left := VolumeRect.Right;
end
else
begin
// apply the current progress to the rectangle
VolumeRect.Top := VolumeRect.Bottom - Round(VolumeRect.Height * Progress);
// subtract the clearing space
ClearRect.Bottom := VolumeRect.Top;
end;
// calculate the current needed color for the current progress
if (AStartColor <> AEndColor) then
VolumeColor := RGBToColor(
Round((1 - Progress) * GetRValue(AStartColor) + Progress * GetRValue(AEndColor)),
Round((1 - Progress) * GetGValue(AStartColor) + Progress * GetGValue(AEndColor)),
Round((1 - Progress) * GetBValue(AStartColor) + Progress * GetBValue(AEndColor)))
else
VolumeColor := AStartColor;
// freeze the canvas
BufferBitmap.Canvas.Lock;
if (ABorderSpace > 0) then
begin
// draw a border
BufferBitmap.Canvas.Pen.Style := psSolid;
BufferBitmap.Canvas.Pen.Color := clBlack;
BufferBitmap.Canvas.Rectangle(BufferBitmap.Canvas.ClipRect);
end;
// reset the unused space color
BufferBitmap.Canvas.Brush.Style := bsSolid;
BufferBitmap.Canvas.Brush.Color := APanel.Color;
BufferBitmap.Canvas.FillRect(ClearRect);
// paint the progress
if (not ASolidColor) then
begin
if ADrawHorizontal then
BufferBitmap.Canvas.GradientFill(VolumeRect, AStartColor, VolumeColor, gdHorizontal)
else
BufferBitmap.Canvas.GradientFill(VolumeRect, VolumeColor, AStartColor, gdVertical);
end
else
begin
BufferBitmap.Canvas.Brush.Color := VolumeColor;
BufferBitmap.Canvas.FillRect(VolumeRect);
end;
// apply percentage display
if AShowText then
begin
BufferBitmap.Canvas.Font := APanel.Font;
BufferBitmap.Canvas.Brush.Style := bsClear;
PercText := Format('%d%%', [Round(Progress * 100)]);
BufferBitmap.Canvas.TextOut(
((APanel.ClientWidth - BufferBitmap.Canvas.TextWidth(PercText)) div 2),
((APanel.ClientHeight - BufferBitmap.Canvas.TextHeight(PercText)) div 2),
PercText);
end;
// unfreeze the canvas
BufferBitmap.Canvas.Unlock;
// update the screen
APanel.Canvas.Draw(0, 0, BufferBitmap);
finally
BufferBitmap.Free;
end;
end;