{"id":232955,"date":"2014-08-11T18:52:03","date_gmt":"2014-08-11T14:52:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=232955"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=232955","title":{"rendered":"<span class=\"post_title\">MindStream. \u041a\u0430\u043a \u043c\u044b \u043f\u0438\u0448\u0435\u043c \u041f\u041e \u043f\u043e\u0434 FireMonkey<\/span>"},"content":{"rendered":"<div class=\"content html_format\"> \t\t\t\u041c\u0435\u0441\u044f\u0446 \u043d\u0430\u0437\u0430\u0434 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0440\u043e\u0441\u0441-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f FireMonkey. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043e\u0432, \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<p>  \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u044b \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438\u0441\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0425\u0430\u0431\u0440\u0435. <\/p>\n<p>  \u0412 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u0438\u043a, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a: Dependency Injection, \u0444\u0430\u0431\u0440\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u0442.\u0434. \u0412 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u0442\u0443\u0434\u0430 \u0442\u0435\u0441\u0442\u044b Dunit. DUnit\u2019a \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u0442 \u0434\u043b\u044f FMX, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u0438\u043c. <\/p>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u043c\u044b \u0441 \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0432\u0438\u0434:<\/p>\n<p>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/2bc\/7ab\/305\/2bc7ab3058004c01ba4c95f4f9b5dd9c.png\"\/><br \/>  <a name=\"habracut\"><\/a><br \/>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u0443\u0447\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043d\u0430 Canvas\u2019e. \u041f\u0435\u0440\u0432\u044b\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0438 \u043b\u0438\u043d\u0438\u044f.<\/p>\n<p>  \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u043d\u0430 \u0444\u043e\u0440\u043c\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 TImage, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Bitmap:  <\/p>\n<pre><code class=\"delphi\">procedure TfmMain.FormCreate(Sender: TObject); begin  imgMain.Bitmap := TBitmap.Create(400, 400);  imgMain.Bitmap.Clear(TAlphaColorRec.White); end; <\/code><\/pre>\n<p>  \u041f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430 \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430:  <\/p>\n<pre><code class=\"delphi\">procedure TfmMain.btnRectClick(Sender: TObject); begin  imgMain.Bitmap.Canvas.BeginScene;  imgMain.Bitmap.Canvas.DrawRect(TRectF.Create(10, 10, 200, 270),                                 30, 60,                                 AllCorners, 100,                                 TCornerType.ctRound);  imgMain.Bitmap.Canvas.EndScene; end; <\/code><\/pre>\n<p>   \u0414\u043b\u044f \u043b\u0438\u043d\u0438\u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043f\u0440\u043e\u0449\u0435:  <\/p>\n<pre><code class=\"delphi\"> ImgMain.Bitmap.Canvas.BeginScene;  ImgMain.Bitmap.Canvas.DrawLine(FStartPos, TPointF.Create(X, Y), 1);  ImgMain.Bitmap.Canvas.EndScene; <\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0444\u0438\u0433\u0443\u0440 TMyShape \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u043d\u0430\u0448\u0438 \u0444\u0438\u0433\u0443\u0440\u044b TLine \u0438 TRectangle:  <\/p>\n<pre><code class=\"delphi\">type   TMyShape = class  private   FStartPoint, FFinalPoint: TPointF;  public   Constructor Create(aStartPoint, aFinalPoint: TPointF); overload;   procedure DrawTo(aCanvas : TCanvas);   procedure DrawShape(aCanvas : TCanvas); virtual; abstract;  end;   TLine = class(TMyShape)  private    procedure DrawShape(aCanvas : TCanvas); override;  end;   TRectangle = class(TMyShape)  private    procedure DrawShape(aCanvas : TCanvas); override;  end;  procedure TMyShape.DrawTo(aCanvas: TCanvas); begin   aCanvas.BeginScene;   DrawShape(aCanvas);   aCanvas.EndScene; end; <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c \u043c\u0435\u0442\u043e\u0434 DrawTo \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0443 \u0445\u043e\u043b\u0441\u0442\u0430 \u043a \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044e \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0444\u0438\u0433\u0443\u0440\u044b. <\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 TDrawness \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0444\u0438\u0433\u0443\u0440, \u0438 \u0438\u0445 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435:  <\/p>\n<pre><code class=\"delphi\">type  TDrawness = class  private   FShapeList : TObjectList&lt;TMyShape&gt;;     function GetShapeList: TObjectList&lt;TMyShape&gt;;  public   constructor Create;   destructor Destroy; override;   procedure DrawTo(aCanvas : TCanvas);  property ShapeList : TObjectList&lt;TMyShape&gt; read GetShapeList;  end; <\/code><\/pre>\n<p>  \u041f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0430 DrawTo \u043f\u0440\u043e\u0431\u0435\u0433\u0430\u0435\u0442 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 \u0441\u043f\u0438\u0441\u043a\u0443 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430:  <\/p>\n<pre><code class=\"delphi\">procedure TDrawness.DrawTo(aCanvas: TCanvas); var  i : Integer; begin  for i:= 0 to FShapeList.Count-1   do FShapeList[i].DrawTo(aCanvas); end; <\/code><\/pre>\n<p>  \u0422\u043e \u0435\u0441\u0442\u044c, \u0442\u0435\u043f\u0435\u0440\u044c, \u043a\u0430\u0436\u0434\u0430\u044f \u0444\u0438\u0433\u0443\u0440\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 Drawness. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c:  <\/p>\n<pre><code class=\"delphi\">procedure TfmMain.btnRectClick(Sender: TObject); var  l_StartPoint, l_FinalPoint: TPointF; begin  l_StartPoint := TPointF.Create(StrToFloat(edtStartPointX.Text),                                 StrToFloat(edtStartPointY.Text));  l_FinalPoint := TPointF.Create(StrToFloat(edtFinalPointX.Text),                                 StrToFloat(edtFinalPointY.Text));  FDrawness.ShapeList.Add(TRectangle.Create(l_StartPoint, l_FinalPoint));  FDrawness.ShapeList.Last.DrawTo(imgMain.Bitmap.Canvas); end; <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0441\u0442\u0440\u043e\u0447\u043a\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u043d\u0430\u043c \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u044b \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0444\u0438\u0433\u0443\u0440\u0443.<\/p>\n<p>  \u0414\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u0438\u043d\u0438\u0439 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u043a\u0440\u0443\u0433, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 \u043b\u0438\u043d\u0438\u0438:  <\/p>\n<pre><code class=\"delphi\">type  TmsPointCircle= class(TMyShape)  private    procedure DrawShape(const aCanvas : TCanvas); override;  end;  procedure TmsPointCircle.DrawShape(const aCanvas: TCanvas); var  l_StartPoint, l_FinalPoint: TPointF; begin  l_StartPoint.X := FStartPoint.X - 15;  l_StartPoint.Y := FStartPoint.Y - 15;   l_FinalPoint.X := FStartPoint.X + 15;  l_FinalPoint.Y := FStartPoint.Y + 15;   aCanvas.DrawEllipse(TRectF.Create(l_StartPoint, l_FinalPoint), 1); end; <\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043b\u0438\u043d\u0438\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0432\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u043c\u044b\u0448\u043a\u0438, \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e\u043a\u0430 \u0432 \u043b\u043e\u0431:  <\/p>\n<pre><code class=\"delphi\">procedure TfmMain.imgMainMouseDown(Sender: TObject; Button: TMouseButton;   Shift: TShiftState; X, Y: Single); begin  FPressed := True;  FStartPos := TPointF.Create(X, Y);   if FIsFirstClick then   FIsFirstClick := False  else  begin   FDrawness.ShapeList.Add(TLine.Create(FStartPos, FLastPoint));   FDrawness.ShapeList.Last.DrawTo(imgMain.Bitmap.Canvas);    FIsFirstClick := True;  end;   FLastPoint := TPointF.Create(X, Y);   FDrawness.ShapeList.Add(TmsPointCircle.Create(FStartPos, FLastPoint));  FDrawness.ShapeList.Last.DrawTo(imgMain.Bitmap.Canvas); end; <\/code><\/pre>\n<p>  \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043b\u0430\u0441\u0441 TDrawness \u043c\u0435\u0442\u043e\u0434 AddPrimitive:  <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.AddPrimitive(const aShape: TmsShape); begin  FShapeList.Add(aShape); end; <\/code><\/pre>\n<p>  \u0410 \u0432\u043e\u0442 \u0442\u0443\u0442 \u043c\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c Dependency Injection. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0442\u0438\u043f\u044b \u043d\u0430\u0448\u0438\u0445 \u0444\u0438\u0433\u0443\u0440. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u043c\u0435\u0442\u0430\u043a\u043b\u0430\u0441\u0441\u0430 TmsShape. \u0421\u0430\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441\u0434\u0435\u043b\u0430\u0435\u043c Singleton\u2019\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0438\u043f\u043e\u0432 \u043d\u0430\u0448\u0438\u0445 \u0444\u0438\u0433\u0443\u0440 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0443\u0434\u0430 \u043c\u0435\u0442\u043e\u0434 AddPrimitive.  <\/p>\n<pre><code class=\"delphi\">unit msRegisteredPrimitives;  interface  uses  msShape, Generics.Collections;  type  RmsShape = class of TmsShape;   TmsRegistered = TList&lt;RmsShape&gt;;   TmsRegisteredPrimitives  = class  strict private   FmsRegistered : TmsRegistered;   class var FInstance: TmsRegisteredPrimitives;   constructor Create;  public   class function GetInstance: TmsRegisteredPrimitives;   procedure AddPrimitive(const Value : RmsShape);  end;   implementation  procedure TmsRegisteredPrimitives.AddPrimitive(const Value: RmsShape); begin  FmsRegistered.Add(Value); end;  constructor TmsRegisteredPrimitives.Create;  begin   inherited;  end;   class function TmsRegisteredPrimitives.GetInstance: TmsRegisteredPrimitives;  begin   If FInstance = nil Then   begin    FInstance := TmsRegisteredPrimitives.Create();   end;   Result := FInstance;  end;  end. <\/code><\/pre>\n<p>  \u0418\u043d\u044a\u0435\u043a\u0446\u0438\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0443\u0436\u0438\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442 TMsShape.   <\/p>\n<pre><code class=\"delphi\">initialization  TmsRegisteredPrimitives.GetInstance.AddPrimitive(TmsLine);  TmsRegisteredPrimitives.GetInstance.AddPrimitive(TmsRectangle); end. <\/code><\/pre>\n<p>  \u0417\u0430\u043d\u043e\u0441\u0438\u043c(\u043d\u0430 FormCreate) \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043e\u0432 \u0432 ComboBox \u0434\u0430\u0431\u044b \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0431\u044b\u043b\u043e \u0438\u0445 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c:  <\/p>\n<pre><code class=\"delphi\">for i := 0 to TmsRegisteredPrimitives.GetInstance.PrimitivesCount-1 do   cbbPrimitives.Items.AddObject(TmsRegisteredPrimitives.GetInstance.Primitives[i].ClassName,                                 TObject(TmsRegisteredPrimitives.GetInstance.Primitives[i])); <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043f\u0443\u0442\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u0442 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0431\u0440\u0430\u043d \u0432 ComboBox:  <\/p>\n<pre><code class=\"delphi\">FDrawness.AddPrimitive(RmsShape(cbbPrimitives.items.Objects[cbbPrimitives.ItemIndex]).Create(TPointF.Create(X,Y),TPointF.Create(X+100,Y+100))); <\/code><\/pre>\n<p>  \u041e\u0431\u044a\u0435\u043a\u0442\u0443 TmsShape \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 IsNeedsSecondClick. \u041a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0432 \u043f\u043e\u0442\u043e\u043c\u043a\u0430\u0445. \u0414\u043b\u044f \u043b\u0438\u043d\u0438\u0439 True, \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 False.<\/p>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 TmsDrawness \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0432 ComboBox\u2019e:  <\/p>\n<pre><code class=\"delphi\"> property CurrentClass : RmsShape read FCurrentClass write FCurrentClass; <\/code><\/pre>\n<p>  \u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u0447\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 ComboBox.OnChange:  <\/p>\n<pre><code class=\"delphi\"> FDrawness.CurrentClass := RmsShape(cbbPrimitives.items.Objects[cbbPrimitives.ItemIndex]); <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u0438\u0433\u0443\u0440\u044b \u0432 Drawness:  <\/p>\n<pre><code class=\"delphi\"> ShapeObject := FDrawness.CurrentClass.Create(FStartPos, FLastPoint);  FDrawness.AddPrimitive(ShapeObject); <\/code><\/pre>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a Drawness \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0444\u0438\u0433\u0443\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u043c\u0443 \u043c\u0435\u0442\u043e\u0434 \u043e\u0447\u0438\u0441\u0442\u043a\u0438 Canvas\u2019a:  <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.Clear(const aCanvas: TCanvas); begin  aCanvas.BeginScene;  aCanvas.Clear(TAlphaColorRec.Null);  aCanvas.EndScene; end; <\/code><\/pre>\n<p>  \u0418 \u043f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f. \u0411\u0443\u0434\u0435\u043c \u043f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u043c \u043e\u0447\u0438\u0449\u0430\u0442\u044c Canvas, \u0430 \u043f\u043e\u0442\u043e\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 Drawness.List.  <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.DrawTo(const aCanvas: TCanvas; const aOrigin : TPointF); var  i : Integer; begin  Clear(aCanvas);   for i:= 0 to FShapeList.Count-1   do FShapeList[i].DrawTo(aCanvas, aOrigin); end; <\/code><\/pre>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0443\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c \u0432 \u0440\u0430\u0431\u043e\u0442\u0435 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430, \u043f\u043e\u0440\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0437\u0430 \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433, \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <\/p>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434 TDrawness.AddPrimitive \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043d\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0444\u043e\u0440\u043c\u0435.  <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.AddPrimitive(const aStart: TPointF; const aFinish: TPointF); begin  Assert(CurrentClass &lt;&gt; nil);  FShapeList.Add(CurrentClass.Create(aStart, aFinish)); end; <\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c, \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u0444\u0438\u0433\u0443\u0440\u044b. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u044b \u0441\u0440\u0430\u0437\u0443 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a, \u0432\u0432\u0435\u0434\u0451\u043c \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0442\u0438\u043f\u0430 TmsShape. \u041a\u043e\u0434 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:  <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.AddPrimitive(const aStart: TPointF; const aFinish: TPointF); begin  Assert(CurrentClass &lt;&gt; nil);  FCurrentAddedShape := CurrentClass.Create(aStart, aFinish);  FShapeList.Add(FCurrentAddedShape); end; <\/code><\/pre>\n<p>  \u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u043d\u0443\u0436\u0435\u043d \u043b\u0438 \u044d\u0442\u043e\u043c\u0443 \u043a\u043b\u0430\u0441\u0441\u0443 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043b\u0438\u043a \u043c\u044b\u0448\u0438 \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f.   <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.AddPrimitive(const aStart: TPointF; const aFinish: TPointF); begin  Assert(CurrentClass &lt;&gt; nil);  FCurrentAddedShape := CurrentClass.Create(aStart, aFinish);  FShapeList.Add(FCurrentAddedShape);  if not FCurrentAddedShape.IsNeedsSecondClick then  \/\/ - \u0435\u0441\u043b\u0438 \u043d\u0435 \u043d\u0430\u0434\u043e SecondClick, \u0442\u043e \u043d\u0430\u0448 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 - \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d   FCurrentAddedShape := nil; end; <\/code><\/pre>\n<p>  \u0412 \u0442\u043e\u0436\u0435 \u0432\u0440\u0435\u043c\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043e\u0432 \u043d\u0430 \u0444\u043e\u0440\u043c\u0435:  <\/p>\n<pre><code class=\"delphi\">procedure TfmMain.imgMainMouseDown(Sender: TObject; Button: TMouseButton;   Shift: TShiftState; X, Y: Single); var  l_StartPoint : TPointF; begin  l_StartPoint := TPointF.Create(X, Y);   if (FDrawness.CurrentAddedShape = nil) then  \/\/ - \u043c\u044b \u041d\u0415 \u0414\u041e\u0411\u0410\u0412\u041b\u042f\u041b\u0418 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u0430 - \u043d\u0430\u0434\u043e \u0435\u0433\u043e \u0414\u041e\u0411\u0410\u0412\u0418\u0422\u042c   FDrawness.AddPrimitive(l_StartPoint, l_StartPoint)  else   FDrawness.FinalizeCurrentShape(l_StartPoint);   FDrawness.DrawTo(imgMain.Bitmap.Canvas, FOrigin); end; <\/code><\/pre>\n<p>  \u0418\u0442\u0430\u043a \u0447\u0442\u043e \u0436\u0435 \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. <br \/>  \u0415\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043b\u0438\u043d\u0438\u044e, \u043d\u0430\u0448 CurrentAddedShape \u0440\u0430\u0432\u0435\u043d nil \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u043a\u043b\u0438\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u0442\u043e\u0447\u043a\u0430\u043c\u0438 \u043d\u0430\u0447\u0430\u043b\u0430 \u0438 \u043a\u043e\u043d\u0446\u0430 \u043e\u0442\u0440\u0435\u0437\u043a\u0430. <\/p>\n<p>  \u0414\u0430\u043b\u0435\u0435 \u0432 FDrawness.AddPrimitive \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 \u0438 \u0442\u0430\u043a \u043a\u0430\u043a(\u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u043b\u0438\u043d\u0438\u0435\u0439) \u0435\u043c\u0443 \u043d\u0443\u0436\u0435\u043d \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u043b\u0438\u043a \u043c\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c.<\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b. \u0421\u0435\u0439\u0447\u0430\u0441 \u0443 \u043d\u0430\u0441 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430 \u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f \u0442\u0430\u043a \u043a\u0430\u043a \u043b\u0438\u043d\u0438\u044f \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0439 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435 \u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f.<\/p>\n<p>  \u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u043c\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0437 \u043c\u044b\u0448\u043a\u043e\u0439, \u043c\u044b \u043e\u043f\u044f\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c CurrentAddedShape, \u0438 \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0435\u0433\u043e \u043d\u0435 \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u043b\u0438, \u0442\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0444\u0438\u043d\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0438\u0433\u0443\u0440\u044b, \u0433\u0434\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0432\u0442\u043e\u0440\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u043b\u0438\u043d\u0438\u0438, \u0438 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u043c \u043d\u0430\u0448 \u0431\u0443\u0444\u0435\u0440\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442:  <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.FinalizeCurrentShape(const aFinish: TPointF); begin   Assert(CurrentAddedShape &lt;&gt; nil);   CurrentAddedShape.FinalPoint := aFinish;   FCurrentAddedShape := nil; end; <\/code><\/pre>\n<p>  \u0418 \u043e\u043f\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0444\u0438\u0433\u0443\u0440\u044b. <\/p>\n<p>  \u0414\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0438\u0433\u0443\u0440, \u0432 FDrawness.AddPrimitive \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0438\u0433\u0443\u0440\u044b \u0432 \u0441\u043f\u0438\u0441\u043e\u043a, \u043c\u044b \u0441\u0440\u0430\u0437\u0443 \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0430\u0435\u043c \u043d\u0430\u0448 \u201c\u0431\u0443\u0444\u0435\u0440\u201d.<\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043d\u0433\u0430(\u0431\u043e\u043b\u0435\u0435 \u0432\u043c\u0435\u043d\u044f\u0435\u043c\u043e \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u043d\u0430\u0448\u0438 \u043c\u0435\u0442\u043e\u0434\u044b, \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430\u0436\u0430\u0442\u0438\u0439 \u043c\u044b\u0448\u043a\u0438 \u0432 Drawness) \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a\u0430\u044f \u043a\u0430\u0440\u0442\u0438\u043d\u0430:  <\/p>\n<pre><code class=\"delphi\">procedure TmsDiagramm.ProcessClick(const aStart: TPointF); begin  if ShapeIsEnded then  \/\/ - \u043c\u044b \u041d\u0415 \u0414\u041e\u0411\u0410\u0412\u041b\u042f\u041b\u0418 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u0430 - \u043d\u0430\u0434\u043e \u0435\u0433\u043e \u0414\u041e\u0411\u0410\u0412\u0418\u0422\u042c   BeginShape(aStart)  else   EndShape(aStart); end;  function TmsDiagramm.ShapeIsEnded: Boolean; begin  Result := (CurrentAddedShape = nil); end;  procedure TmsDiagramm.BeginShape(const aStart: TPointF); begin  Assert(CurrentClass &lt;&gt; nil);  FCurrentAddedShape := CurrentClass.Create(aStart, aStart);  FShapeList.Add(FCurrentAddedShape);  if not FCurrentAddedShape.IsNeedsSecondClick then  \/\/ - \u0435\u0441\u043b\u0438 \u043d\u0435 \u043d\u0430\u0434\u043e SecondClick, \u0442\u043e \u043d\u0430\u0448 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 - \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d   FCurrentAddedShape := nil;  Invalidate; end;  procedure TmsDiagramm.EndShape(const aFinish: TPointF); begin  Assert(CurrentAddedShape &lt;&gt; nil);  CurrentAddedShape.EndTo(aFinish);  FCurrentAddedShape := nil;  Invalidate; end;  procedure TmsDiagramm.Invalidate; begin  Clear;  DrawTo(FCanvas, FOrigin); end; <\/code><\/pre>\n<p>  \u0422\u0430\u043a \u043a\u0430\u043a TDrawness \u0443\u0436\u0435 \u043f\u043e \u0441\u0443\u0442\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440\u043e\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u043e \u0435\u0433\u043e \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c Canvas \u043a \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044e, \u0437\u0430\u043e\u0434\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c enumerator:  <\/p>\n<pre><code class=\"delphi\">procedure TmsDrawness.DrawTo(const aCanvas: TCanvas; const aOrigin : TPointF); var  l_Shape : TmsShape; begin  aCanvas.BeginScene;  try   for l_Shape in FShapeList do    l_Shape.DrawTo(aCanvas, aOrigin);  finally   aCanvas.EndScene;  end;\/\/try..finally end; <\/code><\/pre>\n<p>  \u041f\u0440\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0438 \u043b\u0438\u043d\u0438\u0438, \u0440\u0438\u0441\u0443\u0435\u043c \u043a\u0440\u0443\u0433 \u043d\u0430 \u043c\u0435\u0441\u0442\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043d\u0430\u0436\u0430\u0442\u0438\u044f:  <\/p>\n<pre><code class=\"delphi\">procedure TmsLine.DrawTo(const aCanvas : TCanvas; const aOrigin : TPointF); var  l_Proxy : TmsShape; begin  if (StartPoint = FinishPoint) then  begin   l_Proxy := TmsPointCircle.Create(StartPoint, StartPoint);   try    l_Proxy.DrawTo(aCanvas, aOrigin);   finally    FreeAndNil(l_Proxy);   end;\/\/try..finally  end\/\/StartPoint = FinishPoint  else   aCanvas.DrawLine(StartPoint.Add(aOrigin),                    FinishPoint.Add(aOrigin), 1); end; <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0438 \u0440\u0438\u0441\u0443\u0435\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439 \u043a\u0440\u0443\u0436\u043e\u043a, \u043e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043e\u0432 \u0432 Drawness \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0437 \u043c\u044b\u0448\u043a\u043e\u0439, \u043d\u0430\u0448 \u0445\u043e\u043b\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u0430\u043d, \u0438 \u043a\u0440\u0443\u0433\u0430 \u0443\u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442.<\/p>\n<p>  \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0444\u0438\u0433\u0443\u0440\u0443 \u2014 \u043a\u0440\u0443\u0433:  <\/p>\n<pre><code class=\"delphi\">type  TmsCircle = class(TmsShape)  protected   procedure DrawShape(const aCanvas : TCanvas; const aOrigin : TPointF); override;  public   class function IsNeedsSecondClick : Boolean; override;  end;  implementation  const  c_CircleRadius = 50;  { TmsCircle }  procedure TmsCircle.DrawShape(const aCanvas: TCanvas; const aOrigin : TPointF); var  l_StartPoint, l_FinalPoint: TPointF; begin  l_StartPoint.X := FStartPoint.X - c_CircleRadius;  l_StartPoint.Y := FStartPoint.Y - c_CircleRadius;   l_FinalPoint.X := FStartPoint.X + c_CircleRadius;  l_FinalPoint.Y := FStartPoint.Y + c_CircleRadius;   aCanvas.DrawEllipse(TRectF.Create(l_StartPoint.Add(aOrigin),                                    l_FinalPoint.Add(aOrigin)), 1); end;  class function TmsCircle.IsNeedsSecondClick: Boolean; begin  Result := False; end;  end. <\/code><\/pre>\n<p>  \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u043a\u0440\u0443\u0433\u0430 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 \u043d\u0430 \u0432\u044b\u0437\u043e\u0432 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430:  <\/p>\n<pre><code class=\"delphi\">class function TmsCircle.Radius: Integer; begin  Result := 50; end; <\/code><\/pre>\n<p>  \u0412 \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0438 \u0447\u0435\u0433\u043e, \u0432 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0433\u043e \u043a\u0440\u0443\u0433\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043b\u0438\u0448\u044c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 Radius:  <\/p>\n<pre><code class=\"delphi\">type  TmsPointCircle = class(TmsCircle)  protected   class function Radius: Integer; override;  end;  implementation  { TmsPointCircle }  class function TmsPointCircle.Radius: Integer; begin  Result := 10; end;  end. <\/code><\/pre>\n<p>  \u0414\u043e\u0434\u0435\u043b\u044b\u0432\u0430\u0435\u043c \u043d\u0430\u0448 Dependency Injection. \u041f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0441. \u0418 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 TmsShape \u043d\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 Register. \u0422\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u043c:<\/p>\n<p>  \u041a\u043b\u0430\u0441\u0441 TmsShape \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:  <\/p>\n<pre><code class=\"delphi\">type  TmsShape = class abstract (TObject)  private   FStartPoint: TPointF;   FFinishPoint: TPointF;  protected   property StartPoint : TPointF read FStartPoint;   property FinishPoint : TPointF read FFinishPoint;   class procedure Register;  public   constructor Create(const aStartPoint, aFinishPoint: TPointF); virtual;   procedure DrawTo(const aCanvas : TCanvas; const aOrigin : TPointF); virtual; abstract;   class function IsNeedsSecondClick : Boolean; virtual;   procedure EndTo(const aFinishPoint: TPointF);  end;  implementation  uses   msRegisteredPrimitives   ;  class procedure TmsShape.Register; begin  TmsRegisteredPrimitives.Instance.AddPrimitive(Self); end;  constructor TmsShape.Create(const aStartPoint, aFinishPoint: TPointF); begin  FStartPoint := aStartPoint;  FFinishPoint := aFinishPoint; end;  procedure TmsShape.EndTo(const aFinishPoint: TPointF); begin  FFinishPoint := aFinishPoint; end;  class function TmsShape.IsNeedsSecondClick : Boolean; begin  Result := false; end;  end. <\/code><\/pre>\n<p>  \u0410 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0441\u0442\u0440\u043e\u043a\u0430 \u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 TmsRectangle:  <\/p>\n<pre><code class=\"delphi\">initialization  TmsRectangle.Register; <\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0441 \u0437\u0430\u043a\u0440\u0443\u0433\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u043a\u0440\u0430\u044f\u043c\u0438:  <\/p>\n<pre><code class=\"delphi\">type  TmsRoundedRectangle = class(TmsRectangle)  protected   procedure DrawTo(const aCanvas : TCanvas; const aOrigin : TPointF); override;  end;\/\/TmsRoundedRectangle  implementation  procedure TmsRoundedRectangle.DrawTo(const aCanvas: TCanvas; const aOrigin : TPointF); begin  aCanvas.DrawRect(TRectF.Create(StartPoint.Add(aOrigin),                                 FinishPoint.Add(aOrigin)),                   10, 10,                   AllCorners, 1,                   TCornerType.ctRound); end;  initialization  TmsRoundedRectangle.Register;  end. <\/code><\/pre>\n<p>  \u0418 \u0432\u0441\u0451! \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0444\u0438\u0433\u0443\u0440\u044b \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435, \u044d\u0442\u043e \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c. <br \/>  \u0415\u0449\u0451 \u0440\u0430\u0437. <br \/>  \u041d\u0430\u043c \u043d\u0430\u0434\u043e \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u043e\u0442 \u043b\u044e\u0431\u043e\u0439 \u0444\u0438\u0433\u0443\u0440\u044b, \u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f(\u0415\u0441\u043b\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e). <br \/>  \u0422\u0430\u043a \u043a\u0430\u043a TmsShape \u2014 \u0441\u0443\u043f\u0435\u0440\u043a\u043b\u0430\u0441\u0441, \u0442\u043e \u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 Register \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440. <br \/>  \u0414\u0430\u043b\u044c\u0448\u0435 \u0443 \u043d\u0430\u0441 \u043d\u0430 FormCreate \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432 ComboBox. <br \/>  \u0418 \u043f\u0440\u0438 \u0432\u044b\u0431\u043e\u0440\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0444\u0438\u0433\u0443\u0440\u044b, \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b.<\/p>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044e \u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u0444\u0438\u0433\u0443\u0440\u044b. \u0412 \u043a\u043b\u0430\u0441\u0441\u0435 TmsRectangle \u0432\u0432\u0435\u0434\u0451\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u0432\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 CornerRadius, \u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435, \u0437\u0430\u043e\u0434\u043d\u043e \u0443\u0431\u0440\u0430\u0432 \u043c\u0430\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0447\u0438\u0441\u043b\u0430.  <\/p>\n<pre><code class=\"delphi\">class function TmsRectangle.CornerRadius: Single; begin  Result := 0; end;  procedure TmsRectangle.DrawTo(const aCanvas: TCanvas; const aOrigin : TPointF); begin  aCanvas.DrawRect(TRectF.Create(StartPoint.Add(aOrigin),                                 FinishPoint.Add(aOrigin)),                   CornerRadius,                   CornerRadius,                   AllCorners,                   1,                   TCornerType.ctRound); end; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u043d\u043e\u0432\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 CornerRadius \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c \u0443\u0433\u043b\u043e\u043c \u043e\u043a\u0440\u0443\u0433\u043b\u0435\u043d\u0438\u044f \u0443\u0433\u043b\u043e\u0432. \u041a\u043b\u0430\u0441\u0441 \u0432 \u0446\u0435\u043b\u043e\u043c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:  <\/p>\n<pre><code class=\"delphi\">type  TmsRoundedRectangle = class(TmsRectangle)  protected   class function CornerRadius: Single; override;  end;\/\/TmsRoundedRectangle  implementation  class function TmsRoundedRectangle.CornerRadius: Single; begin  Result := 10; end;  initialization  TmsRoundedRectangle.Register;  end. <\/code><\/pre>\n<p>  \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u043c\u0441\u044f \u043e\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442. \u0410 \u0442\u0430\u043a \u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0446\u0432\u0435\u0442 \u0437\u0430\u043b\u0438\u0432\u043a\u0438. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0437\u0430\u043b\u0438\u0442\u044c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a:  <\/p>\n<pre><code class=\"delphi\">procedure TmsRectangle.DrawTo(const aCanvas: TCanvas; const aOrigin : TPointF); begin  aCanvas.Fill.Color := TAlphaColorRec.White;  aCanvas.DrawRect(TRectF.Create(StartPoint.Add(aOrigin),                                 FinishPoint.Add(aOrigin)),                   CornerRadius,                   CornerRadius,                   AllCorners,                   1,                   TCornerType.ctRound);  aCanvas.FillRect(TRectF.Create(StartPoint.Add(aOrigin),                                 FinishPoint.Add(aOrigin)),                   CornerRadius,                   CornerRadius,                   AllCorners,                   1,                   TCornerType.ctRound); end; <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u044b \u0437\u0430\u043a\u0440\u0430\u0441\u0438\u0442\u044c \u0444\u0438\u0433\u0443\u0440\u0443, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0446\u0432\u0435\u0442 \u0437\u0430\u043a\u0440\u0430\u0441\u043a\u0438 \u0445\u043e\u043b\u0441\u0442\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0447\u0442\u043e \u0431\u044b \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434, \u0438 \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0432 \u043c\u0435\u0442\u043e\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u2014 \u043c\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c FillColor \u0434\u043b\u044f TmsShape. \u0410 \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u0443 \u0441\u0443\u043f\u0435\u0440 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<p>  \u0411\u0443\u0434\u0435\u043c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0445\u043e\u043b\u0441\u0442\u0443, \u0430 \u0443\u0436\u0435 \u043f\u043e\u0442\u043e\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0444\u0438\u0433\u0443\u0440\u044b:  <\/p>\n<pre><code class=\"delphi\">procedure TmsShape.DrawTo(const aCanvas : TCanvas; const aOrigin : TPointF); begin  aCanvas.Fill.Color := FillColor;  DoDrawTo(aCanvas, aOrigin); end; <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0434\u043b\u044f \u043a\u0440\u0443\u0433\u0430:  <\/p>\n<pre><code class=\"delphi\">type  TmsCircle = class(TmsShape)  protected   class function InitialRadiusX: Integer; virtual;   class function InitialRadiusY: Integer; virtual;   function FillColor: TAlphaColor; override;   procedure DoDrawTo(const aCanvas : TCanvas; const aOrigin : TPointF); override;  public   constructor Create(const aStartPoint, aFinishPoint: TPointF); override;  end; <\/code><\/pre>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043e\u043c \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0436\u0435\u043b\u0442\u044b\u0439 \u043e\u0432\u0430\u043b:  <\/p>\n<pre><code class=\"delphi\">type  TmsUseCaseLikeEllipse = class(TmsCircle)  protected   class function InitialRadiusY: Integer; override;   function FillColor: TAlphaColor; override;  end;\/\/TmsUseCaseLikeEllipse  implementation  class function TmsUseCaseLikeEllipse.InitialRadiusY: Integer; begin  Result := 35; end;  function TmsUseCaseLikeEllipse.FillColor: TAlphaColor; begin  Result := TAlphaColorRec.Yellow; end;  initialization  TmsUseCaseLikeEllipse.Register;  end. <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 \u2014 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a:  <\/p>\n<pre><code class=\"delphi\">type  TmsTriangle = class(TmsShape)  protected   function FillColor: TAlphaColor; override;   procedure DoDrawTo(const aCanvas : TCanvas; const aOrigin : TPointF); override;  end;\/\/TmsTriangle  implementation  uses  System.Math.Vectors  ;  function TmsTriangle.FillColor: TAlphaColor; begin  Result := TAlphaColorRec.Green; end;  procedure TmsTriangle.DoDrawTo(const aCanvas: TCanvas; const aOrigin : TPointF); const  cHeight = 100; var  l_P : TPolygon; begin  SetLength(l_P, 4);  l_P[0] := TPointF.Create(StartPoint.X - cHeight div 2,                           StartPoint.Y + cHeight div 2);  l_P[1] := TPointF.Create(StartPoint.X + cHeight div 2,                           StartPoint.Y + cHeight div 2);  l_P[2] := TPointF.Create(StartPoint.X,                           StartPoint.Y - cHeight div 2);  l_P[3] := l_P[0];  aCanvas.DrawPolygon(l_P, 1);  aCanvas.FillPolygon(l_P, 0.5); end;  initialization  TmsTriangle.Register;  end. <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0438\u0433\u0443\u0440. \u041d\u043e \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e. \u0422\u0438\u043f TPolygon \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u0437 TPointF. \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0435\u0433\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0440\u0430\u0441\u0447\u0435\u0442\u0430\u043c, \u043f\u0440\u0438 \u0432\u0441\u0451\u043c \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0442\u043e\u0447\u043a\u0430 \u043f\u043e\u043b\u0438\u0433\u043e\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0435\u0433\u043e \u043f\u0435\u0440\u0432\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439. \u0420\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0436\u0435 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438.<\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0434\u0451\u043c \u0432 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432. \u041a\u043b\u0430\u0441\u0441 TmsDrawness \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0435\u043c \u0432 TmsDiagramm. \u0422\u0430\u043a\u0436\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 Canvas \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043b\u0430\u0441\u0441 Diagramm, \u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u043c Canvas \u0447\u0430\u0441\u0442\u044c\u044e Diagramm. <\/p>\n<p>  \u0423\u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u0444\u043e\u0440\u043c\u044b \u201c\u043b\u0438\u0448\u043d\u0438\u0435 \u0437\u043d\u0430\u043d\u0438\u044f\u201d \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043c \u0438\u0445 \u0432 \u043a\u043b\u0430\u0441\u0441 Diagramm, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0444\u0438\u0433\u0443\u0440 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.  <\/p>\n<pre><code class=\"delphi\">type  TmsDiagramm = class(TObject)  private   FShapeList : TmsShapeList;   FCurrentClass : RmsShape;   FCurrentAddedShape : TmsShape;   FCanvas : TCanvas;   FOrigin : TPointF;  private   procedure DrawTo(const aCanvas : TCanvas; const aOrigin : TPointF);   function CurrentAddedShape: TmsShape;   procedure BeginShape(const aStart: TPointF);   procedure EndShape(const aFinish: TPointF);   function ShapeIsEnded: Boolean;   class function AllowedShapes: RmsShapeList;   procedure CanvasChanged(aCanvas: TCanvas);  public   constructor Create(anImage: TImage);   procedure ResizeTo(anImage: TImage);   destructor Destroy; override;   procedure ProcessClick(const aStart: TPointF);   procedure Clear;   property CurrentClass : RmsShape read FCurrentClass write FCurrentClass;   procedure Invalidate;   procedure AllowedShapesToList(aList: TStrings);   procedure SelectShape(aList: TStrings; anIndex: Integer);  end;  implementation  uses  msRegisteredPrimitives  ;  class function TmsDiagramm.AllowedShapes: RmsShapeList; begin  Result := TmsRegisteredPrimitives.Instance.Primitives; end;  procedure TmsDiagramm.AllowedShapesToList(aList: TStrings); var  l_Class : RmsShape; begin  for l_Class in AllowedShapes do   aList.AddObject(l_Class.ClassName, TObject(l_Class)); end;  procedure TmsDiagramm.SelectShape(aList: TStrings; anIndex: Integer); begin  CurrentClass := RmsShape(aList.Objects[anIndex]); end;  procedure TmsDiagramm.ProcessClick(const aStart: TPointF); begin  if ShapeIsEnded then  \/\/ - \u043c\u044b \u041d\u0415 \u0414\u041e\u0411\u0410\u0412\u041b\u042f\u041b\u0418 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u0430 - \u043d\u0430\u0434\u043e \u0435\u0433\u043e \u0414\u041e\u0411\u0410\u0412\u0418\u0422\u042c   BeginShape(aStart)  else   EndShape(aStart); end;  procedure TmsDiagramm.BeginShape(const aStart: TPointF); begin  Assert(CurrentClass &lt;&gt; nil);  FCurrentAddedShape := CurrentClass.Create(aStart, aStart);  FShapeList.Add(FCurrentAddedShape);  if not FCurrentAddedShape.IsNeedsSecondClick then  \/\/ - \u0435\u0441\u043b\u0438 \u043d\u0435 \u043d\u0430\u0434\u043e SecondClick, \u0442\u043e \u043d\u0430\u0448 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432 - \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d   FCurrentAddedShape := nil;  Invalidate; end;  procedure TmsDiagramm.Clear; begin  FCanvas.BeginScene;  try   FCanvas.Clear(TAlphaColorRec.Null);  finally   FCanvas.EndScene;  end;\/\/try..finally end;  constructor TmsDiagramm.Create(anImage: TImage); begin  FShapeList := TmsShapeList.Create;  FCurrentAddedShape := nil;  FCanvas := nil;  FOrigin := TPointF.Create(0, 0);  ResizeTo(anImage);  FCurrentClass := AllowedShapes.First; end;  procedure TmsDiagramm.ResizeTo(anImage: TImage); begin  anImage.Bitmap := TBitmap.Create(Round(anImage.Width), Round(anImage.Height));  CanvasChanged(anImage.Bitmap.Canvas); end;  procedure TmsDiagramm.CanvasChanged(aCanvas: TCanvas); begin  FCanvas := aCanvas;  Invalidate; end;  function TmsDiagramm.CurrentAddedShape: TmsShape; begin  Result := FCurrentAddedShape; end;  destructor TmsDiagramm.Destroy; begin  FreeAndNil(FShapeList);  inherited; end;  procedure TmsDiagramm.DrawTo(const aCanvas: TCanvas; const aOrigin : TPointF); var  l_Shape : TmsShape; begin  aCanvas.BeginScene;  try   for l_Shape in FShapeList do    l_Shape.DrawTo(aCanvas, aOrigin);  finally   aCanvas.EndScene;  end;\/\/try..finally end;  procedure TmsDiagramm.EndShape(const aFinish: TPointF); begin  Assert(CurrentAddedShape &lt;&gt; nil);  CurrentAddedShape.EndTo(aFinish);  FCurrentAddedShape := nil;  Invalidate; end;  procedure TmsDiagramm.Invalidate; begin  Clear;  DrawTo(FCanvas, FOrigin); end;  function TmsDiagramm.ShapeIsEnded: Boolean; begin  Result := (CurrentAddedShape = nil); end;  end. <\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u0444\u043e\u0440\u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:  <\/p>\n<pre><code class=\"delphi\">var  fmMain: TfmMain;  implementation  {$R *.fmx}  procedure TfmMain.btnClearImageClick(Sender: TObject); begin  FDiagramm.Clear; end;  procedure TfmMain.btnDrawAllClick(Sender: TObject); begin  FDiagramm.Invalidate; end;  procedure TfmMain.cbbPrimitivesChange(Sender: TObject); begin  FDiagramm.SelectShape(cbbPrimitives.Items, cbbPrimitives.ItemIndex); end;  procedure TfmMain.FormCreate(Sender: TObject); begin  FDiagramm := TmsDiagramm.Create(imgMain);  FDiagramm.AllowedShapesToList(cbbPrimitives.Items); end;  procedure TfmMain.FormDestroy(Sender: TObject); begin  FreeAndNil(FDiagramm); end;  procedure TfmMain.imgMainMouseMove(Sender: TObject; Shift: TShiftState; X,   Y: Single); begin  Caption := 'x = ' + FloatToStr(X) + '; y = ' + FloatToStr(Y); end;  procedure TfmMain.imgMainResize(Sender: TObject); begin  FDiagramm.ResizeTo(imgMain); end;  procedure TfmMain.imgMainMouseDown(Sender: TObject; Button: TMouseButton;   Shift: TShiftState; X, Y: Single); begin  FDiagramm.ProcessClick(TPointF.Create(X, Y)); end;  procedure TfmMain.miAboutClick(Sender: TObject); begin  ShowMessage(self.Caption); end;  procedure TfmMain.miExitClick(Sender: TObject); begin  self.Close; end;  end. <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443 \u043d\u0430\u0441 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0431\u044b\u043b \u0437\u0430\u043f\u0438\u0441\u0430\u043d \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043f\u0440\u044f\u0442\u0430\u043d \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440\u0435 TmsDiagram. <\/p>\n<p>  \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0448\u0430\u0433\u043e\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e:  <\/p>\n<pre><code class=\"delphi\">type  TmsDiagrammList = TObjectList&lt;TmsDiagramm&gt;;   TmsDiagramms = class(TObject)  private   f_Diagramms : TmsDiagrammList;   f_CurrentDiagramm : TmsDiagramm;  public   constructor Create(anImage: TImage; aList: TStrings);   destructor Destroy; override;   procedure ProcessClick(const aStart: TPointF);   procedure Clear;   procedure SelectShape(aList: TStrings; anIndex: Integer);   procedure AllowedShapesToList(aList: TStrings);   procedure ResizeTo(anImage: TImage);   procedure AddDiagramm(anImage: TImage; aList: TStrings);   function CurrentDiagrammIndex: Integer;   procedure SelectDiagramm(anIndex: Integer);  end;\/\/TmsDiagramms  implementation  uses  System.SysUtils  ;  constructor TmsDiagramms.Create(anImage: TImage; aList: TStrings); begin  inherited Create;  f_Diagramms := TmsDiagrammList.Create;  AddDiagramm(anImage, aList); end;  procedure TmsDiagramms.AddDiagramm(anImage: TImage; aList: TStrings); begin  f_CurrentDiagramm := TmsDiagramm.Create(anImage, IntToStr(f_Diagramms.Count + 1));  f_Diagramms.Add(f_CurrentDiagramm);  aList.AddObject(f_CurrentDiagramm.Name, f_CurrentDiagramm);  \/\/f_CurrentDiagramm.Invalidate; end;  function TmsDiagramms.CurrentDiagrammIndex: Integer; begin  Result := f_Diagramms.IndexOf(f_CurrentDiagramm); end;  procedure TmsDiagramms.SelectDiagramm(anIndex: Integer); begin  if (anIndex &lt; 0) OR (anIndex &gt;= f_Diagramms.Count) then   Exit;  f_CurrentDiagramm := f_Diagramms.Items[anIndex];  f_CurrentDiagramm.Invalidate; end;  destructor TmsDiagramms.Destroy; begin  FreeAndNil(f_Diagramms);  inherited; end;  procedure TmsDiagramms.ProcessClick(const aStart: TPointF); begin  f_CurrentDiagramm.ProcessClick(aStart); end;  procedure TmsDiagramms.Clear; begin  f_CurrentDiagramm.Clear; end;  procedure TmsDiagramms.SelectShape(aList: TStrings; anIndex: Integer); begin  f_CurrentDiagramm.SelectShape(aList, anIndex); end;  procedure TmsDiagramms.AllowedShapesToList(aList: TStrings); begin  f_CurrentDiagramm.AllowedShapesToList(aList); end;  procedure TmsDiagramms.ResizeTo(anImage: TImage); begin  f_CurrentDiagramm.ResizeTo(anImage); end;  end. <\/code><\/pre>\n<p>  \u041a\u0430\u043a \u0432\u0438\u0434\u0438\u043c, \u043a\u043b\u0430\u0441\u0441 \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c, \u043f\u043e \u0441\u0443\u0442\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b, \u0438 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c.<\/p>\n<p>  \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0447\u0442\u043e \u0443 \u043a\u0430\u0436\u0434\u043e\u0439 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0441\u0432\u043e\u0439 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 IndexOf \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0443:  <\/p>\n<pre><code class=\"delphi\">function TmsRegisteredShapes.IndexOf(const aValue : RmsShape): Integer; begin  Result := f_Registered.IndexOf(aValue); end; <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435:  <\/p>\n<pre><code class=\"delphi\">function TmsDiagramm.CurrentShapeClassIndex: Integer; begin  Result := AllowedShapes.IndexOf(FCurrentClass); end; <\/code><\/pre>\n<p>  \u0418 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c:  <\/p>\n<pre><code class=\"delphi\">function TmsDiagramms.CurrentShapeClassIndex: Integer; begin  Result := f_CurrentDiagramm.CurrentShapeClassIndex; end; <\/code><\/pre>\n<p>  \u041e\u0434\u043d\u0430\u043a\u043e \u043c\u044b \u0432\u0441\u0451 \u0435\u0449\u0451 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u0441\u043f\u0438\u0441\u043a\u0443 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 \u0444\u043e\u0440\u043c\u044b, \u043f\u043e\u0440\u0430 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0438 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e. \u0414\u043b\u044f \u0447\u0435\u0433\u043e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u201c\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u201d. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043e\u0432 \u0444\u043e\u0440\u043c\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u0439:  <\/p>\n<pre><code class=\"delphi\">type  TmsDiagrammsController = class(TObject)  private   imgMain: TImage;   cbShapes: TComboBox;   cbDiagramm: TComboBox;   btAddDiagramm: TButton;   FDiagramm: TmsDiagramms;   procedure cbDiagrammChange(Sender: TObject);   procedure imgMainResize(Sender: TObject);   procedure cbShapesChange(Sender: TObject);   procedure btAddDiagrammClick(Sender: TObject);   procedure imgMainMouseDown(Sender: TObject; Button: TMouseButton;       Shift: TShiftState; X, Y: Single);  public   constructor Create(aImage: TImage; aShapes: TComboBox; aDiagramm: TComboBox; aAddDiagramm: TButton);   destructor Destroy; override;   procedure Clear;   procedure ProcessClick(const aStart: TPointF);  end;\/\/TmsDiagrammsController  implementation  uses  System.SysUtils  ;  constructor TmsDiagrammsController.Create(aImage: TImage; aShapes: TComboBox; aDiagramm: TComboBox; aAddDiagramm: TButton); begin  inherited Create;  imgMain := aImage;  cbShapes := aShapes;  cbDiagramm := aDiagramm;  btAddDiagramm := aAddDiagramm;  FDiagramm := TmsDiagramms.Create(imgMain, cbDiagramm.Items);  FDiagramm.AllowedShapesToList(cbShapes.Items);  cbShapes.ItemIndex := FDiagramm.CurrentShapeClassIndex;  cbDiagramm.ItemIndex := FDiagramm.CurrentDiagrammIndex;  cbDiagramm.OnChange := cbDiagrammChange;  imgMain.OnResize := imgMainResize;  cbShapes.OnChange := cbShapesChange;  btAddDiagramm.OnClick := btAddDiagrammClick;  imgMain.OnMouseDown := imgMainMouseDown; end;  procedure TmsDiagrammsController.cbDiagrammChange(Sender: TObject); begin  FDiagramm.SelectDiagramm(cbDiagramm.ItemIndex);  cbShapes.ItemIndex := FDiagramm.CurrentShapeClassIndex; end;  procedure TmsDiagrammsController.imgMainResize(Sender: TObject); begin  FDiagramm.ResizeTo(imgMain); end;  procedure TmsDiagrammsController.cbShapesChange(Sender: TObject); begin  FDiagramm.SelectShape(cbShapes.Items, cbShapes.ItemIndex); end;  procedure TmsDiagrammsController.btAddDiagrammClick(Sender: TObject); begin  FDiagramm.AddDiagramm(imgMain, cbDiagramm.Items);  cbDiagramm.ItemIndex := FDiagramm.CurrentDiagrammIndex;  cbShapes.ItemIndex := FDiagramm.CurrentShapeClassIndex; end;  destructor TmsDiagrammsController.Destroy; begin  FreeAndNil(FDiagramm); end;  procedure TmsDiagrammsController.Clear; begin  FDiagramm.Clear; end;  procedure TmsDiagrammsController.ProcessClick(const aStart: TPointF); begin  FDiagramm.ProcessClick(aStart); end;  procedure TmsDiagrammsController.imgMainMouseDown(Sender: TObject;   Button: TMouseButton; Shift: TShiftState; X, Y: Single); begin  Self.ProcessClick(TPointF.Create(X, Y)); end;  end. <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0451 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u2014 \u044d\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440:  <\/p>\n<pre><code class=\"delphi\">procedure TfmMain.FormCreate(Sender: TObject); begin  FDiagrammsController := TmsDiagrammsController.Create(imgMain, cbShapes, cbDiagramm, btAddDiagramm); end; <\/code><\/pre>\n<p>  \u041a\u0430\u0440\u0442\u0438\u043d\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/99a\/207\/2c3\/99a2072c3ada427c92ca464569e67d6a.PNG\"\/><\/p>\n<p>  UML \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<p>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/2bc\/7ab\/305\/2bc7ab3058004c01ba4c95f4f9b5dd9c.png\"\/><\/p>\n<p>  <a href=\"https:\/\/bitbucket.org\/ingword\/mindstream\/branch\/Developing\">BitBucket repository<\/a><\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0438, \u043a\u0430\u043a \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043e\u0442 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u041f\u0440\u0438\u0432\u0435\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u0440 Dependency Injection. \u0427\u0442\u043e \u043d\u0430\u043c \u043e\u0447\u0435\u043d\u044c \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u043b\u043e \u0436\u0438\u0437\u043d\u044c. \u0418\u043d\u0430\u0447\u0435 \u0432 \u043a\u043e\u0434\u0435 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u043b\u0438\u0441\u044c \u0431\u044b \u043d\u0435\u0432\u043d\u044f\u0442\u043d\u044b\u0435 case of \u0438 Object is. \u041f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438, \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043a\u0430\u043a \u0443\u0445\u043e\u0434\u0438\u0442\u044c \u043e\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0439. \u0421\u043e\u0437\u0434\u0430\u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0435\u0440\u0435\u0442 \u043d\u0430 \u0441\u0435\u0431\u044f \u0432\u0441\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u0430. \u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0438, \u043a\u0430\u043a \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u201c\u0448\u0432\u0435\u0439\u0446\u0430\u0440\u0441\u043a\u0438\u0445 \u043d\u043e\u0436\u0435\u0439\u201d \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430, \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u043b\u043e\u0439 \u043f\u043e \u043c\u0435\u0440\u0435 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438. TmsDiagramm \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435. TmsDiagramms \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c, \u043e\u0434\u043d\u0430\u043a\u043e \u043a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0430 \u043d\u0451\u043c \u0442\u0430\u043a\u0436\u0435 \u0432\u0441\u0451 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u0436\u0434\u043e\u0439 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u0440\u043e\u043c. \u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u043a\u043b\u0430\u0441\u0441 TmsDiagrammsController, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u0443\u044e\u0449\u0438\u043c \u0437\u0432\u0435\u043d\u043e\u043c \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0438 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430\u043c\u0438. <\/p>\n<p>  P.S. \u0423\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0435 \u0445\u0430\u0431\u0440\u0430\u044e\u0437\u0435\u0440\u044b. \u0421 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u0435\u043c \u0432\u044b\u0441\u043b\u0443\u0448\u0430\u044e \u0432\u0441\u0435 \u0432\u0430\u0448\u0438 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0421\u0442\u0430\u0442\u044c\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u0430 \u043d\u0430 \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u043a\u0440\u0443\u0433 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u044b \u0443\u0436 \u043e\u0447\u0435\u043d\u044c \u0434\u043e\u0442\u043e\u0448\u043d\u043e. \u042d\u0442\u043e \u043c\u043e\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430 \u0425\u0430\u0431\u0440\u0435, \u043f\u043e\u0441\u0435\u043c\u0443, \u043d\u0435 \u0441\u0443\u0434\u0438\u0442\u0435 \u0441\u0442\u0440\u043e\u0433\u043e. \t\t\t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/232955\/\"> http:\/\/habrahabr.ru\/post\/232955\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\"> \t\t\t\u041c\u0435\u0441\u044f\u0446 \u043d\u0430\u0437\u0430\u0434 \u043c\u044b \u0440\u0435\u0448\u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0440\u043e\u0441\u0441-\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f FireMonkey. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043b\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043e\u0432, \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<p>  \u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u044b \u0434\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043b\u0438\u0441\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0425\u0430\u0431\u0440\u0435. <\/p>\n<p>  \u0412 \u0441\u0442\u0430\u0442\u044c\u044f\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0442\u0435\u0445\u043d\u0438\u043a, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a: Dependency Injection, \u0444\u0430\u0431\u0440\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u0442.\u0434. \u0412 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u0442\u0443\u0434\u0430 \u0442\u0435\u0441\u0442\u044b Dunit. DUnit\u2019a \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u0442 \u0434\u043b\u044f FMX, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u0438\u043c. <\/p>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u043c\u044b \u0441 \u0440\u0430\u0431\u043e\u0447\u0435\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0432\u0438\u0434:<\/p>\n<p>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/2bc\/7ab\/305\/2bc7ab3058004c01ba4c95f4f9b5dd9c.png\"\/>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-232955","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/232955","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=232955"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/232955\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=232955"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=232955"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=232955"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}