Link to home
Start Free TrialLog in
Avatar of Software Software
Software SoftwareFlag for Austria

asked on

IMPORTANT: Canvas: Drawing is not drawn correctly

Hello,
I have the following problem:

If I want to draw a rectangle on the paintbox in the lower right corner, then the rectangle will not be displayed completely after scrolling. What do I have to change to make the rectangle completely visible after scrolling down?

Here is a video of the problem (20s):
https://youtu.be/EETK1P1oG8g

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    ScrollBox1: TScrollBox;
    PaintBox1: TPaintBox;
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  protected
    procedure Paint; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Paint;
begin
  inherited;
    //paintbox1.Canvas.Rectangle(5,5,300,200);
end;

procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  paintbox1.Canvas.Rectangle(X,Y,X+200,Y+300);
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  paint;
end;

end. 

Open in new window


Thank you
Unit1.dfm
Unit1.pas
Avatar of ste5an
ste5an
Flag of Germany image

Well, you're somehow on the correct track. The entire thing is also called owner drawing. The paint box is just your canvas. One thing to know, components only draw on the visible area (should be obvious). But as they or in this case the paint box doesn't know, what objects are used, you need to redraw your objects when necessary, Here you really need to make yourself familiar how owner drawing works.

As I said you're on the right track. The Paint method of components is invoked, when they possibly need to be redrawn. E.g. something like this:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    ScrollBox1: TScrollBox;
    PaintBox1: TPaintBox;
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  private
    FLeft, FTop: Integer;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  FLeft := Y;
  FTop := X;
  PaintBox1.Invalidate;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  PaintBox1.Canvas.Rectangle(FTop, FLeft, FTop + 200, FLeft + 300);
end;

end.

Open in new window

Avatar of Software Software

ASKER

I also noticed something when I scroll down to the bottom and the rectangle in the
place lower corner. Then the scrollbar does not get bigger so you can see the whole rectangle.
How can I change this?

Video (15s):
https://youtu.be/7ThQNJtNZK4

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    ScrollBox1: TScrollBox;
    Image1: TImage;
    procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormActivate(Sender: TObject);
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  x1,x2,y1,y2:Integer;
implementation

{$R *.dfm}

procedure TForm1.FormActivate(Sender: TObject);
  var i:Integer;
begin
 for i := 0 to 30 do
   begin
    image1.Canvas.MoveTo(30*i, 0);
    image1.Canvas.LineTo(30*+i, image1.Height);
   end;
end;

procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  image1.canvas.Pen.Color:=clwhite;
  image1.Canvas.Rectangle(x1,y1,x2,y2);
end;

procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  image1.canvas.Pen.Color:=clblack;
  x1:=X;
  x2:=X+100;
  y1:=Y;
  y2:=Y+100;
  image1.canvas.Pen.Color:=clblack;
  image1.Canvas.Rectangle(x1,y1,x2,y2);
end;

end.

Open in new window

You draw on image canvas with constant size (width, height) - so there is no TImage resize - and that is reason why scroll box did not show "correct" scroll bar position (when is on auto).

Seem that you are novice to Delphi and you don't understand graphics on Delphi.
You need to create internal bitmap and draw on it. After that - assign it to Timage.
To avoid this step - use TPaintBox. If your object needs more space to draw as a whole - need to expand Canvas (TBitmap/TPaintBox) first.....
This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.