본문 바로가기

파이어몽키

[FMX,VCL 비교] #1 VCL의 Canvas와 FMX의 Canvas 차이

파이어몽키로 작업하다보면 VCL과의 차이점으로 어려움을 겪는 경우가 많습니다.

그동안 작업하며 습득한 차이점을 한가지한가지 풀어놓으려 합니다.

그중 첫번째 Canvas 입니다.

일반적으로 TImage에 Drawing을 하는 예제로 구성하였습니다.
VCL과 FMX의 동일한 기능을 구현했으니 비교해 보시면 좋을 것 같습니다.

FMX 코딩시 주의점

1, TImage.Picture.Bitmap => TImage.Bitmap : VCL의 Picture 객체가 빠졌습니다.

2, Bitmap.Canvas.BeginScene ~ EndScene, Bitmap.BitmapChange : Canvas에 그리기고 화면에 표시하기 위한 절차입니다.

3, Brush => Fill, Pen => Stroke 등으로 속성들이 약간씩 변했습니다.

4, MoveTo, LineTo => DrawLine

5, FMX의 기본적인 좌표가 Single 형이기 때문에 Bitmap의 Pixel 단위인 Integer로 형변환(Round, Trunc)이 필요합니다.


 이하 소스코드 입니다. 빈프로젝트에 아래 소스 복사하면 컴파일 됩니다.(Unit명만 주의) 폼에 컨트롤이 없습니다.

| VCL Canvas Freeline Draw

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FDownPos: TPoint;
    FImage: TImage;

    procedure MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FImage := TImage.Create(Self);
  FImage.Parent := Self;
  FImage.Align := alClient;
  FImage.OnMouseDown := MouseDown;
  FImage.OnMouseMove := MouseMove;
  FImage.Picture.Bitmap.SetSize(FImage.Width, FImage.Height);
  FIMage.Picture.Bitmap.Canvas.Brush.Color := clBlack;
  FImage.Picture.Bitmap.Canvas.FillRect(FImage.ClientRect);
  FImage.Visible := True;
end;

procedure TForm1.MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if ssLeft in Shift then
    FDownPos := Point(X, Y);
end;

procedure TForm1.MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if ssLeft in Shift then
  begin
    with FImage.Picture.Bitmap.Canvas do
    begin
      Pen.Color := clRed;
      Pen.Width := 3;
      MoveTo(FDownPos.X, FDownPos.Y);
      LineTo(X, Y);
    end;

    FDownPos := Point(X, Y);
  end;
end;

end.


| FMX Canvas Freeline Draw

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Objects;

type
  TForm2 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FDownPos: TPointF;
    FImage: TImage;

    procedure MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Single);
    procedure MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

procedure TForm2.FormCreate(Sender: TObject);
begin
  FImage := TImage.Create(Self);
  FImage.Parent := Self;
  FImage.Align := TAlignLayout.alClient;
  FImage.OnMouseDown := MouseDown;
  FImage.OnMouseMove := MouseMove;
  FImage.Bitmap.Create(Round(FImage.Width), Round(FImage.Height));
  FImage.Bitmap.Canvas.BeginScene;
  FImage.Bitmap.Canvas.Fill.Color := claBlack;
  FImage.Bitmap.Canvas.FillRect(FImage.ClipRect, 0, 0, AllCorners, 1);
  FImage.Bitmap.Canvas.EndScene;
  FImage.Visible := True;

end;

procedure TForm2.MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
begin
  if ssLeft in Shift then
    FDownPos := PointF(X, Y);
end;

procedure TForm2.MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
begin
  if ssLeft in Shift then
  begin
    with FImage.Bitmap.Canvas do
    begin
      BeginScene;
      Stroke.Color := claRed;
      StrokeThickness := 3;
      DrawLine(FDownPos, PointF(X, Y), 1);
      EndScene;
    end;
    FImage.Bitmap.BitmapChanged;

    FDownPos := PointF(X, Y);
  end;
end;

end.