Hello!
I'm coming to FPC/Lazarus from the C++/Python world - last time I had to do with Pascal was under DOS/Win3.11 and Win95, using TV2/BP7. As you imagine, it was quite some time ago...
Anyway, I've decided to de-dust my Pascal skills or rather re-learn, and am porting some of the small codebase from C++. It goes quite well but now I came to an issue.
I am prototyping a small interface that drawn completely on TCanvas. To that end, I have a component (TCustomComponent descendant) that's created in 10 copies, displaying 10 different sets of data.
It shows but fails with drawing a frame and a background - if, however, I put a TPicture there and draw it, the picture itself is drawn properly. I understand that I am missing some logic but am also out of ideas as of what am I missing. My approach is based on this bit of documentation:
https://wiki.freepascal.org/Developing_with_Graphics#Create_a_custom_control_which_draws_itself - part titled Create a custom control which draws itself
The code consists of the unit holding the element (TRPreview, trimed out all the unnecessary bits) and bits from main unit, which is supposed to put all that on the form. Please remember that I come from a very different background and the code is just a boilerplate. Having said that though, I'll be happy if anyone points obvious wrong approach to the subject.
unit RPreview;
{$mode ObjFPC}{$H+}
interface
uses
Classes, Sysutils, REngine, Controls, graphics, lcltype;
type
TRPreview = class(TCustomControl)
private
_mprod: Extended;
_rprod: Extended;
_owned: Boolean;
_type: ReactorType;
_props :TReactorProperties;
_img: TPicture;
public
constructor Create(AOwner:TComponent);
procedure Free;
procedure Paint; override;
procedure EraseBackground(DC: HDC); override;
end;
implementation
constructor TRPreview.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
_mprod:=0;
_rprod:=0;
_owned:=false;
_type:=rtNone;
_img:=TPicture.Create;
end;
procedure TRPreview.setType(t:ReactorType);
var
res: String;
begin
if t=rtNone then Exit;
_type:=t;
// cut out out of context code
_img.LoadFromResourceName(HINSTANCE,res,TPortableNetworkGraphic);
end;
procedure TRPreview.Free;
begin
_img.Free;
inherited Free;
end;
procedure TRPreview.Paint;
var
b: TBrush;
p: TPen;
begin
if _type=rtNone then exit;
b:=TBrush.Create; p:=TPen.Create;
//p.Width:=0;
b.Color:=clBlack;
b.Style:=bsSolid;
//Canvas.Pen:=p;
Canvas.Brush:=b;
Canvas.FillRect(Left+4,Top+4,Left+Width-4,Top+Height-4);
//Canvas.Draw(5,5,_img.Bitmap);
//p.Width:=5;
//p.Color:=clGray;
//b.Style:=bsClear; b.Color:=clNone;
//Canvas.Pen:=p;
//Canvas.Brush:=b;
//Canvas.RoundRect(Top,Left,Width,Height,5,5);
b.Free; p.Free;
Inherited Paint;
end;
procedure TRPreview.EraseBackground(DC: HDC);
begin
//Inherited EraseBackground(DC);
end;
end.
And the way it's being processed on the main form:
procedure TForm1.FormCreate(Sender: TObject);
var
t: ReactorType;
dx, dy, cx: Integer;
begin
bkg:=TPicture.Create;
dx:=(Width div 2)-(2*180)-90; dy:=7*25; cx:=1;
bkg.LoadFromResourceName(HInstance,'BACKGROUND',TPortableNetworkGraphic);
brush.Bitmap:=bkg.Bitmap;
Canvas.FloodFill(0,0,clDefault,fsSurface);
Engine:=TEngine.Create;
for t:=rtIsland to rtContinent do begin
if t=rtNone then continue;
boxes[t]:=TRPreview.Create(Self);
boxes[t].Parent:=Self;
boxes[t].Width:=170; boxes[t].Height:=170;
boxes[t].Left:=dx; boxes[t].Top:=dy;
boxes[t].RType:=t;
boxes[t].DoubleBuffered:=true;
cx+=1;
If cx=6 then begin
dx:=(Width div 2)-(2*180)-90;
dy+=180;
end else dx+=180;
end;
end;
"boxes" is an array of TRPreview.
The result I am getting is all the boxes are square, with a gray background. What am I doing wrong?
Also, closing the program (compiled in debug mode, no optimisations) takes about half a second - that's normal?
My OS is Debian 12, all development packages come from a stable repository. Can also test on Windows and macOS if needed.
Many thanks in advance!