FMXTCanvasSaveCanvas (Delphi)
Contents
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:
- A TImage.
- Two TButton objects (a Save State button and a Restore State button) and a TMemo object to display the saved state.
- A TColorComboBox object to set and display the current Stroke color.
- A TColorComboBox object to set and display the current Fill color.
- A TNumberBox to set and display the current StrokeThickness property value.
- A TNumberBox to set and display the current Font size.
- Three TComboBox objects to set and display the current StrokeCap, StrokeDah, and StrokeJoin properties.
- Two TButton objects for drawing and filling an ellipse and a rectangle.
- A TButton and a TEdit to set and display a text.
- A TButton to clear and reset the TCanvas to the initial state.
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.
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
- FMX.Graphics.TCanvas.SaveState ( fr | de | ja )
- FMX.Graphics.TCanvas.RestoreState ( fr | de | ja )
- FMX.Graphics.TCanvas.Stroke ( fr | de | ja )
- FMX.Graphics.TCanvas.StrokeThickness ( fr | de | ja )
- FMX.Graphics.TCanvas.StrokeCap ( fr | de | ja )
- FMX.Graphics.TCanvas.StrokeDash ( fr | de | ja )
- FMX.Graphics.TCanvas.StrokeJoin ( fr | de | ja )
- FMX.Graphics.TCanvas.Font ( fr | de | ja )
- FMX.Graphics.TCanvas.Fill ( fr | de | ja )
- FMX.Graphics.TCanvas.Clear ( fr | de | ja )
- FMX.Graphics.TCanvas.DrawEllipse ( fr | de | ja )
- FMX.Graphics.TCanvas.FillEllipse ( fr | de | ja )
- FMX.Graphics.TCanvas.DrawRect ( fr | de | ja )
- FMX.Graphics.TCanvas.FillRect ( fr | de | ja )
- FMX.Graphics.TCanvas.FillText ( fr | de | ja )
- FMX.Objects.TImage.Bitmap ( fr | de | ja )
- FMX.Objects.TBitmap.Canvas ( fr | de | ja )
- System.Types.TRectF ( fr | de | ja )
See Also
- FMX.Forms.TCommonCustomForm.OnCreate ( fr | de | ja )
- FMX.Controls.TControl.OnClick ( fr | de | ja )
- FMX.Controls.TControl.OnExit ( fr | de | ja )