FMXTCanvasSaveCanvas (C++)
Contents
Description
This example shows how to use the SaveCanvas and RestoreCanvas functions and their results. Is 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 - C++ 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 display 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.
TForm1 *Form1;
TCanvasSaveState *SaveState, *InitialState;
Add a new procedure to the form class, named UpdateStateComboBox
(do not forget to add it on the header as well), 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.
void __fastcall TForm1::UpdateStateComboBox() {
// 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(__delphirtti(TStrokeCap),
(int)(MainImage->Bitmap->Canvas->StrokeCap)));
StrokeDashComboBox->ItemIndex = StrokeDashComboBox->ListBox->Items->IndexOf
(GetEnumName(__delphirtti(TStrokeDash),
(int)(MainImage->Bitmap->Canvas->StrokeDash)));
StrokeJoinComboBox->ItemIndex = StrokeJoinComboBox->ListBox->Items->IndexOf
(GetEnumName(__delphirtti(TStrokeJoin),
(int)(MainImage->Bitmap->Canvas->StrokeJoin)));
FillColorColorComboBox->Color = MainImage->Bitmap->Canvas->Fill->Color;
TextSizeNumberBox->Value = MainImage->Bitmap->Canvas->Font->Size;
}
Add the following code to the OnCreate event handler of the form.
void __fastcall TForm1::FormCreate(TObject *Sender) {
// initializes the initial bitmap
MainImage->Bitmap = new TBitmap(MainImage->Width, MainImage->Height);
// updates the combo boxes values
UpdateStateComboBox();
// saves the initial state of the canvas to be customized
InitialState = MainImage->Bitmap->Canvas->SaveState();
}
Add the following lines of code to the OnClick event handlers of SaveCanvas and RestoreCanvas buttons:
void __fastcall TForm1::SaveButtonClick(TObject *Sender) {
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);
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::RestoreButtonClick(TObject *Sender) {
// restores the saved properties
MainImage->Bitmap->Canvas->RestoreState(SaveState);
RestoreButton->Enabled = false;
// updates the combo boxes
UpdateStateComboBox();
// clears the memo
StateMemo->Lines->Clear();
}
// ---------------------------------------------------------------------------
Add the following lines of code to the OnExit event handlers of the TColorComboBox, TNumberBox, and TComboBox objects, respectively:
void __fastcall TForm1::StrokeColorComboBoxExit(TObject *Sender) {
// sets the stroke color
MainImage->Bitmap->Canvas->Stroke->Color = StrokeColorComboBox->Color;
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::ThicknessNumberBox1Exit(TObject *Sender) {
// sets the thickness of the stroke
MainImage->Bitmap->Canvas->StrokeThickness = ThicknessNumberBox1->Value;
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::StrokeCapComboBoxExit(TObject *Sender) {
// sets the stroke cap
MainImage->Bitmap->Canvas->StrokeCap =
TStrokeCap(GetEnumValue(__delphirtti(TStrokeCap),
StrokeCapComboBox->Selected->Text));
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::StrokeDashComboBoxExit(TObject *Sender) {
// sets the stroke dash
MainImage->Bitmap->Canvas->StrokeDash =
TStrokeDash(GetEnumValue(__delphirtti(TStrokeDash),
StrokeDashComboBox->Selected->Text));
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::StrokeJoinComboBoxExit(TObject *Sender) {
// sets the stroke join
MainImage->Bitmap->Canvas->StrokeJoin =
TStrokeJoin(GetEnumValue(__delphirtti(TStrokeJoin),
StrokeJoinComboBox->Selected->Text));
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::FillColorColorComboBoxExit(TObject *Sender) {
// sets the fill color
MainImage->Bitmap->Canvas->Fill->Color = FillColorColorComboBox->Color;
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::TextSizeNumberBoxExit(TObject *Sender) {
// sets the font size
MainImage->Bitmap->Canvas->Font->Size = TextSizeNumberBox->Value;
}
// ---------------------------------------------------------------------------
Add the following lines of code to the OnClik event handlers of the ellipse, rectangle, text, and clear TButton objects, respectively:
void __fastcall TForm1::EllipseButtonClick(TObject *Sender) {
TRectF MyRect;
int x1, y1, x2, y2;
// 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.init(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();
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::RectangleButtonClick(TObject *Sender) {
TRectF MyRect;
int x1, y1, x2, y2;
// 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.init(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();
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::TextButtonClick(TObject *Sender) {
TRectF MyRect;
int x1, y1, x2, y2;
x1 = 60;
y1 = 60;
x2 = MainImage->Bitmap->Canvas->Width - 60;
y2 = MainImage->Bitmap->Canvas->Height - 60;
MyRect.init(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,
TFillTextFlags() << TFillTextFlag::RightToLeft, TTextAlign::Center,
TTextAlign::Center);
MainImage->Bitmap->Canvas->EndScene();
// updates the bitmap
MainImage->Bitmap->BitmapChanged();
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::ClearButtonClick(TObject *Sender)
{
//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();
}
//---------------------------------------------------------------------------
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 )