FMXTCanvasSaveCanvas (Delphi)

From RAD Studio Code Examples
Jump to: navigation, search

Description

This example shows how to use the SaveCanvas and RestoreCanvas functions and their results. It also shows how to dynamically customize the drawing stroke and fill properties of the TCanvas.

To build and test this example, create a Multi-Device Application - Delphi and add the following controls on the form:

The set of TColorComboBox, TNumberBox, and TComboBox objects displays the current state of the drawing and filling TCanvas properties. When the selected values change, the TCanvas properties are updated.

This example does the following:

  • Draws an ellipse, a rectangle, or displays a text with the current draw and fill properties.
  • Saves the state of the canvas at a moment and restores it after.

The drawing is made on the canvas of the bitmap. The bitmap is displayed on the TImage.

In the next sample image, the ellipse was drawn with the state displayed in the memo, and the rectangle was drawn with the state displayed by the set of combo boxes.

SaveCanvas.png

Code

Add as global variables two pointers, SaveState and InitialState, to keep the initial state of the canvas and the state saved when the SaveState button is clicked.

var
  Form1: TForm1;
  SaveState, InitialState: TCanvasSaveState;

Add a new procedure to the form class, named UpdateStateComboBox, to update the set of combo boxes. This method is called when the form is created, the canvas is cleared, or a state is restored, so the combo boxes set show the current draw and fill properties.

procedure TForm1.UpdateStateComboBox;
begin
  // updates the Combo boxes with the current state of the canvas
  StrokeColorComboBox.Color := MainImage.Bitmap.Canvas.Stroke.Color;
  ThicknessNumberBox1.Value := MainImage.Bitmap.Canvas.StrokeThickness;
  StrokeCapComboBox.ItemIndex := StrokeCapComboBox.ListBox.Items.IndexOf
    (GetEnumName(TypeInfo(TStrokeCap),
    integer(MainImage.Bitmap.Canvas.StrokeCap)));
  StrokeDashComboBox.ItemIndex := StrokeDashComboBox.ListBox.Items.IndexOf
    (GetEnumName(TypeInfo(TStrokeDash),
    integer(MainImage.Bitmap.Canvas.StrokeDash)));
  StrokeJoinComboBox.ItemIndex := StrokeJoinComboBox.ListBox.Items.IndexOf
    (GetEnumName(TypeInfo(TStrokeJoin),
    integer(MainImage.Bitmap.Canvas.StrokeJoin)));
  FillColorColorComboBox.Color := MainImage.Bitmap.Canvas.Fill.Color;
  TextSizeNumberBox.Value := MainImage.Bitmap.Canvas.Font.Size;
end;

Add the following code to the OnCreate event handler of the form.

procedure TForm1.FormCreate(Sender: TObject);
begin
  // initializes the initial bitmap
  MainImage.Bitmap := TBitmap.Create(Round(MainImage.Width), Round(MainImage.Height));
  // updates the combo boxes values
  UpdateStateComboBox;
  // saves the initial state of the canvas to be customized
  InitialState := MainImage.Bitmap.Canvas.SaveState;
end;

Add the following lines of code to the OnClick event handlers of SaveCanvas and RestoreCanvas buttons:

procedure TForm1.SaveButtonClick(Sender: TObject);
begin
  StateMemo.Lines.Clear;
  // saves the current state and display the current properties on the StateMemo
  SaveState := MainImage.Bitmap.Canvas.SaveState;
  RestoreButton.Enabled := true;
  // displays the saved properties on the StateMemo
  StateMemo.Lines.Add('Stroke Color: ' +
    StrokeColorComboBox.ListBox.Selected.Text);
  StateMemo.Lines.Add('StrokeThickness: ' + ThicknessNumberBox1.Text);
  StateMemo.Lines.Add('StrokeCap: ' + StrokeCapComboBox.ListBox.Selected.Text);
  StateMemo.Lines.Add('StrokeDash: ' +
    StrokeDashComboBox.ListBox.Selected.Text);
  StateMemo.Lines.Add('StrokeJoin: ' +
    StrokeJoinComboBox.ListBox.Selected.Text);
  StateMemo.Lines.Add('Text Size: ' + TextSizeNumberBox.Text);
  StateMemo.Lines.Add('Fill Color: ' + FillColorColorComboBox.ListBox.
    Selected.Text);
end;

procedure TForm1.RestoreButtonClick(Sender: TObject);
begin
  // restores the saved properties
  MainImage.Bitmap.Canvas.RestoreState(SaveState);
  RestoreButton.Enabled := false;
  //updates the combo boxes
  UpdateStateComboBox;
  // clears the memo
  StateMemo.Lines.Clear;
end;

To get the necessary function to transform a string into an enumeration value and an enumeration value into a string, include the System.TypInfo unit. Add the following lines of code to the OnExit event handlers of the TColorComboBox, TNumberBox, and TComboBox objects, respectively:

procedure TForm1.StrokeColorComboBoxExit(Sender: TObject);
begin
//sets the stroke color
  MainImage.Bitmap.Canvas.Stroke.Color := StrokeColorComboBox.Color;
