2009. június 1., hétfő
How to create a vertical progress bar and fill it from top to bottom
Problem/Question/Abstract:
Is it possible for the position parameter to fill a vertically orientated ProgressBar going down (rather than starting from its bottom and going up)? I want to indicate negative values. Ideal would be Min = -negative value and Max = +positive value with zero position in center and the fill would start from zero center and go either up or down depending on value.
Answer:
Here's one with that capability:
unit W95meter;
{This component is a Windows 95 style progress meter. It is free and donated to
the public domain. I do claim copyright of this code and I hereby prohibit the sale of the source or compiled code to anyone for any amount.
Modified 11/29/00 by Eddie Shipman
1. Added Direction Property to allow reverse fills.
Modified 10/15/97 by Eddie Shipman
1. Added a Max Value so Values over 100 can be used
2. Fixed the Invalidation of the control after properties are changed.
Modified 12/22/95 by John Newlin
1. Caught by Larry E. Tanner 70242,27. Decreasing the Value of the Percent property
would fail to clear the higher segments. Fixed.
2. Setting the EdgeStyle propety to St95None would not eliminate painting the edge outline. Fixed.
by John Newlin CIS 71535,665}
interface
uses
WinTypes, WinProcs, Messages, SysUtils, Classes, Controls, Forms, Menus, Graphics, Dialogs;
type
StyleType = (st95None, st95Lowered, st95Raised);
TDirection = (dirForward, dirReverse);
TW95Meter = class(TGraphicControl)
private
FAlign: TAlign;
FPercent: Integer;
FBackColor: TColor;
FSegColor: TColor;
FSegWidth: Integer;
FSegGap: Integer;
FMax: Integer;
FEdgeStyle: StyleType;
FDirection: TDirection;
procedure Initialize;
procedure SetPercent(Value: Integer);
procedure SetAlign(Value: TAlign);
procedure SetBackColor(Value: TColor);
procedure SetDirection(Value: TDirection);
procedure SetSegColor(Value: TColor);
procedure SetSegWidth(Value: Integer);
procedure SetSegGap(Value: Integer);
procedure SetMax(Value: Integer);
procedure SetStyle(Value: StyleType);
protected
procedure UpdateProgress;
procedure Paint; override;
procedure AdjustSize; dynamic;
procedure RequestAlign; dynamic;
public
constructor Create(AOwner: TComponent); override;
property Canvas;
function IntPercent(High, Low: Longint): Integer;
function RealPercent(High, Low: real): Integer;
published
property OnClick;
property OnDblClick;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property Cursor;
property Align: TAlign read FAlign write SetAlign default alNone;
property Direction: TDirection read FDirection write SetDirection default dirForward;
property EdgeStyle: StyleType read FEdgeStyle write SetStyle default st95Lowered;
property SegmentGap: Integer read FSegGap write SetSegGap default 2;
property SegmentWidth: Integer read FSegWidth write SetSegWidth default 8;
property SegmentColor: TColor read FSegColor write SetSegColor default clActiveCaption;
property BackGroundColor: TColor read FBackColor write SetBackColor default clBtnFace;
property Percent: Integer read FPercent write SetPercent default 0;
property Max: Integer read FMax write SetMax default 100;
property Width default 100;
property Height default 18;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Win32', [TW95Meter]);
end;
procedure TW95Meter.SetSegWidth(Value: Integer);
begin
if (Value > 0) and (Value <> FSegWidth) then
begin
FSegWidth := Value;
Invalidate;
end;
end;
procedure TW95Meter.SetMax(Value: Integer);
begin
if Value <> FMax then
begin
FMax := Value;
Invalidate;
end;
end;
procedure TW95Meter.SetSegGap(Value: Integer);
begin
if (Value > 0) and (Value <> FSegGap) then
begin
FSegGap := Value;
Invalidate;
end;
end;
procedure TW95Meter.SetBackColor(Value: TColor);
begin
if FBackColor <> Value then
begin
FBackColor := Value;
Invalidate;
end;
end;
procedure TW95Meter.SetSegColor(Value: TColor);
begin
if FSegColor <> Value then
begin
FSegColor := Value;
Invalidate;
end;
end;
procedure TW95Meter.SetPercent(Value: Integer);
var
bRefresh: boolean;
begin
if Value <> FPercent then
begin
if FPercent > Value then
bRefresh := true
else
bRefresh := false;
FPercent := Value;
if (Fpercent = 0) or (bRefresh = true) or (csDesigning in ComponentState) then
Invalidate;
UpdateProgress;
end;
end;
procedure TW95Meter.SetStyle(Value: StyleType);
begin
if Value <> FEdgeStyle then
begin
FEdgeStyle := Value;
Invalidate;
end;
end;
procedure TW95Meter.Initialize;
begin
Width := 100;
Height := 18;
FPercent := 0;
FBackColor := clBtnFace;
FSegColor := clActiveCaption;
FSegWidth := 8;
FSegGap := 2;
FEdgeStyle := st95Lowered;
FMax := 100;
FDirection := dirForward;
end;
constructor TW95Meter.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Initialize;
end;
procedure TW95Meter.UpdateProgress;
var
x1, y1, x2, y2, max: Integer;
bg: TColor;
procedure DoHorizontalF;
var
i: Integer;
begin
x1 := 4;
x2 := x1 + FSegWidth;
y1 := 4;
y2 := Height - 4;
max := Width div (FSegWidth + FSegGap);
Max := round(max * (FPerCent / FMax));
for i := 1 to Max do
begin
with canvas do
begin
if x2 <= width - 4 then
Rectangle(x1, y1, x2, y2);
x1 := x1 + FSegWidth + FSegGap;
x2 := x1 + FSegWidth;
end;
end;
end;
procedure DoVerticalF;
var
i, h: Integer;
begin
h := height;
x1 := 4;
x2 := Width - 4;
y1 := Height - (FSegWidth + 4);
y2 := Height - 4;
max := Height div (FSegWidth + FSegGap);
max := round(max * (FPercent / FMax));
for i := 1 to max do
begin
with canvas do
begin
if y1 >= 4 then
Rectangle(x1, y1, x2, y2);
y1 := y1 - (FSegWidth + FSegGap);
y2 := y1 + FsegWidth;
end;
end;
end;
procedure DoHorizontalR;
var
i: Integer;
begin
x1 := Width - 4;
x2 := x1 - FSegWidth;
y1 := 4;
y2 := Height - 4;
max := Width div (FSegWidth + FSegGap);
Max := round(max * (FPerCent / FMax));
for i := 1 to Max do
begin
with canvas do
begin
if x2 <= width - 4 then
Rectangle(x1, y1, x2, y2);
x1 := x1 - FSegWidth - FSegGap;
x2 := x1 - FSegWidth;
end;
end;
end;
procedure DoVerticalR;
var
i: Integer;
begin
x1 := 4;
x2 := Width - 4;
y1 := 4;
y2 := 4 + FSegWidth;
max := Height div (FSegWidth + FSegGap);
max := round(max * (FPercent / FMax));
for i := 1 to max do
begin
with canvas do
begin
if y1 >= 4 then
Rectangle(x1, y1, x2, y2);
y1 := y1 + (FSegWidth + FSegGap);
y2 := y1 + FSegWidth;
end;
end;
end;
begin
canvas.pen.color := FSegColor;
canvas.brush.color := FsegColor;
case FDirection of
dirForward:
begin
if Width > Height then
DoHorizontalF
else
DoVerticalF;
end;
dirReverse:
begin
if Width > Height then
DoHorizontalR
else
DoVerticalR;
end;
end;
end;
procedure TW95Meter.Paint;
begin
with Canvas do
begin
Brush.Color := FBackColor;
if FEdgeStyle = st95none then
begin
Pen.Width := 0;
Pen.Color := FBackColor;
Rectangle(0, 0, width, height);
if FPercent > 0 then
UpdateProgress;
exit;
end;
pen.Width := 2;
if FEdgeStyle = st95Lowered then
pen.color := clgray
else
pen.color := clWhite;
moveto(0, height);
lineto(0, 0);
lineto(width - 1, 0);
if FEdgeStyle = st95Lowered then
pen.color := clWhite
else
pen.color := clGray;
lineto(width - 1, height - 1);
lineto(0, height - 1);
Pen.Width := 0;
Brush.Color := FBackColor;
Pen.Color := FBackColor;
Rectangle(1, 1, Width - 1, Height - 1);
if FPercent > 0 then
UpdateProgress;
end;
end;
function TW95Meter.RealPercent(High, Low: Real): Integer;
begin
result := 0;
if High = 0.0 then
exit;
Result := Round((Low / High) * FMax);
end;
function TW95Meter.IntPercent(High, Low: Longint): Integer;
begin
result := 0;
if High = 0 then
exit;
Result := Round((low / high) * FMax);
end;
procedure TW95Meter.SetAlign(Value: TAlign);
var
OldAlign: TAlign;
begin
if FAlign <> Value then
begin
OldAlign := FAlign;
FAlign := Value;
if not (csLoading in ComponentState) and (not (csDesigning in ComponentState) or
(Parent <> nil)) then
if ((OldAlign in [alTop, alBottom]) = (Value in [alRight, alLeft])) and
not (OldAlign in [alNone, alClient]) and not (Value in [alNone, alClient]) then
SetBounds(Left, Top, Height, Width)
else
AdjustSize;
end;
end;
procedure TW95Meter.AdjustSize;
begin
if not (csLoading in ComponentState) then
SetBounds(Left, Top, Width, Height);
end;
procedure TW95Meter.RequestAlign;
begin
{ if Parent <> nil then Parent.AlignControl(Self); }
end;
procedure TW95Meter.SetDirection(Value: TDirection);
begin
if Value <> FDirection then
begin
FDirection := Value;
Invalidate;
end;
end;
end.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése