FPercentDone
was 0
, was assigning it's value in the wrong place. Adding UpdatePercent
procedure and calling it when a value changes fixes it and everything gets drawn.
Dumb mistake, sorry for wasting your time.
First of all, this is my first attempt at writing a component of any kind. Properties, methods etc. were an easy part, however I have hit a wall with drawing to the canvas. I am sure this is some rookie mistake, but I simply don't see it. I have stared at the TGauge
included with delphi because I am trying something similar but simpler, it is still just a horizontal bar. I am failing at making it draw the progress at run time, that is the weirdest part, for me anyway, that I can see it working at design time but not when I run it... I do get the background coloring right at least, but no progress bar.
Without any code pasting, since it is similar to TGauge
anyway. I have two TBitmap's
, one for background the other for the progress bar itself, I fill one with background color, draw that to the component canvas, if there are borders offset the origin of the second one and decrease its rectangle, paint it with the progress color and draw that to the canvas... It seemed this simple to me, but what am I doing wrong?
Relevant code:
type
TCustomGaugeComp = class(TGraphicControl)
private
FMaxValue, FMinValue, FCurValue: DWord;
FFillBackColor, FFillForeColor: TColor;
FPercentDone: Real;
FBorderStyle: TBorderStyle;
FBorderWidth: Integer;
procedure SetMaxValue(Value: DWord);
procedure SetMinValue(Value: DWord);
procedure SetProgress(Value: DWord);
procedure SetFillBackColor(Value: TColor);
procedure SetFillForeColor(Value: TColor);
procedure SetBorderStyle(Value: TBorderStyle);
function GetPercentDone: String;
procedure SetBorderWidth(Value: integer);
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
published
property Align;
property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle;
property BorderWidth: Integer read FBorderWidth write SetBorderWidth default 1;
property Constraints;
property Enabled;
property Font;
property FillForeColor: TColor read FFillForeColor write SetFillForeColor default clBlack;
property FillBackColor: TColor read FFillBackColor write SetFillBackColor default clWhite;
property MinValue: DWord read FMinValue write SetMinValue default 0;
property MaxValue: DWord read FMaxValue write SetMaxValue default 100;
property Progress: DWord read FCurValue write SetProgress default 0;
property PercentDone: String read GetPercentDone;
property Visible;
end;
procedure TCustomGaugeComp.Paint;
var
Background, Progress: TBitMap;
begin
with Canvas do
begin
Background := TBitMap.Create;
try
Background.Height := Height;
Background.Width := Width;
Background.Canvas.Brush.Color := FFillBackColor;
Background.Canvas.Brush.Style := bsSolid;
Background.Canvas.FillRect(ClientRect);
Progress := TBitMap.Create;
try
Progress.Height := Height;
Progress.Width := Width;
if FBorderStyle = bsSingle then
begin
Progress.Height := Progress.Height - BorderWidth*2;
Progress.Width := Progress.Width - BorderWidth*2;
end;
Progress.Width := trunc(Progress.Width*FPercentDone/100);
Progress.Canvas.Brush.Color := FFillForeColor;
Progress.Canvas.FillRect(Rect(0,0,Progress.Width,Progress.Height));
Background.Canvas.Draw(BorderWidth,BorderWidth,Progress);
finally
Progress.Free;
end;
Draw(0,0,Background);
finally
Background.Free;
end;
end;
end;
RePaint (or Refresh) is called whenever a value changes: min/max/position/borderwidth.
In fact it is not acting perfectly at design time either, progress is drawn, at times, sometimes not drawn at all until I just OPEN the Object Inspector, just go with my mouse there... TGauge
uses CopyMode
excessively, I just started this and I do not really understand CopyMode
values yet or its proper use, so copy-pasting and tweaking the code just will not do.
TGauge
itself, gradually modify it to bring it nearer to your code, and see where it breaks. Or state with your code and graduallyTGauge
ify it and see where it starts working. Or pick a point halfway in between, see whether it works, and keep subdividing. – Gareth McCaughanprocedure Paint; override;
You don't necessarily have to call Paint yourself, let Windows call it for you. Instead, callInvalidate;
and that will tell Windows to call Paint when it gets a chance. – Jerry DodgeProgress.Width := trunc(..
line and hover over 'FPercentDone'. If it's '0', it is expected that you don't see the progress bar. – Sertac Akyuz