end;

procedure TForm1.ThicknessNumberBox1Exit(Sender: TObject);
begin
//sets the thickness of the stroke
  MainImage.Bitmap.Canvas.StrokeThickness := ThicknessNumberBox1.Value;
end;

procedure TForm1.StrokeCapComboBoxExit(Sender: TObject);
begin
//sets the stroke cap
  MainImage.Bitmap.Canvas.StrokeCap :=
    TStrokeCap(GetEnumValue(TypeInfo(TStrokeCap),
    StrokeCapComboBox.Selected.Text));
end;

procedure TForm1.StrokeDashComboBoxExit(Sender: TObject);
begin
//sets the stroke dash
  MainImage.Bitmap.Canvas.StrokeDash :=
    TStrokeDash(GetEnumValue(TypeInfo(TStrokeDash),
    StrokeDashComboBox.Selected.Text));
end;

procedure TForm1.StrokeJoinComboBoxExit(Sender: TObject);
begin
//sets the stroke join
  MainImage.Bitmap.Canvas.StrokeJoin :=
    TStrokeJoin(GetEnumValue(TypeInfo(TStrokeJoin),
    StrokeJoinComboBox.Selected.Text));
end;

procedure TForm1.FillColorColorComboBoxExit(Sender: TObject);
begin
//sets the fill color
  MainImage.Bitmap.Canvas.Fill.Color := FillColorColorComboBox.Color;
end;

procedure TForm1.TextSizeNumberBoxExit(Sender: TObject);
begin
//sets the font size
  MainImage.Bitmap.Canvas.Font.Size := TextSizeNumberBox.Value;
end;

Add the following lines of code to the OnClick event handlers of the ellipse, rectangle, text, and clear TButton objects, respectively:

procedure TForm1.EllipseButtonClick(Sender: TObject);
var
  MyRect: TRectF;
  x1, y1, x2, y2: integer;
begin
  // draws and fills an ellipse on the canvas with the current state
  x1 := 20;
  y1 := 20;
  x2 := MainImage.Bitmap.Canvas.Width - 20;
  y2 := MainImage.Bitmap.Canvas.Height - 20;
  // sets the circumscribed rectangle of the ellipse
  MyRect := TRectF.Create(x1, y1, x2, y2);
  // draws the ellipse on the canvas
  MainImage.Bitmap.Canvas.BeginScene;
  MainImage.Bitmap.Canvas.DrawEllipse(MyRect, 40);
  MainImage.Bitmap.Canvas.FillEllipse(MyRect, 40);
  MainImage.Bitmap.Canvas.EndScene;
  // updates the bitmap
  MainImage.Bitmap.BitmapChanged;
end;

procedure TForm1.RectangleButtonClick(Sender: TObject);
var
  MyRect: TRectF;
  x1, y1, x2, y2: integer;
begin
  // draws and fills a rectangle on the canvas with the current state
  // the rectangle to be drawn
  x1 := 60;
  y1 := 60;
  x2 := MainImage.Bitmap.Canvas.Width - 60;
  y2 := MainImage.Bitmap.Canvas.Height - 60;
  MyRect := TRectF.Create(x1, y1, x2, y2);
  MainImage.Bitmap.Canvas.BeginScene;
  MainImage.Bitmap.Canvas.DrawRect(MyRect, 0, 0, AllCorners, 100);
  MainImage.Bitmap.Canvas.FillRect(MyRect, 0, 0, AllCorners, 100);
  MainImage.Bitmap.Canvas.EndScene;
  // updates the bitmap
  MainImage.Bitmap.BitmapChanged;
end;

procedure TForm1.TextButtonClick(Sender: TObject);
var
  MyRect: TRectF;
  x1, y1, x2, y2: integer;
begin
  x1 := 60;
  y1 := 60;
  x2 := MainImage.Bitmap.Canvas.Width - 60;
  y2 := MainImage.Bitmap.Canvas.Height - 60;
  MyRect := TRectF.Create(x1, y1, x2, y2);
  // fills and draws the text in the specified rectangle area of the canvas
  MainImage.Bitmap.Canvas.BeginScene;
  MainImage.Bitmap.Canvas.FillText(MyRect, TextEdit.Text, false, 100,
    [TFillTextFlag.RightToLeft], TTextAlign.Center, TTextAlign.Center);
  MainImage.Bitmap.Canvas.EndScene;
  // updates the bitmap
  MainImage.Bitmap.BitmapChanged;
end;

procedure TForm1.ClearButtonClick(Sender: TObject);
begin
  //clears the canvas and restores the initial state
  MainImage.Bitmap.Canvas.BeginScene;
  MainImage.Bitmap.Canvas.Clear(claNull);
  MainImage.Bitmap.BitmapChanged;
  MainImage.Bitmap.Canvas.RestoreState(InitialState);
  MainImage.Bitmap.Canvas.EndScene;
  //updates the combo boxes
  UpdateStateComboBox;
end;

Uses

See Also