2
votes

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.

1
I don't know a thing about Delphi, but I can say this: You are much more likely to get useful responses if you show us the most relevant bits of your code. If it's very similar to something that comes with Delphi and that's known to work, you might find the following strategy useful: start with TGauge itself, gradually modify it to bring it nearer to your code, and see where it breaks. Or state with your code and gradually TGaugeify it and see where it starts working. Or pick a point halfway in between, see whether it works, and keep subdividing.Gareth McCaughan
We really need the code to answer your question. Did you override the paint method?NGLN
To elaborate on NGLN's comment, the declaration should look like procedure Paint; override; You don't necessarily have to call Paint yourself, let Windows call it for you. Instead, call Invalidate; and that will tell Windows to call Paint when it gets a chance.Jerry Dodge
@NGLN yes, paint is overridden. Code added.Raith
@Raith - Put a breakpoint on Progress.Width := trunc(.. line and hover over 'FPercentDone'. If it's '0', it is expected that you don't see the progress bar.Sertac Akyuz

1 Answers

1
votes

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.