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 FireMonkey HD 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.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.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.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.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.ftRightToLeft], TTextAlign.taCenter, TTextAlign.taCenter); 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.Types.TCanvas.SaveState ( fr | de | ja )
- FMX.Types.TCanvas.RestoreState ( fr | de | ja )
- FMX.Types.TCanvas.Stroke ( fr | de | ja )
- FMX.Types.TCanvas.StrokeThickness ( fr | de | ja )
- FMX.Types.TCanvas.StrokeCap ( fr | de | ja )
- FMX.Types.TCanvas.StrokeDash ( fr | de | ja )
- FMX.Types.TCanvas.StrokeJoin ( fr | de | ja )
- FMX.Types.TCanvas.Font ( fr | de | ja )
- FMX.Types.TCanvas.Fill ( fr | de | ja )
- FMX.Types.TCanvas.Clear ( fr | de | ja )
- FMX.Types.TCanvas.DrawEllipse ( fr | de | ja )
- FMX.Types.TCanvas.FillEllipse ( fr | de | ja )
- FMX.Types.TCanvas.DrawRect ( fr | de | ja )
- FMX.Types.TCanvas.FillRect ( fr | de | ja )
- FMX.Types.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 )
