Forum > LCL

Painting on a control - 3 questions: OnPaint, ImageList, program logic

(1/10) > >>

majolika:
Hello!
I have three newbies question about painting on a control.
For the educational purposes I'm programming a mine sweeper game.

1st question: OnPaint
When I click on a start buttion I show a mine field and fill it with squares. Then I click on the mine field and show a mine. But the mine field fully repaint and my squares is gone. Why?

2nd question: ImageList
ImageList is very usefull control but I found one strange thing: when I'm drawing an same image with ImageList and with Canvas.Draw it gives me different results. Why?


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---ImageList1.Resolution[24].Draw(Bevel1.Canvas,  x, y, 0, True);
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---MineField.Canvas.Draw(x, y, Picture_Loaded_From_TImage_Placed_On_The_Form);
I attached screenshot to show the difference: left, brighter mine field — ImageList, right, darker — Canvas.Draw

3rd question: program logic
First click on the start button works well but the second doesn't work at all. Why?

Here's the minimal proof-of-concept code:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit test_unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls; type   TForm1 = class(TForm)    Bevel1: TBevel;    Button1: TButton;    ImageList1: TImageList;    procedure Bevel1MouseUp(Sender: TObject; Button: TMouseButton;      Shift: TShiftState; X, Y: Integer);    procedure Bevel1Paint(Sender: TObject);    procedure Button1Click(Sender: TObject);  private   public   end; var  Form1: TForm1;  BoxSize: Integer = 24;  FieldRow: integer = 10;  FieldCol: integer = 10;  Button1Clicked: Boolean = False;  DrawABomb: Boolean = False;  CoordX, CoordY: Integer; implementation {$R *.lfm} procedure TForm1.Button1Click(Sender: TObject);begin  Button1Clicked := True;  Bevel1.Width := FieldCol * BoxSize;  Bevel1.Height := FieldRow * BoxSize;  Bevel1.Show;end; procedure TForm1.Bevel1Paint(Sender: TObject);var  x, y: Integer;begin  if Button1Clicked then begin     for x := 0 to FieldCol - 1 do begin         for y := 0 to FieldRow - 1 do begin             ImageList1.Resolution[24].Draw(Bevel1.Canvas,             (x * BoxSize), (y * BoxSize), 0, True);         end;     end;     Button1Clicked := False;  end;  if DrawABomb then begin     ImageList1.Resolution[24].Draw(Bevel1.Canvas, CoordX, CoordY, 1, True);     DrawABomb := False;  end;end; procedure TForm1.Bevel1MouseUp(Sender: TObject; Button: TMouseButton;          Shift: TShiftState; X, Y: Integer);begin  if Button = mbLeft then begin     DrawABomb := True;     CoordX := X; CoordY := Y;     Bevel1.Repaint;  end;end; end. 

ASerge:

--- Quote from: majolika on January 22, 2025, 04:55:52 pm ---1st question: OnPaint
When I click on a start buttion I show a mine field and fill it with squares. Then I click on the mine field and show a mine. But the mine field fully repaint and my squares is gone. Why?

--- End quote ---
It is better to use TPaintBox.
In the OnPaint handler, assume that all the content is corrupted and incorrect. Based on this, build the logic of rendering.

majolika:

--- Quote from: ASerge on January 22, 2025, 05:36:36 pm ---It is better to use TPaintBox.

--- End quote ---
Thanks! I'll try and be back later to say if it works for me.

majolika:

--- Quote from: ASerge on January 22, 2025, 05:36:36 pm ---It is better to use TPaintBox.

--- End quote ---
No, if I simply replace TBevel with TPaintBox it's not working. Attached pics demonstrates three steps with TBevel (show mine) and PaintBox (show no mine).


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit test2_unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls; type   TForm1 = class(TForm)    Button1: TButton;    ImageList1: TImageList;    PaintBox1: TPaintBox;    procedure Button1Click(Sender: TObject);    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;              Shift: TShiftState; X, Y: Integer);    procedure PaintBox1Paint(Sender: TObject);  private   public   end; var  Form1: TForm1;  BoxSize: Integer = 24;  FieldRow: integer = 10;  FieldCol: integer = 10;  Button1Clicked: Boolean = False;  DrawABomb: Boolean = False;  FieldWidth, FieldHeight: Integer; implementation {$R *.lfm} procedure TForm1.Button1Click(Sender: TObject);begin  Button1Clicked := True;  PaintBox1.Width := FieldCol * BoxSize;  PaintBox1.Height := FieldRow * BoxSize;end; procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;          Shift: TShiftState; X, Y: Integer);begin  if Button = mbLeft then begin     DrawABomb := True;     PaintBox1.Repaint;  end;end; procedure TForm1.PaintBox1Paint(Sender: TObject);var x, y: integer;begin  if Button1Clicked then begin     for x := 0 to FieldCol - 1 do begin         for y := 0 to FieldRow - 1 do begin             ImageList1.Resolution[24].Draw(PaintBox1.Canvas,             (x * BoxSize), (y * BoxSize), 0, True);         end;     end;     Button1Clicked := False;  end;  if DrawABomb then begin     ImageList1.Resolution[24].Draw(PaintBox1.Canvas, x, y, 1, True);     DrawABomb := False;  end;end; end. 

--- Quote from: ASerge on January 22, 2025, 05:36:36 pm ---In the OnPaint handler, assume that all the content is corrupted and incorrect. Based on this, build the logic of rendering.

--- End quote ---
I found a simplistic clone of MS Paint on Github. It seems that author creates a bitmap in memory, in OnMouseUp/Down/Move draws something on top of this bitmap and then in OnPaint just put the whole bitmap on the PaintBox. But it's kinda wierd solution. Why are the things so complicated?!

ASerge:

--- Quote from: majolika on January 22, 2025, 07:23:14 pm ---It seems that author creates a bitmap in memory, in OnMouseUp/Down/Move draws something on top of this bitmap and then in OnPaint just put the whole bitmap on the PaintBox. But it's kinda wierd solution. Why are the things so complicated?!

--- End quote ---
It just caches a lot of drawings on a separate bitmap. To speed up. But the principle remains the same - redraw each time.

Navigation

[0] Message Index

[#] Next page

Go to full version