English Русский 中文 Español Deutsch Português
DoEasyライブラリのグラフィックス(第79部): 「アニメーションフレーム」オブジェクトクラスとその子孫オブジェクト

DoEasyライブラリのグラフィックス(第79部): 「アニメーションフレーム」オブジェクトクラスとその子孫オブジェクト

MetaTrader 5 | 7 10月 2021, 13:56
277 0
Artyom Trishkin
Artyom Trishkin

内容


概念

前回の記事では、描画された形状の下にある背景の一部を保存してから復元するためのクラスを作成しました。ここでは、この概念についての作業を再開し、それに基づいて、単一のアニメーションフレームの基本クラスとその子孫(テキストアニメーションフレームと長方形アニメーションフレームのクラス)を作成します。

基本クラスには単一のアニメーションフレームの共通のプロパティセットが含まれ、その子孫には、形状を描画するための固有のメソッドがあります。テキストアニメーションクラスはテキストの操作を可能にするためのものです。長方形アニメーションフレームは、単一のアニメーションフレームを作成し、そのようなCCanvasクラスメソッドに基づく描画メソッドを使用してさまざまな形状を描画するためのものです。

作成された各フォームオブジェクトはカスタムキャンバスに描画するための一連のメソッドを備えているため、フォーム上に新しい画像をすばやく作成して管理できます。各フォームで描画ツールを便利に使用できるように、フォーム上に作成されたすべてのテキストと形状の画像のリストを特徴とする共通クラスを作成します。後に新しいアニメーションメソッドを追加する際には、それらのリストも共通クラスに配置します。このような概念により、新しい画像を動的に作成して適切なリストに保存し、次に、フォームオブジェクトからそれらをすばやく取得して、その背景上に表示することができます。この場合、そのようなオブジェクトは、フォームの背景をその下に自動的に保存します。オブジェクトが削除、変更、または移動された場合、保存された背景が復元されます。

したがって、今回の記事では、前の記事で作成した描画フレームを少し修正し、基本アニメーションフレームオブジェクトのクラスを開発し、2つの子孫クラス(テキストアニメーションフレームと長方形アニメーションフレームクラス)を開発します。これらのフレームオブジェクトのリストを格納するためのクラスを作成し、フォームオブジェクトからそれらを操作する機能を提供しましょう。


ライブラリクラスの改善

まず、以前に作成したライブラリクラスを改善します。\MQL5\Include\DoEasy\Defines.mqhで、長方形アニメーションフレームクラスにアニメーションフレームのリスト描画された形状タイプのリストを追加します。

//+------------------------------------------------------------------+
//| Data for working with graphical element animation                |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| List of animation frame types                                    |
//+------------------------------------------------------------------+
enum ENUM_ANIMATION_FRAME_TYPE
  {
   ANIMATION_FRAME_TYPE_TEXT,                         // Text animation frame
   ANIMATION_FRAME_TYPE_QUAD,                         // Rectangle animation frame
  };
//+------------------------------------------------------------------+
//| List of drawn shape types                                        |
//+------------------------------------------------------------------+
enum ENUM_FIGURE_TYPE
  {
   FIGURE_TYPE_PIXEL,                                 // Pixel
   FIGURE_TYPE_PIXEL_AA,                              // Pixel with antialiasing
   
   FIGURE_TYPE_LINE_VERTICAL,                         // Vertical line
   FIGURE_TYPE_LINE_VERTICAL_THICK,                   // Vertical segment of a freehand line having a specified width using antialiasing algorithm
   
   FIGURE_TYPE_LINE_HORIZONTAL,                       // Horizontal line
   FIGURE_TYPE_LINE_HORIZONTAL_THICK,                 // Horizontal segment of a freehand line having a specified width using antialiasing algorithm
   
   FIGURE_TYPE_LINE,                                  // Arbitrary line
   FIGURE_TYPE_LINE_AA,                               // Line with antialiasing
   FIGURE_TYPE_LINE_WU,                               // Line with WU smoothing
   FIGURE_TYPE_LINE_THICK,                            // Segment of a freehand line having a specified width using antialiasing algorithm
   
   FIGURE_TYPE_POLYLINE,                              // Polyline
   FIGURE_TYPE_POLYLINE_AA,                           // Polyline with antialiasing
   FIGURE_TYPE_POLYLINE_WU,                           // Polyline with WU smoothing
   FIGURE_TYPE_POLYLINE_SMOOTH,                       // Polyline with a specified width using two smoothing algorithms
   FIGURE_TYPE_POLYLINE_THICK,                        // Polyline with a specified width using a smoothing algorithm    
   
   FIGURE_TYPE_POLYGON,                               // Polygon
   FIGURE_TYPE_POLYGON_FILL,                          // Filled polygon
   FIGURE_TYPE_POLYGON_AA,                            // Polygon with antialiasing
   FIGURE_TYPE_POLYGON_WU,                            // Polygon with WU smoothing
   FIGURE_TYPE_POLYGON_SMOOTH,                        // Polygon with a specified width using two smoothing algorithms
   FIGURE_TYPE_POLYGON_THICK,                         // Polygon with a specified width using a smoothing algorithm
   
   FIGURE_TYPE_RECTANGLE,                             // Rectangle
   FIGURE_TYPE_RECTANGLE_FILL,                        // Filled rectangle
   
   FIGURE_TYPE_CIRCLE,                                // Circle
   FIGURE_TYPE_CIRCLE_FILL,                           // Filled circle
   FIGURE_TYPE_CIRCLE_AA,                             // Circle with antialiasing
   FIGURE_TYPE_CIRCLE_WU,                             // Circle with WU smoothing
   
   FIGURE_TYPE_TRIANGLE,                              // Triangle
   FIGURE_TYPE_TRIANGLE_FILL,                         // Filled triangle
   FIGURE_TYPE_TRIANGLE_AA,                           // Triangle with antialiasing
   FIGURE_TYPE_TRIANGLE_WU,                           // Triangle with WU smoothing
   
   FIGURE_TYPE_ELLIPSE,                               // Ellipse
   FIGURE_TYPE_ELLIPSE_FILL,                          // Filled ellipse
   FIGURE_TYPE_ELLIPSE_AA,                            // Ellipse with antialiasing
   FIGURE_TYPE_ELLIPSE_WU,                            // Ellipse with WU smoothing
   
   FIGURE_TYPE_ARC,                                   // Ellipse arc
   FIGURE_TYPE_PIE,                                   // Ellipse sector
   
  };
//+------------------------------------------------------------------+

アニメーションフレームオブジェクトを識別するにはアニメーションフレームタイプ(テキスト、描画された形状、または次の記事で紹介するその他のアニメーションフレームタイプ)を使用します。描画される形状のタイプは、単一の長方形のアニメーションフレームに正確に描画されるものを示します。これらのタイプは、CCanvasクラスの既存の描画メソッド( クラスメソッドの表のデータアクセスプリミティブの描画塗りつぶされたプリミティブの描画アンチエイリアスを使用したプリミティブの描画セクション)に対応します。

\MQL5\Include\DoEasy\Data.mqhに、新しいメッセージインデックスを追加します

//--- CForm
   MSG_FORM_OBJECT_TEXT_NO_SHADOW_OBJ_FIRST_CREATE_IT,// No shadow object. Create it using the CreateShadowObj() method
   MSG_FORM_OBJECT_ERR_FAILED_CREATE_SHADOW_OBJ,      // Failed to create new shadow object
   MSG_FORM_OBJECT_ERR_FAILED_CREATE_PC_OBJ,          // Failed to create new pixel copier object
   MSG_FORM_OBJECT_PC_OBJ_ALREADY_IN_LIST,            // Pixel copier object with ID already present in the list 
   MSG_FORM_OBJECT_PC_OBJ_NOT_EXIST_LIST,             // No pixel copier object with ID in the list 

//--- CFrame
   MSG_FORM_OBJECT_ERR_FAILED_CREATE_FRAME,           // Failed to create a new animation frame object
   MSG_FORM_OBJECT_FRAME_ALREADY_IN_LIST,             // Animation frame object with ID already present in the list 
   MSG_FORM_OBJECT_FRAME_NOT_EXIST_LIST,              // Animation frame object with ID not present in the list 

//--- CShadowObj
   MSG_SHADOW_OBJ_IMG_SMALL_BLUR_LARGE,               // Error! Image size too small or blur too extensive

また、新しく追加したインデックスに対応するメッセージテキストも追加します

//--- CForm
   {"Отсутствует объект тени. Необходимо сначала его создать при помощи метода CreateShadowObj()","There is no shadow object. You must first create it using the CreateShadowObj () method"},
   {"Не удалось создать новый объект для тени","Failed to create new object for shadow"},
   {"Не удалось создать новый объект-копировщик пикселей","Failed to create new pixel copier object"},
   {"В списке уже есть объект-копировщик пикселей с идентификатором ","There is already a pixel copier object in the list with ID "},
   {"В списке нет объекта-копировщика пикселей с идентификатором ","No pixel copier object with ID "},
   
//--- CFrame
   {"Не удалось создать новый объект-кадр анимации","Failed to create new animation frame object"},
   {"В списке уже есть объект-кадр анимации с идентификатором ","The list already contains an animation frame object with an ID "},
   {"В списке нет объекта-кадра анимации с идентификатором ","No animation frame object with ID "},
   
//--- CShadowObj
   {"Ошибка! Размер изображения очень маленький или очень большое размытие","Error! Image size is very small or very large blur"},


ライブラリサービス関数ファイル(\MQL5\Include\DoEasy\Services\DELib.mqh)に、配列の最大値と最小値を返す関数を追加します。

//+------------------------------------------------------------------+
//| Return the maximum value in the array                            |
//+------------------------------------------------------------------+
template<typename T>
bool ArrayMaximumValue(const string source,const T &array[],T &max_value)
  {
   if(ArraySize(array)==0)
     {
      CMessage::ToLog(source,MSG_CANV_ELEMENT_ERR_EMPTY_ARRAY);
      return false;
     }
   max_value=0;
   int index=ArrayMaximum(array);
   if(index==WRONG_VALUE)
      return false;
   max_value=array[index];
   return true;
  }
//+------------------------------------------------------------------+
//| Return the minimum value in the array                            |
//+------------------------------------------------------------------+
template<typename T>
bool ArrayMinimumValue(const string source,const T &array[],T &min_value)
  {
   if(ArraySize(array)==0)
     {
      CMessage::ToLog(source,MSG_CANV_ELEMENT_ERR_EMPTY_ARRAY);
      return false;
     }
   min_value=0;
   int index=ArrayMinimum(array);
   if(index==WRONG_VALUE)
      return false;
   min_value=array[index];
   return true;
  }
//+------------------------------------------------------------------+

これらの関数は、リンクを介して渡された配列にある最大値または最小値を返します。関数からの戻り値は「無効な」値として配列セルに配置される可能性があるため、bool型です。たとえば、配列からデータを受信したときに-1が返される場合(多くの関数で行われるように)、そのような値は配列に設定されている値の1つにすることができます。有効な値(-1)が返された場合、プログラムはこれがエラーであると想定します。これは正しくありません。したがって、エラーが発生した場合はfalseを返し、配列で見つかった最大値または最小値はリンクを介して関数に渡された変数に設定されます。関数がtrueを返す場合、変数は目的の値を格納します。source変数は関数の呼び出し元メソッドの名前を受け取るため、エラーが発生した場合、関数の呼び出し元メソッドの名前とエラーメッセージを確認できます。

変数は、描画された形状タイプの説明を返す関数も受け取ります。

//+------------------------------------------------------------------+
//| Return the description of the drawn shape type                   |
//+------------------------------------------------------------------+
string FigureTypeDescription(const ENUM_FIGURE_TYPE figure_type)
  {
   return(StringSubstr(EnumToString(figure_type),12));
  }
//+------------------------------------------------------------------+

ここでは、列挙形式で関数に渡されたタイプが文字列での説明に変換されます。12番目の記号の位置からの部分文字列は、不要なテキストをトリミングするためにタイプテキスト表現から取得されます。たとえば、FIGURE_TYPE_TRIANGLEの形状タイプは「FIGURE_TYPE_TRIANGLE」に変換され、このテキストから12番目の記号から始まる必要な部分文字列「FIGURE_TYPE_ TRIANGLE 」が取得され、結果として「TRIANGLE」文字列が返されます。

前回の記事では、背景の一部を配列にコピーするメソッドを作成するときに、コピーされた背景の長方形のサイズと座標をフォームに表示されるテキストサイズによって定義しました。ここでは画像も表示します。それらのサイズは、テキストサイズによって定義されなくなるため、背景部分のコピーされた長方形の座標とサイズを定義するメソッドを作成する必要があります。

グラフィック要素クラスの\MQL5\Include\DoEasy\Objects\Graph\GCnvElement.mqhファイルで、メソッドの名前を変更します。

//--- Return coordinate offsets relative to the text anchor point
   void              TextGetShiftXY(const string text,            // Text for calculating the size of its outlining rectangle
                                    const ENUM_TEXT_ANCHOR anchor,// Text anchor point, relative to which the offsets are calculated
                                    int &shift_x,                 // X coordinate of the rectangle upper left corner
                                    int &shift_y);                // Y coordinate of the rectangle upper left corner

現在、このメソッドはGetShiftXYbyText()と呼ばれています。画像のコピーされた部分の座標とサイズをオブジェクトのアンカーポイントを基準にして指定されたサイズで返す新しいメソッドを宣言します

//--- Return coordinate offsets relative to the text anchor point by text
   void              GetShiftXYbyText(const string text,             // Text for calculating the size of its outlining rectangle
                                      const ENUM_TEXT_ANCHOR anchor, // Text anchor point, relative to which the offsets are calculated
                                      int &shift_x,                  // X coordinate of the rectangle upper left corner
                                      int &shift_y);                 // Y coordinate of the rectangle upper left corner
//--- Return coordinate offsets relative to the rectangle anchor point by size
   void              GetShiftXYbySize(const int width,               //Rectangle size by width
                                      const int height,              //Rectangle size by height
                                      const ENUM_TEXT_ANCHOR anchor, // Rectangle anchor point, relative to which the offsets are calculated
                                      int &shift_x,                  // X coordinate of the rectangle upper left corner
                                      int &shift_y);                 // Y coordinate of the rectangle upper left corner

クラスの最後に実装します。

以下は、サイズごとに長方形のアンカーポイントを基準にした座標オフセットを返すメソッドです。

//+------------------------------------------------------------------+
//| Return coordinate offsets relative to the rectangle anchor point |
//| by size                                                          |
//+------------------------------------------------------------------+
void CGCnvElement::GetShiftXYbySize(const int width,const int height,const ENUM_TEXT_ANCHOR anchor,int &shift_x,int &shift_y)
  {
   switch(anchor)
     {
      case TEXT_ANCHOR_LEFT_TOP        :  shift_x=0;        shift_y=0;           break;
      case TEXT_ANCHOR_LEFT_CENTER     :  shift_x=0;        shift_y=-height/2;   break;
      case TEXT_ANCHOR_LEFT_BOTTOM     :  shift_x=0;        shift_y=-height;     break;
      case TEXT_ANCHOR_CENTER_TOP      :  shift_x=-width/2; shift_y=0;           break;
      case TEXT_ANCHOR_CENTER          :  shift_x=-width/2; shift_y=-height/2;   break;
      case TEXT_ANCHOR_CENTER_BOTTOM   :  shift_x=-width/2; shift_y=-height;     break;
      case TEXT_ANCHOR_RIGHT_TOP       :  shift_x=-width;   shift_y=0;           break;
      case TEXT_ANCHOR_RIGHT_CENTER    :  shift_x=-width;   shift_y=-height/2;   break;
      case TEXT_ANCHOR_RIGHT_BOTTOM    :  shift_x=-width;   shift_y=-height;     break;
      default                          :  shift_x=0;        shift_y=0;           break;
     }
  }
//+------------------------------------------------------------------+

ここでは、コピーされた領域の幅と高さ、およびメソッドに渡されたアンカーポイントに応じて、アンカーポイントを基準にした座標オフセットを計算し、リンクを介してメソッドに渡された変数に書き込みます。

以下は、テキストアンカーポイントを基準にした座標オフセットを返すメソッドです。

//+------------------------------------------------------------------+
//| Return coordinate offsets relative to the text anchor point      |
//+------------------------------------------------------------------+
void CGCnvElement::GetShiftXYbyText(const string text,const ENUM_TEXT_ANCHOR anchor,int &shift_x,int &shift_y)
  {
   int tw=0,th=0;
   this.TextSize(text,tw,th);
   this.GetShiftXYbySize(tw,th,anchor,shift_x,shift_y);
  }
//+------------------------------------------------------------------+

ここでは、まずメソッドに渡されるテキストのサイズを定義して、 保存されたフォームの背景画像領域の座標オフセットを定義するために上記のメソッドを呼び出します 。

前回の記事では、フォームの背景画像の一部をコピーしてその後配列から復元するためのクラスを開発しました。クラスは、フォームオブジェクトクラスファイルで設定されました。次に、フォームオブジェクトクラスファイルからクラスを削除して、新しく作成されたフレームオブジェクトクラスの新しいファイルに再配置します(クラスを別々のファイルに書き込んで保存する方がよいことがわかりました)。

単一のアニメーションフレームの基本クラスを作成しましょう。このクラスには、そのすべての子孫に共通のプロパティが含まれます。

「アニメーションフレーム」オブジェクトクラス

\MQL5\Include\DoEasy\Objects\Graph\で、新しいAnimations\フォルダーとCFrameクラスのFrame.mqhファイルを作成します。

クラスファイルにグラフィック要素オブジェクトクラスのファイルをインクルードします

//+------------------------------------------------------------------+
//|                                                        Frame.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\GCnvElement.mqh"
//+------------------------------------------------------------------+

次に、フォームオブジェクトクラスファイルから削除したピクセルコピーオブジェクトクラスを配置します(前の記事で検討しました)。

//+------------------------------------------------------------------+
//|                                                        Frame.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\GCnvElement.mqh"
//+------------------------------------------------------------------+
//| Pixel copier class                                               |
//+------------------------------------------------------------------+
class CPixelCopier : public CObject
  {
protected:
   CGCnvElement     *m_element;                             // Pointer to the graphical element
   uint              m_array[];                             // Pixel array
   int               m_id;                                  // ID
   int               m_x;                                   // X coordinate of the upper left corner
   int               m_y;                                   // Y coordinate of the upper left corner
   int               m_w;                                   // Copied image width
   int               m_h;                                   // Copied image height
   int               m_wr;                                  // Calculated copied image width
   int               m_hr;                                  // Calculated copied image height
public:
//--- Compare CPixelCopier objects by a specified property (to sort the list by an object property)
   virtual int       Compare(const CObject *node,const int mode=0) const
                       {
                        const CPixelCopier *obj_compared=node;
                        return(mode==0 ? (this.ID()>obj_compared.ID() ? 1 : this.ID()<obj_compared.ID() ? -1 : 0) : WRONG_VALUE);
                       }
   
//--- Set the properties
   void              SetElement(CGCnvElement *element)         { this.m_element=element;  }
   void              SetID(const int id)                       { this.m_id=id;            }
   void              SetCoordX(const int value)                { this.m_x=value;          }
   void              SetCoordY(const int value)                { this.m_y=value;          }
   void              SetWidth(const int value)                 { this.m_w=value;          }
   void              SetHeight(const int value)                { this.m_h=value;          }
//--- Get the properties
   int               ID(void)                            const { return this.m_id;        }
   int               CoordX(void)                        const { return this.m_x;         }
   int               CoordY(void)                        const { return this.m_y;         }
   int               Width(void)                         const { return this.m_w;         }
   int               Height(void)                        const { return this.m_h;         }
   int               WidthReal(void)                     const { return this.m_wr;        }
   int               HeightReal(void)                    const { return this.m_hr;        }

//--- Copy the part or the entire image to the array
   bool              CopyImgDataToArray(const uint x_coord,const uint y_coord,uint width,uint height);
//--- Copy the part or the entire image from the array to the canvas
   bool              CopyImgDataToCanvas(const int x_coord,const int y_coord);

//--- Constructors
                     CPixelCopier (void){;}
                     CPixelCopier (const int id,
                                   const int x,
                                   const int y,
                                   const int w,
                                   const int h,
                                   CGCnvElement *element) : m_id(id), m_x(x),m_y(y),m_w(w),m_wr(w),m_h(h),m_hr(h) { this.m_element=element; }
                    ~CPixelCopier (void){;}
  };
//+------------------------------------------------------------------+
//| Copy part or all of the image to the array                       |
//+------------------------------------------------------------------+
bool CPixelCopier::CopyImgDataToArray(const uint x_coord,const uint y_coord,uint width,uint height)
  {
//--- Assign coordinate values, passed to the method, to the variables
   int x1=(int)x_coord;
   int y1=(int)y_coord;
//--- If X coordinates goes beyond the form on the right or Y coordinate goes beyond the form at the bottom,
//--- there is nothing to copy, the copied area is outside the form. Return 'false'
   if(x1>this.m_element.Width()-1 || y1>this.m_element.Height()-1)
      return false;
//--- Assign the width and height values of the copied area to the variables
//--- If the passed width and height are equal to zero, assign the form width and height to them
   this.m_wr=int(width==0  ? this.m_element.Width()  : width);
   this.m_hr=int(height==0 ? this.m_element.Height() : height);

//--- If X and Y coordinates are equal to zero (the upper left corner of the form), as well as the width and height are equal to the form width and height,
//--- the copied area is equal to the entire form area. Copy the entire form (returning it from the method) using the ImageCopy() method
   //if(x1==0 && y1==0 && this.m_wr==this.m_element.Width() && this.m_hr==this.m_element.Height())
   //   return this.m_element.ImageCopy(DFUN,this.m_array);

//--- Calculate the right X coordinate and lower Y coordinate of the rectangle area
   int x2=int(x1+this.m_wr-1);
   int y2=int(y1+this.m_hr-1);
//--- If the calculated X coordinate goes beyond the form, the right edge of the form will be used as the coordinate
   if(x2>=this.m_element.Width()-1)
      x2=this.m_element.Width()-1;
//--- If the calculated Y coordinate goes beyond the form, the bottom edge of the form will be used as the coordinate
   if(y2>=this.m_element.Height()-1)
      y2=this.m_element.Height()-1;
//--- Calculate the copied width and height
   this.m_wr=x2-x1+1;
   this.m_hr=y2-y1+1;
//--- Define the necessary size of the array, which is to store all image pixels with calculated width and height
   int size=this.m_wr*this.m_hr;
//--- If failed to set the array size, inform of that and return 'false'
   if(::ArrayResize(this.m_array,size)!=size)
     {
      CMessage::ToLog(DFUN,MSG_LIB_SYS_FAILED_ARRAY_RESIZE,true);
      return false;
     }
//--- Set the index in the array for recording the image pixel
   int n=0;
//--- In a loop by the calculated height of the copied area, starting from the specified Y coordinate
   for(int y=y1;y<y1+this.m_hr;y++)
     {
      //--- in a loop by the calculated width of the copied area, starting from the specified X coordinate
      for(int x=x1;x<x1+this.m_wr;x++)
        {
         //--- Copy the next image pixel to the array and increase the array index
         this.m_array[n]=this.m_element.GetCanvasObj().PixelGet(x,y);
         n++;
        }
     }
//--- Successful - return 'true'
   return true;
  }
//+------------------------------------------------------------------+
//| Copy the part or the entire image from the array to the canvas   |
//+------------------------------------------------------------------+
bool CPixelCopier::CopyImgDataToCanvas(const int x_coord,const int y_coord)
  {
//--- If the array of saved pixels is empty, inform of that and return 'false'
   int size=::ArraySize(this.m_array);
   if(size==0)
     {
      CMessage::ToLog(DFUN,MSG_CANV_ELEMENT_ERR_EMPTY_ARRAY,true);
      return false;
     }
//--- Set the index of the array for reading the image pixel
   int n=0;
//--- In a loop by the previously calculated height of the copied area, starting from the specified Y coordinate
   for(int y=y_coord;y<y_coord+this.m_hr;y++)
     {
      //--- in a loop by the previously calculated width of the copied area, starting from the specified X coordinate
      for(int x=x_coord;x<x_coord+this.m_wr;x++)
        {
         //--- Restore the next image pixel from the array and increase the array index
         this.m_element.GetCanvasObj().PixelSet(x,y,this.m_array[n]);
         n++;
        }
     }
   return true;
  }
//+------------------------------------------------------------------+

ここで(一時的に)変更されたのは、以前に保存したフォーム画像全体をコピーする必要があるコード文字列をコメントアウトしたという事実だけです。ここにエラーがあり、フォームオブジェクト配列からではなく、グラフィカルリソースから背景が直接コピーされました。グラフィカルリソースには、フォームの背景画像に適用されたすべての変更が含まれています。これを修正するには、元のフォーム画像のコピーを特徴とする別の配列にフォームの外観を保存する必要があります。すでにそのような配列がありますが、作成直後に元のフォームの外観を保存するためのメソッドを作成する必要があります。それまで、これらの文字列をコメントアウトしました。フォームの背景の一部ではなく全体のサイズの背景は、フォームの背景の一部を復元するループで復元されます(つまり、ある配列を別の配列にコピーするのではなく、フォームの背景要素を要素ごとに入力することによって) フォームの背景画像の一部の保存されたコピーを格納する配列)。

次に、ピクセルコピークラスの後に、アニメーションフレームオブジェクトクラスの本体を記述します。

//+------------------------------------------------------------------+
//| Single animation frame class                                     |
//+------------------------------------------------------------------+
class CFrame : public CPixelCopier
  {
protected:
   ENUM_ANIMATION_FRAME_TYPE m_frame_figure_type;           // Type of the figure drawn by the frame
   ENUM_TEXT_ANCHOR  m_anchor_last;                         // Last frame anchor point
   double            m_x_last;                              // X coordinate of the upper left corner of the last frame
   double            m_y_last;                              // Y coordinate of the upper left corner of the last frame
   int               m_shift_x_prev;                        // Offset of the X coordinate of the last frame upper left corner
   int               m_shift_y_prev;                        // Offset of the Y coordinate of the last frame upper left corner
public:
//--- Return the last (1) anchor point, (2) X and (3) Y coordinate,
//--- previous offset by (4) X and (5) Y, (6) type of the figure drawn by the frame
   ENUM_TEXT_ANCHOR  LastAnchor(void)                 const { return this.m_anchor_last;        }
   double            LastX(void)                      const { return this.m_x_last;             }
   double            LastY(void)                      const { return this.m_y_last;             }
   int               LastShiftX(void)                 const { return this.m_shift_x_prev;       }
   int               LastShiftY(void)                 const { return this.m_shift_y_prev;       }
   ENUM_ANIMATION_FRAME_TYPE FrameFigureType(void)    const { return this.m_frame_figure_type;  }
   
//--- Default constructor
                     CFrame();
protected:
//--- Text frame constructor
                     CFrame(const int id,
                            const int x,
                            const int y,
                            const string text,
                            CGCnvElement *element);
//--- Rectangle frame constructor
                     CFrame(const int id,
                            const int x,
                            const int y,
                            const int w,
                            const int h,
                            CGCnvElement *element);
  };
//+------------------------------------------------------------------+

クラスはピクセルコピーオブジェクトクラスから派生しているため、実際には、ピクセルコピーオブジェクトクラスです。

クラスで宣言されたすべての変数とメソッドはコメントで説明されています。このクラスは他のアニメーションフレームクラスの基本であるため、子孫に共通するすべてのプロパティとメソッドをここで設定します。

画像を復元するときに画像の前に保存した部分の座標を定義できるように、最後の座標、オフセット、アンカーポイントを返す変数とメソッドが必要です。これらの座標は、その上に描画された画像によって消去された保存済みの背景を配置するために使用されます。

このクラスは3つのコンストラクタを備えています。

  1. デフォルトのpublicコンストラクタ
  2. protectedテキストフレームオブジェクトコンストラクタ
  3. protected長方形フレームオブジェクトコンストラクタ

protectedコンストラクタの実装について考えてみましょう。

以下は、長方形フレームのコンストラクタです。

//+------------------------------------------------------------------+
//| Constructor of rectangle frames                                  |
//+------------------------------------------------------------------+
CFrame::CFrame(const int id,const int x,const int y,const int w,const int h,CGCnvElement *element) : CPixelCopier(id,x,y,w,h,element)
  {
   this.m_frame_figure_type=ANIMATION_FRAME_TYPE_QUAD;
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=x;
   this.m_y_last=y;
   this.m_shift_x_prev=0;
   this.m_shift_y_prev=0;
  }
//+------------------------------------------------------------------+

コンストラクタは、作成された長方形フレームオブジェクトのID、X座標とY座標、フレームの幅と高さ、および新しいオブジェクトが作成されたグラフィック要素オブジェクトへのポインタを受け取ります。クラスはピクセルコピーオブジェクトの子孫であるため、必要なすべてのパラメータをコンストラクタ初期化リストの基本クラスコンストラクタに渡します。これらのパラメータは、コンストラクタ引数に渡されるプロパティのすべてです。
デフォルトパラメータをクラス本体のすべてのクラスメンバー変数に設定します。

以下は、テキストフレームのコンストラクタです。

//+------------------------------------------------------------------+
//| The constructor of text frames                                   |
//+------------------------------------------------------------------+
CFrame::CFrame(const int id,
               const int x,
               const int y,
               const string text,
               CGCnvElement *element)
  {
   int w=0,h=0;
   this.m_element=element;
   this.m_element.GetCanvasObj().TextSize(text,w,h);
   this.m_anchor_last=this.m_element.TextAnchor();
   this.m_frame_figure_type=ANIMATION_FRAME_TYPE_TEXT;
   this.m_x_last=x;
   this.m_y_last=y;
   this.m_shift_x_prev=0;
   this.m_shift_y_prev=0;
   CPixelCopier::SetID(id);
   CPixelCopier::SetCoordX(x);
   CPixelCopier::SetCoordY(y);
   CPixelCopier::SetWidth(w);
   CPixelCopier::SetHeight(h);
  }
//+------------------------------------------------------------------+

コンストラクタは、作成されたテキストフレームオブジェクトのID、そのX座標とY座標、テキスト、および新しいオブジェクトが作成されたグラフィック要素オブジェクトへのポインタを受け取ります。
クラス本体で、最初にテキストサイズを定義し、次にクラスメンバー変数のデフォルト値を設定し、作成されたオブジェクトのID、その座標、およびテキストサイズを親ピクセルコピーオブジェクトに設定します。

アニメーションフレームオブジェクトクラスの子孫のオブジェクトのクラスを作成します。

テキストアニメーションフレームクラス

\MQL5\Include\DoEasy\Objects\Graph\Animations\で、CFrameTextクラスの新しいFrameText.mqhファイルを作成します。

アニメーションフレームクラスのファイルをファイルにインクルードする必要がありますが、クラス自体はその子孫である必要があります

//+------------------------------------------------------------------+
//|                                                    FrameText.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "Frame.mqh"
//+------------------------------------------------------------------+
//| Single text animation frame class                                |
//+------------------------------------------------------------------+
class CFrameText : public CFrame
  {
private:

public:
//--- Display the text on the background while saving and restoring the background
   bool              TextOnBG(const string text,const int x,const int y,const ENUM_TEXT_ANCHOR anchor,const color clr,const uchar opacity,bool redraw=false);

//--- Constructors
                     CFrameText() {;}
                     CFrameText(const int id,CGCnvElement *element) : CFrame(id,0,0,"",element) {}
  };
//+------------------------------------------------------------------+

ここには、フォームオブジェクトの背景にテキストを描画するための1つのpublicメソッド 2つのコンストラクタ(デフォルトとパラメトリックコンストラクタ)があります。

パラメトリックコンストラクタは、作成されたテキストアニメーションフレームオブジェクトのIDと、オブジェクトが作成されたグラフィック要素へのポインタを受け取ります。初期化リストでは、親クラスはコンストラクタ引数で渡されたID、座標とテキストのデフォルト値、およびコンストラクタ引数で渡されたグラフィック要素へのポインタを受け取ります。

以下は、背景を保存および復元しながら背景にテキストを表示するメソッドです。

//+-------------------------------------------------------------------------------+
//| Display the text on the background, while saving and restoring the background |
//+-------------------------------------------------------------------------------+
bool CFrameText::TextOnBG(const string text,const int x,const int y,const ENUM_TEXT_ANCHOR anchor,const color clr,const uchar opacity,bool redraw=false)
  {
//--- Find out the width and height of the text outlining the rectangle (to be used as the size of the saved area)
   int w=0,h=0;
   this.m_element.TextSize(text,w,h);
//--- Calculate coordinate offsets for the saved area depending on the text anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(w,h,anchor,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the text has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If a background area with calculated coordinates and size under the future text is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(x+shift_x,y+shift_y,w,h))
      return false;
//--- Draw the text and update the element
   this.m_element.Text(x,y,text,clr,opacity,anchor);
   this.m_element.Update(redraw);
   this.m_anchor_last=anchor;
   this.m_x_last=x;
   this.m_y_last=y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

メソッドのロジックについては、コードコメントで詳しく説明されています。前回の記事でテスト中にすでに検討した(テストEAのOnChartEvent()ハンドラで同様のロジックが設定されました)ため、ここではすべてが明確であると思います。フォームにテキストが描画された後、そのアンカーポイント、X座標とY座標、およびアンカーポイントを基準にしたオフセット値が、親クラスの変数に設定されて、テキストで上書きされたフォーム画像の背景を復元するために使用されます。

次に、アニメーションフレームオブジェクトの2番目の子孫クラスを作成しましょう。

長方形アニメーションフレームクラス

\MQL5\Include\DoEasy\Objects\Graph\Animations\で、CFrameQuadクラスの新しいFrameQuad.mqhファイルを作成します。

親クラスファイルとクラスファイルにインクルードします(およびクラスファイルから派生します)。

//+------------------------------------------------------------------+
//|                                                    FrameQuad.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "Frame.mqh"
//+------------------------------------------------------------------+
//| Single sprite animation frame class                              |
//+------------------------------------------------------------------+
class CFrameQuad : public CFrame
  {
private:
   double            m_quad_x;                                 // X coordinate of the rectangle enclosing the shape
   double            m_quad_y;                                 // Y coordinate of the rectangle enclosing the shape
   uint              m_quad_width;                             // Width of the rectangle enclosing the shape
   uint              m_quad_height;                            // Height of the rectangle enclosing the shape
   
public:

//--- Constructors
                     CFrameQuad() {;}
                     CFrameQuad(const int id,CGCnvElement *element) : CFrame(id,0,0,0,0,element) { this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;   }

//+------------------------------------------------------------------+

クラスのprivateセクションで、描画された形状を囲む長方形の座標とサイズを格納するクラスメンバー変数を宣言します。これらは、描画された形状によって上書きされた、保存された背景パーツの画像領域の座標とサイズです。

パラメトリックコンストラクタは、作成されたオブジェクトのIDと、オブジェクトが作成されたグラフィック要素へのポインタを受け取ります。メソッド引数で渡されるID、デフォルトの座標とフレームサイズのパラメータ、およびグラフィック要素へのポインタは、コンストラクタ初期化リストの親クラスコンストラクタに渡されます。コンストラクタ本体で、描画した形状のアンカーポイントを「左上」に設定します。これは、コピーされた領域のオフセットを計算するために必要です。この値では、XおよびY座標オフセットのアンカーポイントはゼロに等しくなります。

CCanvasクラスには多数の描画メソッドがあるため、フォームオブジェクトの背景に形状を描画するためのすべての適切なメソッドはクラスのpublicセクションで宣言され、背景の復元が続きます。

public:

//--- Constructors
                     CFrameQuad() {;}
                     CFrameQuad(const int id,CGCnvElement *element) : CFrame(id,0,0,0,0,element) { this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;   }

//+------------------------------------------------------------------+
//| Drawing primitives while saving and restoring the background     |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Methods of drawing primitives without smoothing                  |
//+------------------------------------------------------------------+
//--- Set the color of the dot with the specified coordinates
   bool              SetPixelOnBG(const int x,const int y,const color clr,const uchar opacity=255,const bool redraw=false);
                       
//--- Draw a segment of a vertical line
   bool              DrawLineVerticalOnBG(const int x,                  // X coordinate of the segment
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a segment of a horizontal line
   bool              DrawLineHorizontalOnBG(const int x1,               // X coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y,                            // Segment Y coordinate
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a segment of a freehand line
   bool              DrawLineOnBG(const int x1,                         // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a polyline
   bool              DrawPolylineOnBG(int &array_x[],                   // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a polygon
   bool              DrawPolygonOnBG(int  &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a rectangle using two points
   bool              DrawRectangleOnBG(const int x1,                    // X coordinate of the first point defining the rectangle
                              const int   y1,                           // Y coordinate of the first point defining the rectangle
                              const int   x2,                           // X coordinate of the second point defining the rectangle
                              const int   y2,                           // Y coordinate of the second point defining the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a circle
   bool              DrawCircleOnBG(const int x,                        // X coordinate of the circle center
                              const int   y,                            // Y coordinate of the circle center
                              const int   r,                            // Circle radius
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a triangle
   bool              DrawTriangleOnBG(const int x1,                     // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw an ellipse using two points
   bool              DrawEllipseOnBG(const int x1,                      // X coordinate of the first point defining the ellipse
                              const int   y1,                           // Y coordinate of the first point defining the ellipse
                              const int   x2,                           // X coordinate of the second point defining the ellipse
                              const int   y2,                           // Y coordinate of the second point defining the ellipse
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw an arc of an ellipse inscribed in a rectangle with corners at (x1,y1) and (x2,y2).
//--- The arc boundaries are clipped by lines from the center of the ellipse, which extend to two points with coordinates (x3,y3) and (x4,y4)
   bool              DrawArcOnBG(const int x1,                          // X coordinate of the top left corner forming the rectangle
                              const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                              const int   x3,                           // X coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   y3,                           // Y coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   x4,                           // X coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   y4,                           // Y coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled sector of an ellipse inscribed in a rectangle with corners at (x1,y1) and (x2,y2).
//--- The sector boundaries are clipped by lines from the center of the ellipse, which extend to two points with coordinates (x3,y3) and (x4,y4)
   bool              DrawPieOnBG(const int x1,                          // X coordinate of the upper left corner of the rectangle
                              const int   y1,                           // Y coordinate of the upper left corner of the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner of the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner of the rectangle
                              const int   x3,                           // X coordinate of the first point to find the arc boundaries
                              const int   y3,                           // Y coordinate of the first point to find the arc boundaries
                              const int   x4,                           // X coordinate of the second point to find the arc boundaries
                              const int   y4,                           // Y coordinate of the second point to find the arc boundaries
                              const color clr,                          // Line color
                              const color fill_clr,                     // Fill color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//+------------------------------------------------------------------+
//| Methods of drawing filled primitives without smoothing           |
//+------------------------------------------------------------------+
//--- Fill in the area
   bool              FillOnBG(const int   x,                            // X coordinate of the filling start point
                              const int   y,                            // Y coordinate of the filling start point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const uint  threshould=0,                 // Threshold
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled rectangle
   bool              DrawRectangleFillOnBG(const int x1,                // X coordinate of the first point defining the rectangle
                              const int   y1,                           // Y coordinate of the first point defining the rectangle
                              const int   x2,                           // X coordinate of the second point defining the rectangle
                              const int   y2,                           // Y coordinate of the second point defining the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag

//--- Draw a filled circle
   bool              DrawCircleFillOnBG(const int x,                    // X coordinate of the circle center
                              const int   y,                            // Y coordinate of the circle center
                              const int   r,                            // Circle radius
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled triangle
   bool              DrawTriangleFillOnBG(const int x1,                 // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled polygon
   bool              DrawPolygonFillOnBG(int &array_x[],                // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled ellipse inscribed in a rectangle with the specified coordinates
   bool              DrawEllipseFillOnBG(const int x1,                  // X coordinate of the top left corner forming the rectangle
                              const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false);                // Chart redraw flag
                       
//+------------------------------------------------------------------+
//| Methods of drawing primitives using smoothing                    |
//+------------------------------------------------------------------+
//--- Draw a point using AntiAliasing algorithm
   bool              SetPixelAAOnBG(const double x,                     // Point X coordinate
                              const double y,                           // Point Y coordinate
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   redraw=false);               // Chart redraw flag
                       
//--- Draw a segment of a freehand line using AntiAliasing algorithm
   bool              DrawLineAAOnBG(const int x1,                       // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a segment of a freehand line using Wu algorithm
   bool              DrawLineWuOnBG(const int x1,                       // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draws a segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawLineThickOnBG(const int x1,                    // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const int   size,                         // Line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // Line style is one of the ENUM_LINE_END enumeration's values
 
//--- Draw a vertical segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawLineThickVerticalOnBG(const int x,             // X coordinate of the segment
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   y2,                           // Y coordinate of the segment second point
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a horizontal segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawLineThickHorizontalOnBG(const int x1,          // X coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y,                            // Segment Y coordinate
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Line style is one of the ENUM_LINE_END enumeration's values

//--- Draws a polyline using AntiAliasing algorithm
   bool              DrawPolylineAAOnBG(int &array_x[],                 // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draws a polyline using Wu algorithm
   bool              DrawPolylineWuOnBG(int &array_x[],                 // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a polyline with a specified width consecutively using two antialiasing algorithms.
//--- First, individual line segments are smoothed based on Bezier curves.
//--- Then, the raster antialiasing algorithm is applied to the polyline built from these segments to improve the rendering quality
   bool              DrawPolylineSmoothOnBG(const int &array_x[],       // Array with the X coordinates of polyline points
                              const int    &array_y[],                  // Array with the Y coordinates of polyline points
                              const int    size,                        // Line width
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const double tension=0.5,                 // Smoothing parameter value
                              const double step=10,                     // Approximation step
                              const bool   redraw=false,                // Chart redraw flag
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END   end_style=LINE_END_ROUND);// Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a polyline having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawPolylineThickOnBG(const int &array_x[],        // Array with the X coordinates of polyline points
                              const int      &array_y[],                // Array with the Y coordinates of polyline points
                              const int      size,                      // Line width
                              const color    clr,                       // Color
                              const uchar    opacity=255,               // Opacity
                              const bool     redraw=false,              // Chart redraw flag
                              const uint     style=STYLE_SOLID,         // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              ENUM_LINE_END  end_style=LINE_END_ROUND); // Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a polygon using AntiAliasing algorithm
   bool              DrawPolygonAAOnBG(int &array_x[],                  // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a polygon using Wu algorithm
   bool              DrawPolygonWuOnBG(int &array_x[],                  // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a polygon with a specified width consecutively using two smoothing algorithms.
//--- First, individual segments are smoothed based on Bezier curves.
//--- Then, the raster smoothing algorithm is applied to the polygon built from these segments to improve the rendering quality. 
   bool              DrawPolygonSmoothOnBG(int &array_x[],              // Array with the X coordinates of polyline points
                              int          &array_y[],                  // Array with the Y coordinates of polyline points
                              const int    size,                        // Line width
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const double tension=0.5,                 // Smoothing parameter value
                              const double step=10,                     // Approximation step
                              const bool   redraw=false,                // Chart redraw flag
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END   end_style=LINE_END_ROUND);// Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a polygon having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawPolygonThickOnBG(const int &array_x[],         // array with the X coordinates of polygon points
                              const int   &array_y[],                   // array with the Y coordinates of polygon points
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // line style
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // line ends style
                       
//--- Draw a triangle using AntiAliasing algorithm
   bool              DrawTriangleAAOnBG(const int x1,                   // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a triangle using Wu algorithm
   bool              DrawTriangleWuOnBG(const int x1,                   // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a circle using AntiAliasing algorithm
   bool              DrawCircleAAOnBG(const int x,                      // X coordinate of the circle center
                              const int    y,                           // Y coordinate of the circle center
                              const double r,                           // Circle radius
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX);             // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a circle using Wu algorithm
   bool              DrawCircleWuOnBG(const int x,                      // X coordinate of the circle center
                              const int    y,                           // Y coordinate of the circle center
                              const double r,                           // Circle radius
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX);             // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw an ellipse by two points using AntiAliasing algorithm
   bool              DrawEllipseAAOnBG(const double x1,                 // X coordinate of the first point defining the ellipse
                              const double y1,                          // Y coordinate of the first point defining the ellipse
                              const double x2,                          // X coordinate of the second point defining the ellipse
                              const double y2,                          // Y coordinate of the second point defining the ellipse
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX);             // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw an ellipse by two points using Wu algorithm
   bool              DrawEllipseWuOnBG(const int x1,                    // X coordinate of the first point defining the ellipse
                              const int   y1,                           // Y coordinate of the first point defining the ellipse
                              const int   x2,                           // X coordinate of the second point defining the ellipse
                              const int   y2,                           // Y coordinate of the second point defining the ellipse
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  };
//+------------------------------------------------------------------+

これらの各メソッドの実装は、同様の描画メソッドの実装と同様です。ただし、ほとんどすべての描画メソッドには固有のニュアンスがあります(2つの類似した描画メソッドの保存領域のサイズは、それぞれの特徴によって異なる場合があります)。

これらのメソッドの実装を見てみましょう。

以下は、指定された座標で点の色を設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the color of the dot with the specified coordinates          |
//+------------------------------------------------------------------+
bool CFrameQuad::SetPixelOnBG(const int x,const int y,const color clr,const uchar opacity=255,const bool redraw=false)
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=1;
   this.m_quad_height=1;
   
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If a background area with calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.SetPixel(x,y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

メソッドのロジックは、コードで十分に詳細にコメントされています。もっと満遍なく考えてみましょう。ここでは、まず背景の長方形領域の左上端のX座標とY座標を設定して、描画された点の下で後に背景を復元するのに備えて配列に保存します。これはドット(1ピクセルの画像)のみであるため、保存された領域の座標は描画されたドットの座標と一致し、サイズは1ピクセルのサイズ(1 x 1)と一致します。

次に、背景が以前に保存されているかどうかを確認します(背景保存先の配列サイズがゼロ以外)。保存されている場合、以前に保存したフォームオブジェクトの背景を復元します(復元された領域の座標とサイズはクラス変数ですでに設定されています)。背景が正常に復元されたら、フォームの背景をドットの新しい座標で保存し、ドットを描画します。新しく描画されたドットによって消去された背景を後で復元するために、新しい座標、保存された領域のサイズ、シフトをクラス変数に保存します。

以下は、垂直線の線分を描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a segment of a vertical line                                |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineVerticalOnBG(const int   x,              // X coordinate of the segment
                                      const int   y1,             // Y coordinate of the segment first point
                                      const int   y2,             // Y coordinate of the segment second point
                                      const color clr,            // Color
                                      const uchar opacity=255,    // Opacity
                                      const bool  redraw=false)   // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=x;
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawLineVertical(x,y1,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

ここで、形状の輪郭を描く長方形の座標とサイズの計算は、前のメソッドとは異なります。1ピクセルの幅で垂直線を引くので、これは自然なことです。線の高さは、線の2つのY座標の最大値と最小値の差として計算する必要があります。保存領域のY座標は、2つのY座標の最小値(描画された線の上の点)に対応します。

以下は、水平線の線分を描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a segment of a horizontal line                              |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineHorizontalOnBG(const int   x1,           // X coordinate of the segment first point
                                        const int   x2,           // X coordinate of the segment second point
                                        const int   y,            // Segment Y coordinate
                                        const color clr,          // Color
                                        const uchar opacity=255,  // Opacity
                                        const bool  redraw=false) // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawLineHorizontal(x1,x2,y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

ここで、座標と保存領域のサイズの計算は、これが水平線であり、ここでの高さが1ピクセルに等しいことを除いて、前のメソッドでの同じ計算と同様です。 保存された領域の幅とX座標を計算する必要があります。

以下は、フリーハンドの線分を描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a segment of a freehand line                                |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineOnBG(const int   x1,            // X coordinate of the segment first point
                              const int   y1,            // Y coordinate of the segment first point
                              const int   x2,            // X coordinate of the segment second point
                              const int   y2,            // Y coordinate of the segment second point
                              const color clr,           // Color
                              const uchar opacity=255,   // Opacity
                              const bool  redraw=false)  // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawLine(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

ここで、保存された領域の座標とサイズは、描画された線の座標に基づいて計算されます

以下は、ポリラインを描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a polyline                                                  |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineOnBG(int         &array_x[],   // Array with the X coordinates of polyline points
                                  int         &array_y[],   // Array with the Y coordinates of polyline points
                                  const color clr,          // Color
                                  const uchar opacity=255,  // Opacity
                                  const bool  redraw=false) // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;

//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolyline(array_x,array_y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

ここで、座標と保存領域のサイズの計算の背後にある考え方は、上記で検討したメソッドと同じです。ただし、ポリライン(および他の多くの形状)の場合、折れ目の数や座標の数を知ることができないため、座標は変数の形式ではなく配列で渡されるため、実行は異なります。事前にメソッド引数に渡されます。これが、メソッドを呼び出す前に、2つの配列にX座標と各折れ目のドットの適切なY座標を入力する必要がある理由です。
このメソッドでは、以前に検討した関数を使用して配列から最大値と最小値を受け取り、関数に渡された配列から最小値または最大値を返します。得られた値は、保存されたフォームの背景領域の座標とサイズを計算するために使用されます。

以下は、平滑化を使用しない残りの形状描画メソッドです(座標の計算と保存された領域のサイズに注意してください )。

//+------------------------------------------------------------------+
//| Draw the rectangle                                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonOnBG(int         &array_x[],    // Array with the X coordinates of polygon points
                                 int         &array_y[],    // Array with the Y coordinates of polygon points
                                 const color clr,           // Color
                                 const uchar opacity=255,   // Opacity
                                 const bool  redraw=false)  // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   if(this.m_quad_width==0)
      this.m_quad_width=1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
   if(this.m_quad_height==0)
      this.m_quad_height=1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolygon(array_x,array_y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a rectangle using two points                                |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawRectangleOnBG(const int   x1,             // X coordinate of the first point defining the rectangle
                                   const int   y1,             // Y coordinate of the first point defining the rectangle
                                   const int   x2,             // X coordinate of the second point defining the rectangle
                                   const int   y2,             // Y coordinate of the second point defining the rectangle
                                   const color clr,            // Color
                                   const uchar opacity=255,    // Opacity
                                   const bool  redraw=false)   // Chart redraw flag
     {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawRectangle(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw the circle                                                  |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleOnBG(const int   x,              // X coordinate of the circle center
                                const int   y,              // Y coordinate of the circle center
                                const int   r,              // Circle radius
                                const color clr,            // Color
                                const uchar opacity=255,    // Opacity
                                const bool  redraw=false)   // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   int rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawCircle(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_CENTER;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a triangle                                                  |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleOnBG(const int   x1,           // X coordinate of the triangle first vertex
                                  const int   y1,           // Y coordinate of the triangle first vertex
                                  const int   x2,           // X coordinate of the triangle second vertex
                                  const int   y2,           // Y coordinate of the triangle second vertex
                                  const int   x3,           // X coordinate of the triangle third vertex
                                  const int   y3,           // Y coordinate of the triangle third vertex
                                  const color clr,          // Color
                                  const uchar opacity=255,  // Opacity
                                  const bool  redraw=false) // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(::fmin(x1,x2),x3);
   this.m_quad_y=::fmin(::fmin(y1,y2),y3);
   int max_x=::fmax(::fmax(x1,x2),x3);
   int max_y=::fmax(::fmax(y1,y2),y3);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawTriangle(x1,y1,x2,y2,x3,y3,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw an ellipse using two points                                 |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseOnBG(const int   x1,            // X coordinate of the first point defining the ellipse
                                 const int   y1,            // Y coordinate of the first point defining the ellipse
                                 const int   x2,            // X coordinate of the second point defining the ellipse
                                 const int   y2,            // Y coordinate of the second point defining the ellipse
                                 const color clr,           // Color
                                 const uchar opacity=255,   // Opacity
                                 const bool  redraw=false)  // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawEllipse(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw an arc of an ellipse inscribed in a rectangle               |
//| with the corners in (x1,y1) and (x2,y2).                         |
//| The arc boundaries are cropped from the ellipse center           |
//| moving to two points with the coordinates of (x3,y3) and (x4,y4) |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawArcOnBG(const int   x1,             // X coordinate of the top left corner forming the rectangle
                             const int   y1,             // Y coordinate of the top left corner forming the rectangle
                             const int   x2,             // X coordinate of the bottom right corner forming the rectangle
                             const int   y2,             // Y coordinate of the bottom right corner forming the rectangle
                             const int   x3,             // X coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                             const int   y3,             // Y coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                             const int   x4,             // X coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                             const int   y4,             // Y coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                             const color clr,            // Color
                             const uchar opacity=255,    // Opacity
                             const bool  redraw=false)   // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2)-1;
   this.m_quad_y=::fmin(y1,y2)-1;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+2;
   this.m_quad_height=::fabs(y2-y1)+2;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawArc(x1,y1,x2,y2,x3,y3,x4,y4,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a filled sector of an ellipse inscribed in a rectangle      |
//| with the corners in (x1,y1) and (x2,y2).                         |
//| The sector boundaries are cropped from the ellipse center,       |
//| moving to two points with the coordinates of (x3,y3) and (x4,y4) |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPieOnBG(const int   x1,             // X coordinate of the upper left corner of the rectangle
                             const int   y1,             // Y coordinate of the upper left corner of the rectangle
                             const int   x2,             // X coordinate of the bottom right corner of the rectangle
                             const int   y2,             // Y coordinate of the bottom right corner of the rectangle
                             const int   x3,             // X coordinate of the first point to find the arc boundaries
                             const int   y3,             // Y coordinate of the first point to find the arc boundaries
                             const int   x4,             // X coordinate of the second point to find the arc boundaries
                             const int   y4,             // Y coordinate of the second point to find the arc boundaries
                             const color clr,            // Color
                             const color fill_clr,       // Fill color
                             const uchar opacity=255,    // Opacity
                             const bool  redraw=false)   // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2)-1;
   this.m_quad_y=::fmin(y1,y2)-1;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+2;
   this.m_quad_height=::fabs(y2-y1)+2;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPie(x1,y1,x2,y2,x3,y3,x4,y4,clr,fill_clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+


塗りつぶされたプリミティブを平滑化を使用せずに描画するメソッドを考えてみましょう。

以下は、領域を塗りつぶすメソッドです。

//+------------------------------------------------------------------+
//| Fill in the area                                                 |
//+------------------------------------------------------------------+
bool CFrameQuad::FillOnBG(const int   x,              // X coordinate of the filling start point
                          const int   y,              // Y coordinate of the filling start point
                          const color clr,            // Color
                          const uchar opacity=255,    // Opacity
                          const uint  threshould=0,   // Threshold
                          const bool  redraw=false)   // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=0;
   this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=0;
   this.m_quad_height=0;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.Fill(x,y,clr,opacity,threshould);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

このメソッドは任意の囲まれた領域を塗りつぶすため、保存された領域のサイズを事前に知ることはできません。したがって、ここではフォーム全体を保存する必要があります。これを実現するために、座標とサイズをゼロに設定しましょう。これらの値の場合、メソッドは画像の長方形の領域を保存し、フォームの背景全体を配列に保存します。

塗りつぶされたプリミティブを描画する残りのメソッドについては、座標と保存領域サイズの計算は、前に検討した単純な平滑化されていないプリミティブの計算と一致します。メソッドをそのまま見てみましょう。

//+------------------------------------------------------------------+
//| Draw a filled rectangle                                          |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawRectangleFillOnBG(const int   x1,            // X coordinate of the first point defining the rectangle
                                       const int   y1,            // Y coordinate of the first point defining the rectangle
                                       const int   x2,            // X coordinate of the second point defining the rectangle
                                       const int   y2,            // Y coordinate of the second point defining the rectangle
                                       const color clr,           // Color
                                       const uchar opacity=255,   // Opacity
                                       const bool  redraw=false)  // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawRectangleFill(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a filled circle                                             |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleFillOnBG(const int   x,             // X coordinate of the circle center
                                    const int   y,             // Y coordinate of the circle center
                                    const int   r,             // Circle radius
                                    const color clr,           // Color
                                    const uchar opacity=255,   // Opacity
                                    const bool  redraw=false)  // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   int rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawCircleFill(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a filled triangle                                           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleFillOnBG(const int   x1,             // X coordinate of the triangle first vertex
                                      const int   y1,             // Y coordinate of the triangle first vertex
                                      const int   x2,             // X coordinate of the triangle second vertex
                                      const int   y2,             // Y coordinate of the triangle second vertex
                                      const int   x3,             // X coordinate of the triangle third vertex
                                      const int   y3,             // Y coordinate of the triangle third vertex
                                      const color clr,            // Color
                                      const uchar opacity=255,    // Opacity
                                      const bool  redraw=false)   // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(::fmin(x1,x2),x3)-1;
   this.m_quad_y=::fmin(::fmin(y1,y2),y3)-1;
   int max_x=::fmax(::fmax(x1,x2),x3)+1;
   int max_y=::fmax(::fmax(y1,y2),y3)+1;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawTriangleFill(x1,y1,x2,y2,x3,y3,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a filled polygon                                            |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonFillOnBG(int         &array_x[],   // Array with the X coordinates of polygon points
                                     int         &array_y[],   // Array with the Y coordinates of polygon points
                                     const color clr,          // Color
                                     const uchar opacity=255,  // Opacity
                                     const bool  redraw=false) // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolygonFill(array_x,array_y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a filled ellipse inscribed in a rectangle                   |
//| with the given coordinates                                       |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseFillOnBG(const int   x1,           // X coordinate of the top left corner forming the rectangle
                                     const int   y1,           // Y coordinate of the top left corner forming the rectangle
                                     const int   x2,           // X coordinate of the bottom right corner forming the rectangle
                                     const int   y2,           // Y coordinate of the bottom right corner forming the rectangle
                                     const color clr,          // Color
                                     const uchar opacity=255,  // Opacity
                                     const bool  redraw=false) // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawEllipseFill(x1,y1,x2,y2,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+


以下は、平滑化を使用してプリミティブを描画するメソッドです。

以下は、アンチエイリアスアルゴリズムを使用して点を描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a point using AntiAliasing algorithm                        |
//+------------------------------------------------------------------+
bool CFrameQuad::SetPixelAAOnBG(const double x,             // Point X coordinate
                                const double y,             // Point Y coordinate
                                const color  clr,           // Color
                                const uchar  opacity=255,   // Opacity
                                const bool   redraw=false)  // Chart redraw flag
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=x-1;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   this.m_quad_y=y-1;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=3;
   this.m_quad_height=3;
   
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If a background area with calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.SetPixelAA(x,y,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

保存領域の座標とサイズの計算は、平滑化を使用せずに点を描画するメソッドでの同じ計算とは異なります。平滑化された点は、3つの隣接するピクセル(合計9、つまり3 x 3ピクセル)に配置されることがあるため、保存される領域の寸法は、高さ、幅とも3ピクセルである必要があります。X座標とY座標は、それぞれ、点自体の座標から1ピクセル左、1ピクセル上にある必要があります。したがって、点が平滑化アルゴリズムによってぼかされて複数のピクセルに描画された場合、点の輪郭を描く保存領域の長方形には描画された点のすべての辺に1ピクセルの余白があります。これにより、描画された点によって消去された背景の不完全な復元を平滑化で取り除くことができます。

以下は、アンチエイリアスアルゴリズムを使用してフリーハンドの線分を描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a segment of a freehand line                                |
//| using AntiAliasing algorithm                                     |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineAAOnBG(const int   x1,             // X coordinate of the segment first point
                                const int   y1,             // Y coordinate of the segment first point
                                const int   x2,             // X coordinate of the segment second point
                                const int   y2,             // Y coordinate of the segment second point
                                const color clr,            // Color
                                const uchar opacity=255,    // Opacity
                                const bool  redraw=false,   // Chart redraw flag
                                const uint  style=UINT_MAX) // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;

//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;

//--- Draw the shape and update the element
   this.m_element.DrawLineAA(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

メソッドをテストしたところ、描画された線のエッジがぼやけていないことがわかりました。したがって、保存領域サイズの計算は、平滑化を使用せずに線を描画するメソッドの計算と一致します。

以下は、Wuのアルゴリズムを使用してフリーハンドの線分を描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a segment of a freehand line using the                      |
//| Wu algorithm                                                     |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineWuOnBG(const int   x1,             // X coordinate of the segment first point
                                const int   y1,             // Y coordinate of the segment first point
                                const int   x2,             // X coordinate of the segment second point
                                const int   y2,             // Y coordinate of the segment second point
                                const color clr,            // Color
                                const uchar opacity=255,    // Opacity
                                const bool  redraw=false,   // Chart redraw flag
                                const uint  style=UINT_MAX) // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   this.m_quad_height=::fabs(y2-y1)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawLineWu(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

計算は、同じ理由で前のメソッドと似ています。

以下は、予備ろ過を伴う平滑化アルゴリズムを使用して、指定された幅を持つフリーハンドの線分を描画するメソッドです。

//+------------------------------------------------------------------+
//| Draw a  segment of a freehand line having a specified width      |
//| using a smoothing algorithm                                      |
//| with the preliminary sorting                                     |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawLineThickOnBG(const int   x1,                         // X coordinate of the segment first point
                                   const int   y1,                         // Y coordinate of the segment first point
                                   const int   x2,                         // X coordinate of the segment second point
                                   const int   y2,                         // Y coordinate of the segment second point
                                   const int   size,                       // Line width
                                   const color clr,                        // Color
                                   const uchar opacity=255,                // Opacity
                                   const bool  redraw=false,               // Chart redraw flag
                                   const uint  style=STYLE_SOLID,          // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                                   ENUM_LINE_END end_style=LINE_END_ROUND) // Line style is one of the ENUM_LINE_END enumeration's values
  {
//--- Calculate the adjustment of the outlining rectangle coordinates depending on the line size
   int correct=int(::ceil((double)size/2.0))+1;
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2)-correct;
   this.m_quad_y=::fmin(y1,y2)-correct;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1+correct*2;
   this.m_quad_height=::fabs(y2-y1)+1+correct*2;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawLineThick(x1,y1,x2,y2,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

このメソッドの保存領域の計算は上記とは異なります。このような平滑化アルゴリズムを使用した線は、編集可能な値とその端の外観を備えているため、保存される領域の幅は、線とそのエッジのサイズ(幅)を考慮する必要があります(線のエッジは丸めることができるため、線のサイズ (長さ)は、2つの丸め半径、つまり線幅として設定された値だけ増加します。

以下は、予備ろ過を伴う平滑化アルゴリズムを使用して、指定された幅を持つフリーハンドの垂直線分を描画するメソッドです。

//+---------------------------------------------------------------------+
//| Draw a vertical segment of a freehand line having a specified width |
//| using a smoothing algorithm                                         |
//| with the preliminary sorting                                        |
//+---------------------------------------------------------------------+
bool CFrameQuad::DrawLineThickVerticalOnBG(const int   x,                              // X coordinate of the segment
                                           const int   y1,                             // Y coordinate of the segment first point
                                           const int   y2,                             // Y coordinate of the segment second point
                                           const int   size,                           // line width
                                           const color clr,                            // Color
                                           const uchar opacity=255,                    // Opacity
                                           const bool  redraw=false,                   // Chart redraw flag
                                           const uint  style=STYLE_SOLID,              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                                           const ENUM_LINE_END end_style=LINE_END_ROUND)// Line style is one of the ENUM_LINE_END enumeration's values
  {
//--- Calculate the adjustment of the outlining rectangle coordinates depending on the line size and the type of its ends
   int correct_x=(int)::ceil((double)size/2.0);
   int correct_y=(end_style==LINE_END_BUTT ? 0 : correct_x);
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=x-correct_x;
   this.m_quad_y=::fmin(y1,y2)-correct_y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=size;
   this.m_quad_height=::fabs(y2-y1)+1+correct_y*2;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawLineThickVertical(x,y1,y2,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

計算は、前のメソッドで説明したものと同じです。

以下は、平滑化されたプリミティブおよびその他のプリミティブを描画する残りのメソッドです。

//+-----------------------------------------------------------------------+
//| Draws a horizontal segment of a freehand line having a specified width|
//| using a smoothing algorithm                                           |
//| with the preliminary sorting                                          |
//+-----------------------------------------------------------------------+
bool CFrameQuad::DrawLineThickHorizontalOnBG(const int   x1,                              // X coordinate of the segment first point
                                             const int   x2,                              // X coordinate of the segment second point
                                             const int   y,                               // Segment Y coordinate
                                             const int   size,                            // line width
                                             const color clr,                             // Color
                                             const uchar opacity=255,                     // Opacity
                                             const bool  redraw=false,                    // Chart redraw flag
                                             const uint  style=STYLE_SOLID,               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                                             const ENUM_LINE_END end_style=LINE_END_ROUND)// Line style is one of the ENUM_LINE_END enumeration's values
  {
//--- Calculate the adjustment of the outlining rectangle coordinates depending on the line size and the type of its ends
   int correct_y=(int)::ceil((double)size/2.0);
   int correct_x=(end_style==LINE_END_BUTT ? 0 : correct_y);
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2)-correct_x;
   this.m_quad_y=y-correct_y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1+correct_x*2;
   this.m_quad_height=size;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawLineThickHorizontal(x1,x2,y,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a polyline using                                            |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineAAOnBG(int         &array_x[],       // Array with the X coordinates of polyline points
                                    int         &array_y[],       // Array with the Y coordinates of polyline points
                                    const color clr,              // Color
                                    const uchar opacity=255,      // Opacity
                                    const bool  redraw=false,     // Chart redraw flag
                                    const uint  style=UINT_MAX)   // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;

//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolylineAA(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draws a polyline using Wu algorithm                              |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineWuOnBG(int         &array_x[],       // Array with the X coordinates of polyline points
                                    int         &array_y[],       // Array with the Y coordinates of polyline points
                                    const color clr,              // Color
                                    const uchar opacity=255,      // Opacity
                                    const bool  redraw=false,     // Chart redraw flag
                                    const uint  style=UINT_MAX)   // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   this.m_quad_height=(max_y_value-min_y_value)+1;

//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolylineWu(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a polyline with a specified width using                     |
//| two smoothing algorithms in series.                              |
//| First, individual segments are smoothed                          |
//| based on Bezier curves.                                          |
//| Then, to improve the rendering quality,                          |
//| a raster smoothing algorithm is applied                          |
//| made of the polyline segments                                    |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineSmoothOnBG(const int    &array_x[],                    // Array with the X coordinates of polyline points
                                        const int    &array_y[],                    // Array with the Y coordinates of polyline points
                                        const int    size,                          // Line width
                                        const color  clr,                           // Color
                                        const uchar  opacity=255,                   // Chart redraw flag
                                        const double tension=0.5,                   // Smoothing parameter value
                                        const double step=10,                       // Approximation step
                                        const bool   redraw=false,                  // Chart redraw flag
                                        const ENUM_LINE_STYLE style=STYLE_SOLID,    // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                                        const ENUM_LINE_END   end_style=LINE_END_ROUND)// Line style is one of the ENUM_LINE_END enumeration's values
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=0;
   this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=this.m_element.Width();
   this.m_quad_height=this.m_element.Height();
   
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }

//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;

//--- Draw the shape and update the element
   this.m_element.DrawPolylineSmooth(array_x,array_y,size,clr,opacity,tension,step,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a polyline with a specified width using                     |
//| a smoothing algorithm with the preliminary sorting               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolylineThickOnBG(const int   &array_x[],                // Array with the X coordinates of polyline points
                                       const int   &array_y[],                // Array with the Y coordinates of polyline points
                                       const int   size,                      // Line width
                                       const color clr,                       // Color
                                       const uchar opacity=255,               // Opacity
                                       const bool  redraw=false,              // Chart redraw flag
                                       const uint  style=STYLE_SOLID,         // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                                       ENUM_LINE_END end_style=LINE_END_ROUND)// Line style is one of the ENUM_LINE_END enumeration's values
  {
//--- Calculate the adjustment of the outlining rectangle coordinates depending on the line size
   int correct=int(::ceil((double)size/2.0))+1;
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x-correct;
   this.m_quad_y=y-correct;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1+correct*2;
   this.m_quad_height=(max_y_value-min_y_value)+1+correct*2;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolylineThick(array_x,array_y,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a polygon using                                             |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonAAOnBG(int         &array_x[],     // Array with the X coordinates of polygon points
                                   int         &array_y[],     // Array with the Y coordinates of polygon points
                                   const color clr,            // Color
                                   const uchar opacity=255,    // Opacity
                                   const bool  redraw=false,   // Chart redraw flag
                                   const uint  style=UINT_MAX) // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   if(this.m_quad_width==0)
      this.m_quad_width=1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
   if(this.m_quad_height==0)
      this.m_quad_height=1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolygonAA(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a polygon using Wu algorithm                                |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonWuOnBG(int         &array_x[],     // Array with the X coordinates of polygon points
                                   int         &array_y[],     // Array with the Y coordinates of polygon points
                                   const color clr,            // Color
                                   const uchar opacity=255,    // Opacity
                                   const bool  redraw=false,   // Chart redraw flag
                                   const uint  style=UINT_MAX) // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x;
   this.m_quad_y=y;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1;
   if(this.m_quad_width==0)
      this.m_quad_width=1;
   this.m_quad_height=(max_y_value-min_y_value)+1;
   if(this.m_quad_height==0)
      this.m_quad_height=1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolygonWu(array_x,array_y,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a polygon with a specified width using                      |
//| two smoothing algorithms in series.                              |
//| First, individual segments are smoothed based on Bezier curves.  |
//| Then, to improve the rendering quality,                          |
//| a raster smoothing algorithm is applied                          |
//| made of the polyline segments.                                   |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonSmoothOnBG(int          &array_x[],                  // Array with the X coordinates of polyline points
                                       int          &array_y[],                  // Array with the Y coordinates of polyline points
                                       const int    size,                        // Line width
                                       const color  clr,                         // Color
                                       const uchar  opacity=255,                 // Chart redraw flag
                                       const double tension=0.5,                 // Smoothing parameter value
                                       const double step=10,                     // Approximation step
                                       const bool   redraw=false,                // Chart redraw flag
                                       const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                                       const ENUM_LINE_END   end_style=LINE_END_ROUND)// Line style is one of the ENUM_LINE_END enumeration's values
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=0;
   this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=this.m_element.Width();
   this.m_quad_height=this.m_element.Height();
   
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }

//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;

//--- Draw the shape and update the element
   this.m_element.DrawPolygonSmooth(array_x,array_y,size,clr,opacity,tension,step,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a polygon with a specified width using                      |
//| a smoothing algorithm with the preliminary sorting               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawPolygonThickOnBG(const int   &array_x[],                 // array with the X coordinates of polygon points
                                      const int   &array_y[],                 // array with the Y coordinates of polygon points
                                      const int   size,                       // line width
                                      const color clr,                        // Color
                                      const uchar opacity=255,                // Opacity
                                      const bool  redraw=false,               // Chart redraw flag
                                      const uint  style=STYLE_SOLID,          // line style
                                      ENUM_LINE_END end_style=LINE_END_ROUND) // line ends style
  {
//--- Calculate the adjustment of the outlining rectangle coordinates depending on the line size
   int correct=int(::ceil((double)size/2.0))+1;
//--- Set the coordinates of the outlining rectangle
   int x=0,y=0;
   if(!ArrayMinimumValue(DFUN_ERR_LINE,array_x,x) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,y))
      return false;
   this.m_quad_x=x-correct;
   this.m_quad_y=y-correct;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   int max_x_value=0,min_x_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_x,max_x_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_x,min_x_value))
      return false;
   int max_y_value=0,min_y_value=0;
   if(!ArrayMaximumValue(DFUN_ERR_LINE,array_y,max_y_value) || !ArrayMinimumValue(DFUN_ERR_LINE,array_y,min_y_value))
      return false;
   this.m_quad_width=(max_x_value-min_x_value)+1+correct*2;
   this.m_quad_height=(max_y_value-min_y_value)+1+correct*2;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawPolygonThick(array_x,array_y,size,clr,opacity,style,end_style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a triangle using                                            |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleAAOnBG(const int   x1,               // X coordinate of the triangle first vertex
                                    const int   y1,               // Y coordinate of the triangle first vertex
                                    const int   x2,               // X coordinate of the triangle second vertex
                                    const int   y2,               // Y coordinate of the triangle second vertex
                                    const int   x3,               // X coordinate of the triangle third vertex
                                    const int   y3,               // Y coordinate of the triangle third vertex
                                    const color clr,              // Color
                                    const uchar opacity=255,      // Opacity
                                    const bool  redraw=false,     // Chart redraw flag
                                    const uint  style=UINT_MAX)   // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(::fmin(x1,x2),x3);
   this.m_quad_y=::fmin(::fmin(y1,y2),y3);
   int max_x=::fmax(::fmax(x1,x2),x3);
   int max_y=::fmax(::fmax(y1,y2),y3);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawTriangleAA(x1,y1,x2,y2,x3,y3,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a triangle using Wu algorithm                               |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawTriangleWuOnBG(const int   x1,               // X coordinate of the triangle first vertex
                                    const int   y1,               // Y coordinate of the triangle first vertex
                                    const int   x2,               // X coordinate of the triangle second vertex
                                    const int   y2,               // Y coordinate of the triangle second vertex
                                    const int   x3,               // X coordinate of the triangle third vertex
                                    const int   y3,               // Y coordinate of the triangle third vertex
                                    const color clr,              // Color
                                    const uchar opacity=255,      // Opacity
                                    const bool  redraw=false,     // Chart redraw flag
                                    const uint  style=UINT_MAX)   // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(::fmin(x1,x2),x3);
   this.m_quad_y=::fmin(::fmin(y1,y2),y3);
   int max_x=::fmax(::fmax(x1,x2),x3);
   int max_y=::fmax(::fmax(y1,y2),y3);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(max_x-this.m_quad_x)+1;
   this.m_quad_height=int(max_y-this.m_quad_y)+1;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawTriangleWu(x1,y1,x2,y2,x3,y3,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a circle using                                              |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleAAOnBG(const int    x,              // X coordinate of the circle center
                                  const int    y,              // Y coordinate of the circle center
                                  const double r,              // Circle radius
                                  const color  clr,            // Color
                                  const uchar  opacity=255,    // Opacity
                                  const bool   redraw=false,   // Chart redraw flag
                                  const uint   style=UINT_MAX) // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   double rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawCircleAA(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw a circle using Wu algorithm                                 |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawCircleWuOnBG(const int    x,              // X coordinate of the circle center
                                  const int    y,              // Y coordinate of the circle center
                                  const double r,              // Circle radius
                                  const color  clr,            // Color
                                  const uchar  opacity=255,    // Opacity
                                  const bool   redraw=false,   // Chart redraw flag
                                  const uint   style=UINT_MAX) // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   double rd=(r>0 ? r : 1);
   this.m_quad_x=x-rd;
   this.m_quad_y=y-rd;
   double x2=x+rd;
   double y2=y+rd;
   if(this.m_quad_x<0)
      this.m_quad_x=0;
   if(this.m_quad_y<0)
      this.m_quad_y=0;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(::ceil(x2-this.m_quad_x)+1);
   this.m_quad_height=int(::ceil(y2-this.m_quad_y)+1);
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawCircleWu(x,y,rd,clr,opacity);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw an ellipse using two points while applying                  |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseAAOnBG(const double x1,               // X coordinate of the first point defining the ellipse
                                   const double y1,               // Y coordinate of the first point defining the ellipse
                                   const double x2,               // X coordinate of the second point defining the ellipse
                                   const double y2,               // Y coordinate of the second point defining the ellipse
                                   const color  clr,              // Color
                                   const uchar  opacity=255,      // Opacity
                                   const bool   redraw=false,     // Chart redraw flag
                                   const uint   style=UINT_MAX)   // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2)-1;
   this.m_quad_y=::fmin(y1,y2)-1;
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=int(::ceil(::fabs(x2-x1)))+1;
   this.m_quad_height=int(::ceil(::fabs(y2-y1)))+1;
   
   if(this.m_quad_width<3)
      this.m_quad_width=3;
   if(this.m_quad_height<3)
      this.m_quad_height=3;
      
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawEllipseAA(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+
//| Draw an ellipse using two points while applying                  |
//| Wu algorithm                                                     |
//+------------------------------------------------------------------+
bool CFrameQuad::DrawEllipseWuOnBG(const int   x1,             // X coordinate of the first point defining the ellipse
                                   const int   y1,             // Y coordinate of the first point defining the ellipse
                                   const int   x2,             // X coordinate of the second point defining the ellipse
                                   const int   y2,             // Y coordinate of the second point defining the ellipse
                                   const color clr,            // Color
                                   const uchar opacity=255,    // Opacity
                                   const bool  redraw=false,   // Chart redraw flag
                                   const uint  style=UINT_MAX) // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
//--- Set the coordinates of the outlining rectangle
   this.m_quad_x=::fmin(x1,x2);
   this.m_quad_y=::fmin(y1,y2);
//--- Set the width and height of the image outlining the rectangle (to be used as the size of the saved area)
   this.m_quad_width=::fabs(x2-x1)+1;
   if(this.m_quad_width<3)
      this.m_quad_width=3;
   this.m_quad_height=::fabs(y2-y1)+1;
   if(this.m_quad_height<3)
      this.m_quad_height=3;
   
//--- Calculate coordinate offsets for the saved area depending on the anchor point
   int shift_x=0,shift_y=0;
   this.m_element.GetShiftXYbySize(this.m_quad_width,this.m_quad_height,TEXT_ANCHOR_LEFT_TOP,shift_x,shift_y);
//--- If the pixel array is not empty, the background under the image has already been saved -
//--- restore the previously saved background (by the previous coordinates and offsets)
   if(::ArraySize(this.m_array)>0)
     {
      if(!CPixelCopier::CopyImgDataToCanvas(int(this.m_x_last+this.m_shift_x_prev),int(this.m_y_last+this.m_shift_y_prev)))
         return false;
     }
//--- If the background area with the calculated coordinates and size under the future image is successfully saved
   if(!CPixelCopier::CopyImgDataToArray(int(this.m_quad_x+shift_x),int(this.m_quad_y+shift_y),this.m_quad_width,this.m_quad_height))
      return false;
//--- Draw the shape and update the element
   this.m_element.DrawEllipseWu(x1,y1,x2,y2,clr,opacity,style);
   this.m_element.Update(redraw);
   this.m_anchor_last=TEXT_ANCHOR_LEFT_TOP;
   this.m_x_last=this.m_quad_x;
   this.m_y_last=this.m_quad_y;
   this.m_shift_x_prev=shift_x;
   this.m_shift_y_prev=shift_y;
   return true;
  }
//+------------------------------------------------------------------+

ここでのすべてのメソッドの保存された背景領域の計算アルゴリズムは、上記で検討したメソッドの計算アルゴリズムとほぼ同じです。

楕円の描画メソッド(DrawEllipseAAOnBGおよびDrawEllipseWuOnBG)では、楕円が描画される長方形が3ピクセル未満の場合、形状は描画されません。したがって、ここでの計算には、サイズが3ピクセル未満であることのチェックが含まれています。これが私のバグなのか、CCanvasクラスメソッドの機能なのかはまだわかりません。これは後で明らかにしたいと思います。

現在必要なアニメーションフレームオブジェクトのすべてのクラスを開発しました。

次に、作成したアニメーションフレームオブジェクトを保存、アクセス、管理するためのクラスを作成します。

このクラスには、作成されたアニメーションフレームオブジェクト(テキストと長方形のオブジェクト)を格納するための2つの(今のところ)リストと、新しいオブジェクトを作成および管理するためのメソッドが含まれます。続いて、クラスは1つのフォームに属するすべてのアニメーションオブジェクトを格納します。したがって、各フォームは、動的に作成してフォームアニメーションのリストに追加できる独自のアニメーションオブジェクトのセットを備えています。

フォームアニメーションクラス

\MQL5\Include\DoEasy\Objects\Graph\Animations\で、CAnimationsクラスの新しいAnimations.mqhファイルを作成します。

基本アニメーションフレームオブジェクトの新しく作成された子孫クラスファイルのみをクラスファイルに含める必要があります。クラス自体は、CObject標準ライブラリのベースオブジェクトの子孫である必要があります

//+------------------------------------------------------------------+
//|                                                   Animations.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "FrameText.mqh"
#include "FrameQuad.mqh"
//+------------------------------------------------------------------+
//| Pixel copier class                                               |
//+------------------------------------------------------------------+
class CAnimations : public CObject
  {
  }

クラスのprivateセクションで、アニメーションオブジェクトの作成元となるグラフィカル要素オブジェクトへのポインタ、2種類のアニメーションフレームオブジェクトを格納するための2つのリスト、リスト内の指定されたオブジェクトの存在を示すフラグを返すためのメソッド、既存のアニメーションフレームオブジェクトへのポインタを返すメソッド、またはリストにない場合は事前に作成するメソッドを宣言します。

//+------------------------------------------------------------------+
//| Pixel copier class                                               |
//+------------------------------------------------------------------+
class CAnimations : public CObject
  {
private:
   CGCnvElement     *m_element;                             // Pointer to the graphical element
   CArrayObj         m_list_frames_text;                    // List of text animation frames
   CArrayObj         m_list_frames_quad;                    // List of rectangle animation frames

//--- Return the flag indicating the presence of the frame object with the specified ID in the list
   bool              IsPresentFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id);
//--- Return or create a new animation frame object
   CFrame           *GetOrCreateFrame(const string soutce,const int id,const ENUM_ANIMATION_FRAME_TYPE frame_type,const bool create_new);

public:

以下では、すべてのメソッドを検討します。

クラスのpublicセクションで、リスト内のオブジェクトを作成および操作するためのメソッドと、背景を保存および復元しながらプリミティブを描画するメソッドを宣言します。

public:
                     CAnimations(CGCnvElement *element);
                     CAnimations(){;}

//--- Create a new (1) rectangle and (2) text animation frame object
   CFrame           *CreateNewFrameText(const int id);
   CFrame           *CreateNewFrameQuad(const int id);
//--- Return the animation frame objects by ID
   CFrame           *GetFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id);
//--- Return the list of (1) text and (2) rectangle animation frames
   CArrayObj        *GetListFramesText(void)                { return &this.m_list_frames_text;  }
   CArrayObj        *GetListFramesQuad(void)                { return &this.m_list_frames_quad;  }

//+------------------------------------------------------------------+
//| The methods of drawing, while saving and restoring the background|
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Display a text on the background                                 |
//+------------------------------------------------------------------+
   bool              TextOnBG(const int id,
                              const string text,
                              const int x,
                              const int y,
                              const ENUM_TEXT_ANCHOR anchor,
                              const color clr,
                              const uchar opacity,
                              const bool create_new=true,
                              const bool redraw=false);
//+------------------------------------------------------------------+
//| Methods of drawing primitives without smoothing                  |
//+------------------------------------------------------------------+
//--- Set the color of the dot with the specified coordinates
   bool              SetPixelOnBG(const int id,const int x,const int y,const color clr,const uchar opacity=255,const bool create_new=true,const bool redraw=false);
                       
//--- Draw a segment of a vertical line
   bool              DrawLineVerticalOnBG(const int id,                 // Frame ID
                              const int   x,                            // Segment X coordinate
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a segment of a horizontal line
   bool              DrawLineHorizontalOnBG(const int id,               // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y,                            // Segment Y coordinate
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a segment of a freehand line
   bool              DrawLineOnBG(const int id,                         // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a polyline
   bool              DrawPolylineOnBG(const int id,                     // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a polygon
   bool              DrawPolygonOnBG(const int id,                      // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a rectangle using two points
   bool              DrawRectangleOnBG(const int id,                    // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the rectangle
                              const int   y1,                           // Y coordinate of the first point defining the rectangle
                              const int   x2,                           // X coordinate of the second point defining the rectangle
                              const int   y2,                           // Y coordinate of the second point defining the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a circle
   bool              DrawCircleOnBG(const int id,                       // Frame ID
                              const int   x,                            // X coordinate of the circle center
                              const int   y,                            // Y coordinate of the circle center
                              const int   r,                            // Circle radius
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a triangle
   bool              DrawTriangleOnBG(const int id,                     // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw an ellipse using two points
   bool              DrawEllipseOnBG(const int id,                      // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the ellipse
                              const int   y1,                           // Y coordinate of the first point defining the ellipse
                              const int   x2,                           // X coordinate of the second point defining the ellipse
                              const int   y2,                           // Y coordinate of the second point defining the ellipse
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw an arc of an ellipse inscribed in a rectangle with corners at (x1,y1) and (x2,y2).
//--- The arc boundaries are clipped by lines from the center of the ellipse, which extend to two points with coordinates (x3,y3) and (x4,y4)
   bool              DrawArcOnBG(const int id,                          // Frame ID
                              const int   x1,                           // X coordinate of the top left corner forming the rectangle
                              const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                              const int   x3,                           // X coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   y3,                           // Y coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   x4,                           // X coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   y4,                           // Y coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled sector of an ellipse inscribed in a rectangle with corners at (x1,y1) and (x2,y2).
//--- The sector boundaries are clipped by lines from the center of the ellipse, which extend to two points with coordinates (x3,y3) and (x4,y4)
   bool              DrawPieOnBG(const int id,                          // Frame ID
                              const int   x1,                           // X coordinate of the upper left corner of the rectangle
                              const int   y1,                           // Y coordinate of the upper left corner of the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner of the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner of the rectangle
                              const int   x3,                           // X coordinate of the first point to find the arc boundaries
                              const int   y3,                           // Y coordinate of the first point to find the arc boundaries
                              const int   x4,                           // X coordinate of the second point to find the arc boundaries
                              const int   y4,                           // Y coordinate of the second point to find the arc boundaries
                              const color clr,                          // Color
                              const color fill_clr,                     // Fill color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//+------------------------------------------------------------------+
//| Methods of drawing filled primitives without smoothing           |
//+------------------------------------------------------------------+
//--- Fill in the area
   bool              FillOnBG(const int   id,                           // Frame ID
                              const int   x,                            // X coordinate of the filling start point
                              const int   y,                            // Y coordinate of the filling start point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const uint  threshould=0,                 // Threshold
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled rectangle
   bool              DrawRectangleFillOnBG(const int id,                // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the rectangle
                              const int   y1,                           // Y coordinate of the first point defining the rectangle
                              const int   x2,                           // X coordinate of the second point defining the rectangle
                              const int   y2,                           // Y coordinate of the second point defining the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag

//--- Draw a filled circle
   bool              DrawCircleFillOnBG(const int id,                   // Frame ID
                              const int   x,                            // X coordinate of the circle center
                              const int   y,                            // Y coordinate of the circle center
                              const int   r,                            // Circle radius
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled triangle
   bool              DrawTriangleFillOnBG(const int id,                 // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled polygon
   bool              DrawPolygonFillOnBG(const int id,                  // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//--- Draw a filled ellipse inscribed in a rectangle with the specified coordinates
   bool              DrawEllipseFillOnBG(const int id,                  // Frame ID
                              const int   x1,                           // X coordinate of the top left corner forming the rectangle
                              const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false);                // Chart redraw flag
                       
//+------------------------------------------------------------------+
//| Methods of drawing primitives using smoothing                    |
//+------------------------------------------------------------------+
//--- Draw a point using AntiAliasing algorithm
   bool              SetPixelAAOnBG(const int id,                       // Frame ID
                              const double x,                           // Point X coordinate
                              const double y,                           // Point Y coordinate
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false);               // Chart redraw flag
                       
//--- Draw a segment of a freehand line using AntiAliasing algorithm
   bool              DrawLineAAOnBG(const int id,                       // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a segment of a freehand line using Wu algorithm
   bool              DrawLineWuOnBG(const int id,                       // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draws a segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawLineThickOnBG(const int id,                    // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const int   size,                         // Line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // Line style is one of the ENUM_LINE_END enumeration's values
 
//--- Draw a vertical segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawLineThickVerticalOnBG(const int id,            // Frame ID
                              const int   x,                            // Segment X coordinate
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   y2,                           // Y coordinate of the segment second point
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a horizontal segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawLineThickHorizontalOnBG(const int id,          // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y,                            // Segment Y coordinate
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND); // Line style is one of the ENUM_LINE_END enumeration's values

//--- Draws a polyline using AntiAliasing algorithm
   bool              DrawPolylineAAOnBG(const int id,                   // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draws a polyline using Wu algorithm
   bool              DrawPolylineWuOnBG(const int id,                   // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a polyline with a specified width consecutively using two antialiasing algorithms.
//--- First, individual line segments are smoothed based on Bezier curves.
//--- Then, the raster antialiasing algorithm is applied to the polyline built from these segments to improve the rendering quality
   bool              DrawPolylineSmoothOnBG(const int id,               // Frame ID
                              const int    &array_x[],                  // Array with the X coordinates of polyline points
                              const int    &array_y[],                  // Array with the Y coordinates of polyline points
                              const int    size,                        // Line width
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const double tension=0.5,                 // Smoothing parameter value
                              const double step=10,                     // Approximation step
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND);// Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a polyline having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawPolylineThickOnBG(const int id,                // Frame ID
                              const int     &array_x[],                 // Array with the X coordinates of polyline points
                              const int     &array_y[],                 // Array with the Y coordinates of polyline points
                              const int     size,                       // Line width
                              const color   clr,                        // Color
                              const uchar   opacity=255,                // Opacity
                              const bool    create_new=true,            // New object creation flag
                              const bool    redraw=false,               // Chart redraw flag
                              const uint    style=STYLE_SOLID,          // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a polygon using AntiAliasing algorithm
   bool              DrawPolygonAAOnBG(const int id,                    // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a polygon using Wu algorithm
   bool              DrawPolygonWuOnBG(const int id,                    // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a polygon with a specified width consecutively using two smoothing algorithms.
//--- First, individual segments are smoothed based on Bezier curves.
//--- Then, the raster smoothing algorithm is applied to the polygon built from these segments to improve the rendering quality. 
   bool              DrawPolygonSmoothOnBG(const int id,                // Frame ID
                              int          &array_x[],                  // Array with the X coordinates of polyline points
                              int          &array_y[],                  // Array with the Y coordinates of polyline points
                              const int    size,                        // Line width
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const double tension=0.5,                 // Smoothing parameter value
                              const double step=10,                     // Approximation step
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND);// Line style is one of the ENUM_LINE_END enumeration's values
                       
//--- Draw a polygon having a specified width using smoothing algorithm with the preliminary filtration
   bool              DrawPolygonThickOnBG(const int id,                 // Frame ID
                              const int   &array_x[],                   // array with the X coordinates of polygon points
                              const int   &array_y[],                   // array with the Y coordinates of polygon points
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // line style
                              ENUM_LINE_END end_style=LINE_END_ROUND);  // line ends style
                       
//--- Draw a triangle using AntiAliasing algorithm
   bool              DrawTriangleAAOnBG(const int id,                   // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a triangle using Wu algorithm
   bool              DrawTriangleWuOnBG(const int id,                   // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a circle using AntiAliasing algorithm
   bool              DrawCircleAAOnBG(const int id,                     // Frame ID
                              const int    x,                           // X coordinate of the circle center
                              const int    y,                           // Y coordinate of the circle center
                              const double r,                           // Circle radius
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX);             // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw a circle using Wu algorithm
   bool              DrawCircleWuOnBG(const int id,                     // Frame ID
                              const int    x,                           // X coordinate of the circle center
                              const int    y,                           // Y coordinate of the circle center
                              const double r,                           // Circle radius
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX);             // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw an ellipse by two points using AntiAliasing algorithm
   bool              DrawEllipseAAOnBG(const int id,                    // Frame ID
                              const double x1,                          // X coordinate of the first point defining the ellipse
                              const double y1,                          // Y coordinate of the first point defining the ellipse
                              const double x2,                          // X coordinate of the second point defining the ellipse
                              const double y2,                          // Y coordinate of the second point defining the ellipse
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX);             // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       
//--- Draw an ellipse by two points using Wu algorithm
   bool              DrawEllipseWuOnBG(const int id,                    // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the ellipse
                              const int   y1,                           // Y coordinate of the first point defining the ellipse
                              const int   x2,                           // X coordinate of the second point defining the ellipse
                              const int   y2,                           // Y coordinate of the second point defining the ellipse
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX);              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  };
//+------------------------------------------------------------------+


宣言されたメソッドの実装について考えてみましょう。

以下は、パラメトリックコンストラクタです。

//+------------------------------------------------------------------+
//| Parametric constructor                                           |
//+------------------------------------------------------------------+
CAnimations::CAnimations(CGCnvElement *element)
  {
   this.m_element=element;
  }
//+------------------------------------------------------------------+

引数で渡されたグラフィック要素オブジェクトへのポインタの値はm_elementポインタに設定されます。

以下は、タイプとIDでアニメーションフレームオブジェクトへのポインタを返すメソッドです。

//+------------------------------------------------------------------+
//| Return the animation frame objects by type and ID                |
//+------------------------------------------------------------------+
CFrame *CAnimations::GetFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id)
  {
//--- Declare the pointer to the animation frame object
   CFrame *frame=NULL;
//--- Depending on the necessary object type, receive their number in the appropriate list
   int total=
     (
      frame_type==ANIMATION_FRAME_TYPE_TEXT ? this.m_list_frames_text.Total() : 
      frame_type==ANIMATION_FRAME_TYPE_QUAD ? this.m_list_frames_quad.Total() : 0
     );
//--- Get the next object in the loop ...
   for(int i=0;i<total;i++)
     {
      //--- ... by the list corresponding to the animation frame type
      switch(frame_type)
        {
         case ANIMATION_FRAME_TYPE_TEXT : frame=this.m_list_frames_text.At(i); break;
         case ANIMATION_FRAME_TYPE_QUAD : frame=this.m_list_frames_quad.At(i); break;
         default: break;
        }
      //--- if failed to get the pointer, move on to the next one
      if(frame==NULL)
         continue;
      //--- If the object ID correspond to the required one,
      //--- return the pointer to the detected object
      if(frame.ID()==id)
         return frame;
     }
//--- Nothing is found - return NULL
   return NULL;
  }
//+------------------------------------------------------------------+

メソッドロジックはコードコメントで詳細に説明されており、説明は不要です。

以下は、リスト内に指定されたタイプとIDを持つフレームオブジェクトの存在を示すフラグを返すメソッドです。

//+-----------------------------------------------------------------------+
//| Return the flag indicating the presence of the animation frame object |
//| with the specified type and ID                                        |
//+-----------------------------------------------------------------------+
bool CAnimations::IsPresentFrame(const ENUM_ANIMATION_FRAME_TYPE frame_type,const int id)
  {
   return(this.GetFrame(frame_type,id)!=NULL);
  }
//+------------------------------------------------------------------+

このメソッドは、上記で検討したGetFrame()メソッドを呼び出した結果のboolを返します、メソッドは、GetFrame()メソッドがNULL以外の結果を返す場合(必要なオブジェクトがリストに存在する場合)、trueを返し、それ以外の場合はfalse を返しました。

以下は、新しいテキストアニメーションフレームオブジェクトを作成するメソッドです。

//+------------------------------------------------------------------+
//| Create a new text animation frame object                         |
//+------------------------------------------------------------------+
CFrame *CAnimations::CreateNewFrameText(const int id)
  {
//--- If the object with such an ID is already present, inform of that in the journal and return NULL
   if(this.IsPresentFrame(ANIMATION_FRAME_TYPE_TEXT,id))
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_FRAME_ALREADY_IN_LIST),(string)id);
      return NULL;
     }
//--- Create a new text animation frame object with the specified ID
   CFrame *frame=new CFrameText(id,this.m_element);
//--- If failed to create an object, inform of that and return NULL
   if(frame==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_ERR_FAILED_CREATE_FRAME));
      return NULL;
     }
//--- If failed to add the created object to the list, inform of that, remove the object and return NULL
   if(!this.m_list_frames_text.Add(frame))
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST)," ID: ",id);
      delete frame;
      return NULL;
     }
//--- Return the pointer to a newly created object
   return frame;
  }
//+------------------------------------------------------------------+

メソッドのロジックは、コードのコメントで完全に説明されています。

以下は、新しい長方形のアニメーションフレームオブジェクトを作成するメソッドです。

//+------------------------------------------------------------------+
//| Create a new rectangle animation frame object                    |
//+------------------------------------------------------------------+
CFrame *CAnimations::CreateNewFrameQuad(const int id)
  {
//--- If the object with such an ID is already present, inform of that in the journal and return NULL
   if(this.IsPresentFrame(ANIMATION_FRAME_TYPE_QUAD,id))
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_FRAME_ALREADY_IN_LIST),(string)id);
      return NULL;
     }
//--- Create a new rectangle animation frame object with the specified ID
   CFrame *frame=new CFrameQuad(id,this.m_element);
//--- If failed to create an object, inform of that and return NULL
   if(frame==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_FORM_OBJECT_ERR_FAILED_CREATE_FRAME));
      return NULL;
     }
//--- If failed to add the created object to the list, inform of that, remove the object and return NULL
   if(!this.m_list_frames_quad.Add(frame))
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_OBJ_ADD_TO_LIST)," ID: ",id);
      delete frame;
      return NULL;
     }
//--- Return the pointer to a newly created object
   return frame;
  }
//+------------------------------------------------------------------+

メソッドは上記で検討したものと同じです。

以下は、ポインタを返すまたは新しいアニメーションフレームオブジェクトを作成するメソッドです。

//+------------------------------------------------------------------+
//| Return or create a new animation frame object                    |
//+------------------------------------------------------------------+
CFrame *CAnimations::GetOrCreateFrame(const string source,const int id,const ENUM_ANIMATION_FRAME_TYPE frame_type,const bool create_new)
  {
   //--- Declare null pointers to objects
   CFrameQuad *frame_q=NULL;
   CFrameText *frame_t=NULL;
   //--- Depending on the required object type
   switch(frame_type)
     {
      //--- If this is a text animation frame,
      case ANIMATION_FRAME_TYPE_TEXT :
        //--- get the pointer to an object with a specified ID
        frame_t=this.GetFrame(ANIMATION_FRAME_TYPE_TEXT,id);
        //--- If the pointer is obtained, return it
        if(frame_t!=NULL)
           return frame_t;
        //--- If the flag of creating a new object is not set, report an error and return NULL
        if(!create_new)
          {
           ::Print(source,CMessage::Text(MSG_FORM_OBJECT_FRAME_NOT_EXIST_LIST),(string)id);
           return NULL;
          }
        //--- Return the result of creating a new text animation frame object (pointer to the created object)
        return this.CreateNewFrameText(id);
      
      //--- If this is a rectangle animation frame
      case ANIMATION_FRAME_TYPE_QUAD :
        //--- get the pointer to an object with a specified ID
        frame_q=this.GetFrame(ANIMATION_FRAME_TYPE_QUAD,id);
        //--- If the pointer is obtained, return it
        if(frame_q!=NULL)
           return frame_q;
        //--- If the flag of creating a new object is not set, report an error and return NULL
        if(!create_new)
          {
           ::Print(source,CMessage::Text(MSG_FORM_OBJECT_FRAME_NOT_EXIST_LIST),(string)id);
           return NULL;
          }
        //--- Return the result of creating a new rectangle animation frame object (pointer to the created object)
        return this.CreateNewFrameQuad(id);
      //--- In the remaining cases, return NULL
      default:
        return NULL;
     }
  }
//+------------------------------------------------------------------+

メソッドのロジックは、コードのコメントで説明されています。アニメーションフレームを操作する場合は、事前にフレームを作成し、そのフレームへのポインタを取得して、取得したオブジェクトを管理できます。オブジェクトを動的に作成する必要がある場合、このメソッドを使用すると、最初に新しいオブジェクトを作成し(指定されたIDを持つオブジェクトが存在しない場合)、そのオブジェクトへのポインタを返すことができます。したがって、必要に応じてオブジェクトの動的作成を調整し、オブジェクトへのポインタをすぐに取得して管理することができます。

以下は、アニメーションフレームオブジェクトを操作するメソッドです。

以下は、背景を保存および復元しながら背景にテキストを表示するメソッドです。

//+--------------------------------------------------------------------------------+
//| Display the text on the background, while saving and restoring the background  |
//+--------------------------------------------------------------------------------+
bool CAnimations::TextOnBG(const int id,
                           const string text,
                           const int x,
                           const int y,
                           const ENUM_TEXT_ANCHOR anchor,
                           const color clr,
                           const uchar opacity,
                           const bool create_new=true,
                           const bool redraw=false)
  {
   CFrameText *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_TEXT,create_new);
   if(frame==NULL)
      return false;
   return frame.TextOnBG(text,x,y,anchor,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+

このメソッドは、オブジェクトID、表示されたテキストパラメータ(テキスト自体、X座標とY座標、アンカーポイント、色、不透明度)、指定されたIDで新しいオブジェクトを作成する必要があることを示すフラグを受け取ります。 IDがリストに存在せず、チャートの再描画フラグが表示されます。
次に、必要なオブジェクトへのポインタを取得します(または、オブジェクトがない場合はオブジェクトを作成します)。ポインタの取得に失敗した場合は、falseを返します
ポインタを受け取った場合は、取得したテキストアニメーションフレームオブジェクトのTextOnBG()メソッドの結果を返します
<分節4170>

以下は、指定された座標で点の色を設定するメソッドです。

//+------------------------------------------------------------------+
//| Set the color of the dot with the specified coordinates          |
//+------------------------------------------------------------------+
bool CAnimations::SetPixelOnBG(const int id,const int x,const int y,const color clr,const uchar opacity=255,const bool create_new=true,const bool redraw=false)
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.SetPixelOnBG(x,y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+

メソッドのロジックは、上記で検討したメソッドと同じです。このメソッドは、オブジェクトID、描画された形状のX座標とY座標、その色と不透明度、指定されたIDを持つオブジェクトがリストに存在しない場合にそのIDを持つ新しいオブジェクトを作成する必要があることを示すフラグ、チャートの再描画フラグを受け取ります。
次に、必要なオブジェクトへのポインタを取得します(または、オブジェクトがない場合はオブジェクトを作成します)。ポインタの取得に失敗した場合は、falseを返します
ポインタを受け取った場合は、取得したアニメーション長方形フレームオブジェクトのSetPixelOnBG()メソッドの結果を返します

以下は、プリミティブを描画する他のメソッドです。

残りの形状描画メソッドのロジックは、上記で検討したメソッドと同じです。コードをみてみましょう。

//+------------------------------------------------------------------+
//| Draw a segment of a vertical line                                |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineVerticalOnBG(const int id,                 // Frame ID
                           const int   x,                            // Segment X coordinate
                           const int   y1,                           // Y coordinate of the segment first point
                           const int   y2,                           // Y coordinate of the segment second point
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineVerticalOnBG(x,y1,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a segment of a horizontal line                              |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineHorizontalOnBG(const int id,               // Frame ID
                           const int   x1,                           // X coordinate of the segment first point
                           const int   x2,                           // X coordinate of the segment second point
                           const int   y,                            // Segment Y coordinate
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineHorizontalOnBG(x1,x2,y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a segment of a freehand line                                |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineOnBG(const int id,                         // Frame ID
                           const int   x1,                           // X coordinate of the segment first point
                           const int   y1,                           // Y coordinate of the segment first point
                           const int   x2,                           // X coordinate of the segment second point
                           const int   y2,                           // Y coordinate of the segment second point
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a polyline                                                  |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineOnBG(const int id,                     // Frame ID
                           int         &array_x[],                   // Array with the X coordinates of polyline points
                           int         &array_y[],                   // Array with the Y coordinates of polyline points
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineOnBG(array_x,array_y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw the rectangle                                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonOnBG(const int id,                      // Frame ID
                           int         &array_x[],                   // Array with the X coordinates of polygon points
                           int         &array_y[],                   // Array with the Y coordinates of polygon points
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonOnBG(array_x,array_y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a rectangle using two points                                |
//+------------------------------------------------------------------+
bool CAnimations::DrawRectangleOnBG(const int id,                    // Frame ID
                           const int   x1,                           // X coordinate of the first point defining the rectangle
                           const int   y1,                           // Y coordinate of the first point defining the rectangle
                           const int   x2,                           // X coordinate of the second point defining the rectangle
                           const int   y2,                           // Y coordinate of the second point defining the rectangle
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawRectangleOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw the circle                                                  |
//+------------------------------------------------------------------+
bool CAnimations::DrawCircleOnBG(const int id,                       // Frame ID
                           const int   x,                            // X coordinate of the circle center
                           const int   y,                            // Y coordinate of the circle center
                           const int   r,                            // Circle radius
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawCircleOnBG(x,y,r,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a triangle                                                  |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleOnBG(const int id,                     // Frame ID
                           const int   x1,                           // X coordinate of the triangle first vertex
                           const int   y1,                           // Y coordinate of the triangle first vertex
                           const int   x2,                           // X coordinate of the triangle second vertex
                           const int   y2,                           // Y coordinate of the triangle second vertex
                           const int   x3,                           // X coordinate of the triangle third vertex
                           const int   y3,                           // Y coordinate of the triangle third vertex
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw an ellipse using two points                                 |
//+------------------------------------------------------------------+
bool CAnimations::DrawEllipseOnBG(const int id,                      // Frame ID
                           const int   x1,                           // X coordinate of the first point defining the ellipse
                           const int   y1,                           // Y coordinate of the first point defining the ellipse
                           const int   x2,                           // X coordinate of the second point defining the ellipse
                           const int   y2,                           // Y coordinate of the second point defining the ellipse
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawEllipseOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw an arc of an ellipse inscribed in a rectangle               |
//| with the corners in (x1,y1) and (x2,y2).                         |
//| The arc boundaries are cropped from the ellipse center           |
//| moving to two points with the coordinates of (x3,y3) and (x4,y4) |
//+------------------------------------------------------------------+
bool CAnimations::DrawArcOnBG(const int id,                          // Frame ID
                           const int   x1,                           // X coordinate of the top left corner forming the rectangle
                           const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                           const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                           const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                           const int   x3,                           // X coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                           const int   y3,                           // Y coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                           const int   x4,                           // X coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                           const int   y4,                           // Y coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawArcOnBG(x1,y1,x2,y2,x3,y3,x4,y4,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a filled sector of an ellipse inscribed in a rectangle      |
//| with the corners in (x1,y1) and (x2,y2).                         |
//| The sector boundaries are cropped from the ellipse center,       |
//| moving to two points with the coordinates of (x3,y3) and (x4,y4) |
//+------------------------------------------------------------------+
bool CAnimations::DrawPieOnBG(const int id,                          // Frame ID
                           const int   x1,                           // X coordinate of the upper left corner of the rectangle
                           const int   y1,                           // Y coordinate of the upper left corner of the rectangle
                           const int   x2,                           // X coordinate of the bottom right corner of the rectangle
                           const int   y2,                           // Y coordinate of the bottom right corner of the rectangle
                           const int   x3,                           // X coordinate of the first point to find the arc boundaries
                           const int   y3,                           // Y coordinate of the first point to find the arc boundaries
                           const int   x4,                           // X coordinate of the second point to find the arc boundaries
                           const int   y4,                           // Y coordinate of the second point to find the arc boundaries
                           const color clr,                          // Color
                           const color fill_clr,                     // Fill color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPieOnBG(x1,y1,x2,y2,x3,y3,x4,y4,clr,fill_clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Fill in the area                                                 |
//+------------------------------------------------------------------+
bool CAnimations::FillOnBG(const int   id,                           // Frame ID
                           const int   x,                            // X coordinate of the filling start point
                           const int   y,                            // Y coordinate of the filling start point
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const uint  threshould=0,                 // Threshold
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.FillOnBG(x,y,clr,opacity,threshould,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a filled rectangle                                          |
//+------------------------------------------------------------------+
bool CAnimations::DrawRectangleFillOnBG(const int id,                // Frame ID
                           const int   x1,                           // X coordinate of the first point defining the rectangle
                           const int   y1,                           // Y coordinate of the first point defining the rectangle
                           const int   x2,                           // X coordinate of the second point defining the rectangle
                           const int   y2,                           // Y coordinate of the second point defining the rectangle
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawRectangleFillOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a filled circle                                             |
//+------------------------------------------------------------------+
bool CAnimations::DrawCircleFillOnBG(const int id,                   // Frame ID
                           const int   x,                            // X coordinate of the circle center
                           const int   y,                            // Y coordinate of the circle center
                           const int   r,                            // Circle radius
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawCircleFillOnBG(x,y,r,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a filled triangle                                           |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleFillOnBG(const int id,                 // Frame ID
                           const int   x1,                           // X coordinate of the triangle first vertex
                           const int   y1,                           // Y coordinate of the triangle first vertex
                           const int   x2,                           // X coordinate of the triangle second vertex
                           const int   y2,                           // Y coordinate of the triangle second vertex
                           const int   x3,                           // X coordinate of the triangle third vertex
                           const int   y3,                           // Y coordinate of the triangle third vertex
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleFillOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a filled polygon                                            |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonFillOnBG(const int id,                  // Frame ID
                           int         &array_x[],                   // Array with the X coordinates of polygon points
                           int         &array_y[],                   // Array with the Y coordinates of polygon points
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonFillOnBG(array_x,array_y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a filled ellipse inscribed in a rectangle                   |
//| with the given coordinates                                       |
//+------------------------------------------------------------------+
bool CAnimations::DrawEllipseFillOnBG(const int id,                  // Frame ID
                           const int   x1,                           // X coordinate of the top left corner forming the rectangle
                           const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                           const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                           const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false)                 // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawEllipseFillOnBG(x1,y1,x2,y2,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a point using AntiAliasing algorithm                        |
//+------------------------------------------------------------------+
bool CAnimations::SetPixelAAOnBG(const int id,                       // Frame ID
                           const double x,                           // Point X coordinate
                           const double y,                           // Point Y coordinate
                           const color  clr,                         // Color
                           const uchar  opacity=255,                 // Opacity
                           const bool   create_new=true,             // New object creation flag
                           const bool   redraw=false)                // Chart redraw flag
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.SetPixelAAOnBG(x,y,clr,opacity,redraw);
  }
//+------------------------------------------------------------------+
//| Draw a segment of a freehand line using the                      |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineAAOnBG(const int id,                       // Frame ID
                           const int   x1,                           // X coordinate of the segment first point
                           const int   y1,                           // Y coordinate of the segment first point
                           const int   x2,                           // X coordinate of the segment second point
                           const int   y2,                           // Y coordinate of the segment second point
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineAAOnBG(x1,y1,x2,y2,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a segment of a freehand line using the                      |
//| Wu algorithm                                                     |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineWuOnBG(const int id,                       // Frame ID
                           const int   x1,                           // X coordinate of the segment first point
                           const int   y1,                           // Y coordinate of the segment first point
                           const int   x2,                           // X coordinate of the segment second point
                           const int   y2,                           // Y coordinate of the segment second point
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineWuOnBG(x1,y1,x2,y2,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a  segment of a freehand line having a specified width      |
//| using a smoothing algorithm                                      |
//| with the preliminary sorting                                     |
//+------------------------------------------------------------------+
bool CAnimations::DrawLineThickOnBG(const int id,                    // Frame ID
                           const int   x1,                           // X coordinate of the segment first point
                           const int   y1,                           // Y coordinate of the segment first point
                           const int   x2,                           // X coordinate of the segment second point
                           const int   y2,                           // Y coordinate of the segment second point
                           const int   size,                         // Line width
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                           ENUM_LINE_END end_style=LINE_END_ROUND)   // Line style is one of the ENUM_LINE_END enumeration's values
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineThickOnBG(x1,y1,x2,y2,size,clr,opacity,redraw,style,end_style);
  }
//+---------------------------------------------------------------------+
//| Draw a vertical segment of a freehand line having a specified width |
//| using a smoothing algorithm                                         |
//| with the preliminary sorting                                        |
//+---------------------------------------------------------------------+
bool CAnimations::DrawLineThickVerticalOnBG(const int id,            // Frame ID
                           const int   x,                            // Segment X coordinate
                           const int   y1,                           // Y coordinate of the segment first point
                           const int   y2,                           // Y coordinate of the segment second point
                           const int   size,                         // line width
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                           const ENUM_LINE_END end_style=LINE_END_ROUND) // Line style is one of the ENUM_LINE_END enumeration's values
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineThickVerticalOnBG(x,y1,y2,size,clr,opacity,redraw,style,end_style);
  }
//+-----------------------------------------------------------------------+
//| Draws a horizontal segment of a freehand line having a specified width|
//| using a smoothing algorithm                                           |
//| with the preliminary sorting                                          |
//+-----------------------------------------------------------------------+
bool CAnimations::DrawLineThickHorizontalOnBG(const int id,          // Frame ID
                           const int   x1,                           // X coordinate of the segment first point
                           const int   x2,                           // X coordinate of the segment second point
                           const int   y,                            // Segment Y coordinate
                           const int   size,                         // line width
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                           const ENUM_LINE_END end_style=LINE_END_ROUND) // Line style is one of the ENUM_LINE_END enumeration's values
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawLineThickHorizontalOnBG(x1,x2,y,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Draw a polyline using                                            |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineAAOnBG(const int id,                   // Frame ID
                           int         &array_x[],                   // Array with the X coordinates of polyline points
                           int         &array_y[],                   // Array with the Y coordinates of polyline points
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineAAOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draws a polyline using Wu algorithm                              |
//+------------------------------------------------------------------+
//--- 
bool CAnimations::DrawPolylineWuOnBG(const int id,                   // Frame ID
                           int         &array_x[],                   // Array with the X coordinates of polyline points
                           int         &array_y[],                   // Array with the Y coordinates of polyline points
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineWuOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a polyline with a specified width using                     |
//| two smoothing algorithms in series.                              |
//| First, individual segments are smoothed                          |
//| based on Bezier curves.                                          |
//| Then, to improve the rendering quality,                          |
//| a raster smoothing algorithm                                     |
//| made of the polyline segments is applied                                                              |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineSmoothOnBG(const int id,               // Frame ID
                           const int    &array_x[],                  // Array with the X coordinates of polyline points
                           const int    &array_y[],                  // Array with the Y coordinates of polyline points
                           const int    size,                        // Line width
                           const color  clr,                         // Color
                           const uchar  opacity=255,                 // Opacity
                           const double tension=0.5,                 // Smoothing parameter value
                           const double step=10,                     // Approximation step
                           const bool   create_new=true,             // New object creation flag
                           const bool   redraw=false,                // Chart redraw flag
                           const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                           const ENUM_LINE_END   end_style=LINE_END_ROUND) // Line style is one of the ENUM_LINE_END enumeration's values
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineSmoothOnBG(array_x,array_y,size,clr,opacity,tension,step,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Draw a polyline with a specified width using                     |
//| a smoothing algorithm with the preliminary sorting               |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolylineThickOnBG(const int id,                // Frame ID
                           const int      &array_x[],                // Array with the X coordinates of polyline points
                           const int      &array_y[],                // Array with the Y coordinates of polyline points
                           const int      size,                      // Line width
                           const color    clr,                       // Color
                           const uchar    opacity=255,               // Opacity
                           const bool     create_new=true,           // New object creation flag
                           const bool     redraw=false,              // Chart redraw flag
                           const uint     style=STYLE_SOLID,         // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                           ENUM_LINE_END  end_style=LINE_END_ROUND)  // Line style is one of the ENUM_LINE_END enumeration's values
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolylineThickOnBG(array_x,array_y,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Draw a polygon using                                             |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonAAOnBG(const int id,                    // Frame ID
                           int         &array_x[],                   // Array with the X coordinates of polygon points
                           int         &array_y[],                   // Array with the Y coordinates of polygon points
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonAAOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a polygon using Wu algorithm                                |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonWuOnBG(const int id,                    // Frame ID
                           int         &array_x[],                   // Array with the X coordinates of polygon points
                           int         &array_y[],                   // Array with the Y coordinates of polygon points
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonWuOnBG(array_x,array_y,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a polygon with a specified width using                      |
//| two smoothing algorithms in series.                              |
//| First, individual segments are smoothed based on Bezier curves.  |
//| Then, to improve the rendering quality,                          |
//| a raster smoothing algorithm is applied                          |
//| made of the polyline segments.                                   |
//+------------------------------------------------------------------+
bool CAnimations::DrawPolygonSmoothOnBG(const int id,                // Frame ID
                           int          &array_x[],                  // Array with the X coordinates of polyline points
                           int          &array_y[],                  // Array with the Y coordinates of polyline points
                           const int    size,                        // Line width
                           const color  clr,                         // Color
                           const uchar  opacity=255,                 // Opacity
                           const double tension=0.5,                 // Smoothing parameter value
                           const double step=10,                     // Approximation step
                           const bool   create_new=true,             // New object creation flag
                           const bool   redraw=false,                // Chart redraw flag
                           const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                           const ENUM_LINE_END   end_style=LINE_END_ROUND) // Line style is one of the ENUM_LINE_END enumeration's values
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonSmoothOnBG(array_x,array_y,size,clr,opacity,tension,step,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Draw a polygon with a specified width using                      |
//| a smoothing algorithm with the preliminary sorting               |
//+------------------------------------------------------------------+
//--- Draw a polygon having a specified width using smoothing algorithm with the preliminary filtration
bool CAnimations::DrawPolygonThickOnBG(const int id,                 // Frame ID
                           const int   &array_x[],                   // array with the X coordinates of polygon points
                           const int   &array_y[],                   // array with the Y coordinates of polygon points
                           const int   size,                         // line width
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=STYLE_SOLID,            // line style

                           ENUM_LINE_END end_style=LINE_END_ROUND)   // line ends style
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawPolygonThickOnBG(array_x,array_y,size,clr,opacity,redraw,style,end_style);
  }
//+------------------------------------------------------------------+
//| Draw a triangle using                                            |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleAAOnBG(const int id,                   // Frame ID
                           const int   x1,                           // X coordinate of the triangle first vertex
                           const int   y1,                           // Y coordinate of the triangle first vertex
                           const int   x2,                           // X coordinate of the triangle second vertex
                           const int   y2,                           // Y coordinate of the triangle second vertex
                           const int   x3,                           // X coordinate of the triangle third vertex
                           const int   y3,                           // Y coordinate of the triangle third vertex
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleAAOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a triangle using Wu algorithm                               |
//+------------------------------------------------------------------+
bool CAnimations::DrawTriangleWuOnBG(const int id,                   // Frame ID
                           const int   x1,                           // X coordinate of the triangle first vertex
                           const int   y1,                           // Y coordinate of the triangle first vertex
                           const int   x2,                           // X coordinate of the triangle second vertex
                           const int   y2,                           // Y coordinate of the triangle second vertex
                           const int   x3,                           // X coordinate of the triangle third vertex
                           const int   y3,                           // Y coordinate of the triangle third vertex
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawTriangleWuOnBG(x1,y1,x2,y2,x3,y3,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a circle using                                              |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CAnimations::DrawCircleAAOnBG(const int id,                     // Frame ID
                           const int    x,                           // X coordinate of the circle center
                           const int    y,                           // Y coordinate of the circle center
                           const double r,                           // Circle radius
                           const color  clr,                         // Color
                           const uchar  opacity=255,                 // Opacity
                           const bool   create_new=true,             // New object creation flag
                           const bool   redraw=false,                // Chart redraw flag
                           const uint   style=UINT_MAX)              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawCircleAAOnBG(x,y,r,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw a circle using Wu algorithm                                 |
//+------------------------------------------------------------------+
bool CAnimations::DrawCircleWuOnBG(const int id,                     // Frame ID
                           const int    x,                           // X coordinate of the circle center
                           const int    y,                           // Y coordinate of the circle center
                           const double r,                           // Circle radius
                           const color  clr,                         // Color
                           const uchar  opacity=255,                 // Opacity
                           const bool   create_new=true,             // New object creation flag
                           const bool   redraw=false,                // Chart redraw flag
                           const uint   style=UINT_MAX)              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawCircleWuOnBG(x,y,r,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw an ellipse using two points while applying                  |
//| AntiAliasing algorithm                                           |
//+------------------------------------------------------------------+
bool CAnimations::DrawEllipseAAOnBG(const int id,                    // Frame ID
                           const double x1,                          // X coordinate of the first point defining the ellipse
                           const double y1,                          // Y coordinate of the first point defining the ellipse
                           const double x2,                          // X coordinate of the second point defining the ellipse
                           const double y2,                          // Y coordinate of the second point defining the ellipse
                           const color  clr,                         // Color
                           const uchar  opacity=255,                 // Opacity
                           const bool   create_new=true,             // New object creation flag
                           const bool   redraw=false,                // Chart redraw flag
                           const uint   style=UINT_MAX)              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawEllipseAAOnBG(x1,y1,x2,y2,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+
//| Draw an ellipse using two points                                 |
//| using Wu algorithm                     |
//+------------------------------------------------------------------+
bool CAnimations::DrawEllipseWuOnBG(const int id,                    // Frame ID
                           const int   x1,                           // X coordinate of the first point defining the ellipse
                           const int   y1,                           // Y coordinate of the first point defining the ellipse
                           const int   x2,                           // X coordinate of the second point defining the ellipse
                           const int   y2,                           // Y coordinate of the second point defining the ellipse
                           const color clr,                          // Color
                           const uchar opacity=255,                  // Opacity
                           const bool  create_new=true,              // New object creation flag
                           const bool  redraw=false,                 // Chart redraw flag
                           const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
  {
   CFrameQuad *frame=this.GetOrCreateFrame(DFUN,id,ANIMATION_FRAME_TYPE_QUAD,create_new);
   if(frame==NULL)
      return false;
   return frame.DrawEllipseWuOnBG(x1,y1,x2,y2,clr,opacity,redraw,style);
  }
//+------------------------------------------------------------------+


新しく作成されたアニメーションオブジェクトのクラスは、フォームオブジェクトの不可欠な部分であるため、各フォームには、画像を作成する独自のメソッドがあります。

フォームオブジェクトクラスの\MQL5\Include\DoEasy\Objects\Graph\Form.mqhファイルを開き、必要な改善を追加します。

アニメーションオブジェクトクラスのファイルをインクルードします

//+------------------------------------------------------------------+
//|                                                         Form.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "GCnvElement.mqh"
#include "ShadowObj.mqh"
#include "Animations\Animations.mqh"
//+------------------------------------------------------------------+

ピクセルコピーオブジェクトクラスを削除します(別のファイルに移動しました):

//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "GCnvElement.mqh"
#include "ShadowObj.mqh"
#include "Animations\Animations.mqh"
//+------------------------------------------------------------------+
//| Pixel copier class                                               |
//+------------------------------------------------------------------+
class CPixelCopier : public CObject
  {
private:
...
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Form object class                                                |
//+------------------------------------------------------------------+

クラスのprivateセクションで、ピクセルコピー機リストの代わりに

CArrayObj         m_list_pc_obj;                            // List of pixel copier objects

アニメーションクラスオブジェクトへのポインタを宣言します

//+------------------------------------------------------------------+
//|                                                         Form.mqh |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "GCnvElement.mqh"
#include "ShadowObj.mqh"
#include "Animations\Animations.mqh"
//+------------------------------------------------------------------+
//| Form object class                                                |
//+------------------------------------------------------------------+
class CForm : public CGCnvElement
  {
private:
   CArrayObj         m_list_elements;                          // List of attached elements
   CAnimations      *m_animations;                             // Pointer to the animation object
   CShadowObj       *m_shadow_obj;                             // Pointer to the shadow object
   color             m_color_frame;                            // Form frame color
   int               m_frame_width_left;                       // Form frame width to the left
   int               m_frame_width_right;                      // Form frame width to the right
   int               m_frame_width_top;                        // Form frame width at the top
   int               m_frame_width_bottom;                     // Form frame width at the bottom

//--- Initialize the variables
   void              Initialize(void);
//--- Return the name of the dependent object
   string            CreateNameDependentObject(const string base_name)  const
                       { return ::StringSubstr(this.NameObj(),::StringLen(::MQLInfoString(MQL_PROGRAM_NAME))+1)+"_"+base_name;   }
   
//--- Create a new graphical object
   CGCnvElement     *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                      const int element_num,
                                      const string name,
                                      const int x,
                                      const int y,
                                      const int w,
                                      const int h,
                                      const color colour,
                                      const uchar opacity,
                                      const bool movable,
                                      const bool activity);

//--- Create a shadow object
   void              CreateShadowObj(const color colour,const uchar opacity);
   
public:

すでに不要なIsPresentPC()メソッドの宣言をprivateセクションから削除し、その実装をコードリストから削除します。

//--- Create a shadow object
   void              CreateShadowObj(const color colour,const uchar opacity);
   
//--- Return the flag indicating the presence of the copier object with the specified ID in the list
   bool              IsPresentPC(const int id);

public:

クラスのpublicセクションから不要なメソッドを削除します

//--- Return (1) itself, the list of (2) attached objects, (3) pixel copier objects and (4) the shadow object
   CForm            *GetObject(void)                                          { return &this;                  }
   CArrayObj        *GetList(void)                                            { return &this.m_list_elements;  }
   CArrayObj        *GetListPC(void)                                          { return &this.m_list_pc_obj;    }
   CGCnvElement     *GetShadowObj(void)                                       { return this.m_shadow_obj;      }

およびアニメーションオブジェクトへのポインタとテキストおよび長方形のアニメーションフレームのリストを返す新しいメソッドを追加します

   CGCnvElement     *GetShadowObj(void)                                       { return this.m_shadow_obj;      }
//--- Return the pointer to (1) the animation object, the list of (2) text and (3) rectangle animation frames
   CAnimations      *GetAnimationsObj(void)                                   { return this.m_animations;      }
   CArrayObj        *GetListFramesText(void)
                       { return(this.m_animations!=NULL ? this.m_animations.GetListFramesText() : NULL);       }
   CArrayObj        *GetListFramesQuad(void)
                       { return(this.m_animations!=NULL ? this.m_animations.GetListFramesQuad() : NULL);       }
   
//--- Set the form (1) color scheme and (2) style

新しいピクセルコピーオブジェクトを作成するためのメソッドの宣言を削除します

//--- Create a new pixel copier object
   CPixelCopier     *CreateNewPixelCopier(const int id,const int x_coord,const int y_coord,const int width,const int height);

//--- Draw an object shadow

クラス本体の外部に記述されたメソッドの実装も削除されます。

クラスのpublicセクションにある画像ピクセルを操作するためのメソッドのブロックで、アニメーションフレームオブジェクトを作成するための新しいメソッドを記述し、作成されたオブジェクトへのポインタを返し、背景を保存および復元するメソッドを描画します。

//+------------------------------------------------------------------+
//| Methods of working with image pixels                             |
//+------------------------------------------------------------------+
//--- Create a new (1) rectangle and (2) text animation frame object
   bool              CreateNewFrameText(const int id,const int x_coord,const int y_coord,const string text)
                       { return(this.m_animations!=NULL ? this.m_animations.CreateNewFrameText(id)!=NULL : false);            }
                       
   bool              CreateNewFrameQuad(const int id,const int x_coord,const int y_coord,const int width,const int height)
                       { return(this.m_animations!=NULL ? this.m_animations.CreateNewFrameQuad(id)!=NULL : false);            }
                       
//--- Return the frame object of the (1) text and (2) rectangle animation by ID
   CFrame           *GetFrameText(const int id)
                       { return(this.m_animations!=NULL ? this.m_animations.GetFrame(ANIMATION_FRAME_TYPE_TEXT,id) : NULL);   }
                       
   CFrame           *GetFrameQuad(const int id)
                       { return(this.m_animations!=NULL ? this.m_animations.GetFrame(ANIMATION_FRAME_TYPE_QUAD,id) : NULL);   }
                       
//--- Display the text on the background while saving and restoring the background
   bool              TextOnBG(const int id,
                              const string text,
                              const int x,
                              const int y,
                              const ENUM_TEXT_ANCHOR anchor,
                              const color clr,
                              const uchar opacity=255,
                              const bool create_new=true,
                              const bool redraw=false)
                       { return(this.m_animations!=NULL ? this.m_animations.TextOnBG(id,text,x,y,anchor,clr,opacity,create_new,redraw) : false);  }

//--- Set the color of the point with the specified coordinates while saving and restoring the background
   bool              SetPixelOnBG(const int id,const int x,const int y,const color clr,const uchar opacity=255,const bool create_new=true,const bool redraw=false)
                       { return(this.m_animations!=NULL ? this.m_animations.SetPixelOnBG(id,x,y,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a segment of a vertical line
   bool              DrawLineVerticalOnBG(const int id,                 // Frame ID
                              const int   x,                            // Segment X coordinate
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineVerticalOnBG(id,x,y1,y2,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a segment of a horizontal line while saving and restoring the background
   bool              DrawLineHorizontalOnBG(const int id,               // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y,                            // Segment Y coordinate
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineHorizontalOnBG(id,x1,x2,y,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a segment of a freehand line while saving and restoring the background
   bool              DrawLineOnBG(const int id,                         // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a polyline while saving and restoring the background
   bool              DrawPolylineOnBG(const int id,                     // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolylineOnBG(id,array_x,array_y,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a polygon while saving and restoring the background
   bool              DrawPolygonOnBG(const int id,                      // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolygonOnBG(id,array_x,array_y,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a rectangle by two points while saving and restoring the background
   bool              DrawRectangleOnBG(const int id,                    // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the rectangle
                              const int   y1,                           // Y coordinate of the first point defining the rectangle
                              const int   x2,                           // X coordinate of the second point defining the rectangle
                              const int   y2,                           // Y coordinate of the second point defining the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawRectangleOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a circle while saving and restoring the background
   bool              DrawCircleOnBG(const int id,                       // Frame ID
                              const int   x,                            // X coordinate of the circle center
                              const int   y,                            // Y coordinate of the circle center
                              const int   r,                            // Circle radius
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawCircleOnBG(id,x,y,r,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a triangle while saving and restoring the background
   bool              DrawTriangleOnBG(const int id,                     // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawTriangleOnBG(id,x1,y1,x2,y2,x3,y3,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw an ellipse by two points while saving and restoring the background
   bool              DrawEllipseOnBG(const int id,                      // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the ellipse
                              const int   y1,                           // Y coordinate of the first point defining the ellipse
                              const int   x2,                           // X coordinate of the second point defining the ellipse
                              const int   y2,                           // Y coordinate of the second point defining the ellipse
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawEllipseOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw an arc of an ellipse inscribed in a rectangle with corners at (x1,y1) and (x2,y2) while saving and restoring the background.
//--- The arc boundaries are clipped by lines from the center of the ellipse, which extend to two points with coordinates (x3,y3) and (x4,y4)
   bool              DrawArcOnBG(const int id,                          // Frame ID
                              const int   x1,                           // X coordinate of the top left corner forming the rectangle
                              const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                              const int   x3,                           // X coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   y3,                           // Y coordinate of the first point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   x4,                           // X coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const int   y4,                           // Y coordinate of the second point, to which a line from the rectangle center is drawn in order to obtain the arc boundary
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawArcOnBG(id,x1,y1,x2,y2,x3,y3,x4,y4,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a filled sector of an ellipse inscribed in a rectangle with corners at (x1,y1) and (x2,y2) while saving and restoring the background.
//--- The sector boundaries are clipped by lines from the center of the ellipse, which extend to two points with coordinates (x3,y3) and (x4,y4)
   bool              DrawPieOnBG(const int id,                          // Frame ID
                              const int   x1,                           // X coordinate of the upper left corner of the rectangle
                              const int   y1,                           // Y coordinate of the upper left corner of the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner of the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner of the rectangle
                              const int   x3,                           // X coordinate of the first point to find the arc boundaries
                              const int   y3,                           // Y coordinate of the first point to find the arc boundaries
                              const int   x4,                           // X coordinate of the second point to find the arc boundaries
                              const int   y4,                           // Y coordinate of the second point to find the arc boundaries
                              const color clr,                          // Color
                              const color fill_clr,                     // Fill color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPieOnBG(id,x1,y1,x2,y2,x3,y3,x4,y4,clr,fill_clr,opacity,create_new,redraw) : false);  }
                       
//--- Fill the area while saving and restoring the background
   bool              FillOnBG(const int   id,                           // Frame ID
                              const int   x,                            // X coordinate of the filling start point
                              const int   y,                            // Y coordinate of the filling start point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const uint  threshould=0,                 // Threshold
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.FillOnBG(id,x,y,clr,opacity,threshould,create_new,redraw) : false);  }
                       
//--- Draw a filled rectangle while saving and restoring the background
   bool              DrawRectangleFillOnBG(const int id,                // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the rectangle
                              const int   y1,                           // Y coordinate of the first point defining the rectangle
                              const int   x2,                           // X coordinate of the second point defining the rectangle
                              const int   y2,                           // Y coordinate of the second point defining the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawRectangleFillOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a filled circle while saving and restoring the background
   bool              DrawCircleFillOnBG(const int id,                   // Frame ID
                              const int   x,                            // X coordinate of the circle center
                              const int   y,                            // Y coordinate of the circle center
                              const int   r,                            // Circle radius
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawCircleFillOnBG(id,x,y,r,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a filled triangle while saving and restoring the background
   bool              DrawTriangleFillOnBG(const int id,                 // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawTriangleFillOnBG(id,x1,y1,x2,y2,x3,y3,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a filled polygon while saving and restoring the background
   bool              DrawPolygonFillOnBG(const int id,                  // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolygonFillOnBG(id,array_x,array_y,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a filled ellipse inscribed in a rectangle with the specified coordinates while saving and restoring the background
   bool              DrawEllipseFillOnBG(const int id,                  // Frame ID
                              const int   x1,                           // X coordinate of the top left corner forming the rectangle
                              const int   y1,                           // Y coordinate of the top left corner forming the rectangle
                              const int   x2,                           // X coordinate of the bottom right corner forming the rectangle
                              const int   y2,                           // Y coordinate of the bottom right corner forming the rectangle
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false)                 // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.DrawEllipseFillOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a point using AntiAliasing algorithm while saving and restoring the background
   bool              SetPixelAAOnBG(const int id,                       // Frame ID
                              const double x,                           // Point X coordinate
                              const double y,                           // Point Y coordinate
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false)                // Chart redraw flag
                       { return(this.m_animations!=NULL ? this.m_animations.SetPixelAAOnBG(id,x,y,clr,opacity,create_new,redraw) : false);  }
                       
//--- Draw a segment of a freehand line using AntiAliasing algorithm while saving and restoring the background
   bool              DrawLineAAOnBG(const int id,                       // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineAAOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a segment of a freehand line using Wu algorithm while saving and restoring the background
   bool              DrawLineWuOnBG(const int id,                       // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineWuOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration while saving and restoring the background
   bool              DrawLineThickOnBG(const int id,                    // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y2,                           // Y coordinate of the segment second point
                              const int   size,                         // Line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              ENUM_LINE_END end_style=LINE_END_ROUND)   // Line style is one of the ENUM_LINE_END enumeration's values
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineThickOnBG(id,x1,y1,x2,y2,size,clr,opacity,create_new,redraw,style,end_style) : false);  }
                       
//--- Draw a vertical segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration while saving and restoring the background
   bool              DrawLineThickVerticalOnBG(const int id,            // Frame ID
                              const int   x,                            // Segment X coordinate
                              const int   y1,                           // Y coordinate of the segment first point
                              const int   y2,                           // Y coordinate of the segment second point
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND) // Line style is one of the ENUM_LINE_END enumeration's values
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineThickVerticalOnBG(id,x,y1,y2,size,clr,opacity,create_new,redraw,style,end_style) : false);  }
                       
//--- Draw a horizontal segment of a freehand line having a specified width using smoothing algorithm with the preliminary filtration while saving and restoring the background
   bool              DrawLineThickHorizontalOnBG(const int id,          // Frame ID
                              const int   x1,                           // X coordinate of the segment first point
                              const int   x2,                           // X coordinate of the segment second point
                              const int   y,                            // Segment Y coordinate
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND) // Line style is one of the ENUM_LINE_END enumeration's values
                       { return(this.m_animations!=NULL ? this.m_animations.DrawLineThickHorizontalOnBG(id,x1,x2,y,size,clr,opacity,create_new,redraw,style,end_style) : false);  }
                       
//--- Draw a polyline using AntiAliasing algorithm while saving and restoring the background
   bool              DrawPolylineAAOnBG(const int id,                   // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolylineAAOnBG(id,array_x,array_y,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a polyline using Wu algorithm while saving and restoring the background
   bool              DrawPolylineWuOnBG(const int id,                   // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polyline points
                              int         &array_y[],                   // Array with the Y coordinates of polyline points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolylineWuOnBG(id,array_x,array_y,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a polyline with a specified width consecutively using two smoothing algorithms while saving and restoring the background.
//--- First, individual line segments are smoothed based on Bezier curves.
//--- Then, the raster antialiasing algorithm is applied to the polyline built from these segments to improve the rendering quality
   bool              DrawPolylineSmoothOnBG(const int id,               // Frame ID
                              const int    &array_x[],                  // Array with the X coordinates of polyline points
                              const int    &array_y[],                  // Array with the Y coordinates of polyline points
                              const int    size,                        // Line width
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const double tension=0.5,                 // Smoothing parameter value
                              const double step=10,                     // Approximation step
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND)// Line style is one of the ENUM_LINE_END enumeration's values
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolylineSmoothOnBG(id,array_x,array_y,size,clr,opacity,tension,step,create_new,redraw,style,end_style) : false);  }
                       
//--- Draw a polyline having a specified width using smoothing algorithm with the preliminary filtration while saving and restoring the background
   bool              DrawPolylineThickOnBG(const int id,                // Frame ID
                              const int     &array_x[],                 // Array with the X coordinates of polyline points
                              const int     &array_y[],                 // Array with the Y coordinates of polyline points
                              const int     size,                       // Line width
                              const color   clr,                        // Color
                              const uchar   opacity=255,                // Opacity
                              const bool    create_new=true,            // New object creation flag
                              const bool    redraw=false,               // Chart redraw flag
                              const uint    style=STYLE_SOLID,          // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              ENUM_LINE_END end_style=LINE_END_ROUND)   // Line style is one of the ENUM_LINE_END enumeration's values
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolylineThickOnBG(id,array_x,array_y,size,clr,opacity,create_new,redraw,style,end_style) : false);  }
                       
//--- Draw a polygon using AntiAliasing algorithm while saving and restoring the background
   bool              DrawPolygonAAOnBG(const int id,                    // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolygonAAOnBG(id,array_x,array_y,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a polygon using Wu algorithm while saving and restoring the background
   bool              DrawPolygonWuOnBG(const int id,                    // Frame ID
                              int         &array_x[],                   // Array with the X coordinates of polygon points
                              int         &array_y[],                   // Array with the Y coordinates of polygon points
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolygonWuOnBG(id,array_x,array_y,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a polygon with a specified width consecutively using two smoothing algorithms while saving and restoring the background.
//--- First, individual segments are smoothed based on Bezier curves.
//--- Then, the raster smoothing algorithm is applied to the polygon built from these segments to improve the rendering quality. 
   bool              DrawPolygonSmoothOnBG(const int id,                // Frame ID
                              int          &array_x[],                  // Array with the X coordinates of polyline points
                              int          &array_y[],                  // Array with the Y coordinates of polyline points
                              const int    size,                        // Line width
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const double tension=0.5,                 // Smoothing parameter value
                              const double step=10,                     // Approximation step
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const ENUM_LINE_STYLE style=STYLE_SOLID,  // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                              const ENUM_LINE_END end_style=LINE_END_ROUND)// Line style is one of the ENUM_LINE_END enumeration's values
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolygonSmoothOnBG(id,array_x,array_y,size,clr,opacity,tension,step,create_new,redraw,style,end_style) : false);  }
                       
//--- Draw a polygon of a specified width using a smoothing algorithm with the preliminary filtration while saving and restoring the background
   bool              DrawPolygonThickOnBG(const int id,                 // Frame ID
                              const int   &array_x[],                   // array with the X coordinates of polygon points
                              const int   &array_y[],                   // array with the Y coordinates of polygon points
                              const int   size,                         // line width
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=STYLE_SOLID,            // line style
                              ENUM_LINE_END end_style=LINE_END_ROUND)   // line ends style
                       { return(this.m_animations!=NULL ? this.m_animations.DrawPolygonThickOnBG(id,array_x,array_y,size,clr,opacity,create_new,redraw,style,end_style) : false);  }
                       
//--- Draw a triangle using AntiAliasing algorithm while saving and restoring the background
   bool              DrawTriangleAAOnBG(const int id,                   // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawTriangleAAOnBG(id,x1,y1,x2,y2,x3,y3,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a triangle using Wu algorithm while saving and restoring the background
   bool              DrawTriangleWuOnBG(const int id,                   // Frame ID
                              const int   x1,                           // X coordinate of the triangle first vertex
                              const int   y1,                           // Y coordinate of the triangle first vertex
                              const int   x2,                           // X coordinate of the triangle second vertex
                              const int   y2,                           // Y coordinate of the triangle second vertex
                              const int   x3,                           // X coordinate of the triangle third vertex
                              const int   y3,                           // Y coordinate of the triangle third vertex
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawTriangleWuOnBG(id,x1,y1,x2,y2,x3,y3,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a circle using AntiAliasing algorithm while saving and restoring the background
   bool              DrawCircleAAOnBG(const int id,                     // Frame ID
                              const int    x,                           // X coordinate of the circle center
                              const int    y,                           // Y coordinate of the circle center
                              const double r,                           // Circle radius
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX)              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawCircleAAOnBG(id,x,y,r,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw a circle using Wu algorithm while saving and restoring the background
   bool              DrawCircleWuOnBG(const int id,                     // Frame ID
                              const int    x,                           // X coordinate of the circle center
                              const int    y,                           // Y coordinate of the circle center
                              const double r,                           // Circle radius

                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX)              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawCircleWuOnBG(id,x,y,r,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw an ellipse by two points using AntiAliasing algorithm while saving and restoring the background
   bool              DrawEllipseAAOnBG(const int id,                    // Frame ID
                              const double x1,                          // X coordinate of the first point defining the ellipse
                              const double y1,                          // Y coordinate of the first point defining the ellipse
                              const double x2,                          // X coordinate of the second point defining the ellipse
                              const double y2,                          // Y coordinate of the second point defining the ellipse
                              const color  clr,                         // Color
                              const uchar  opacity=255,                 // Opacity
                              const bool   create_new=true,             // New object creation flag
                              const bool   redraw=false,                // Chart redraw flag
                              const uint   style=UINT_MAX)              // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawEllipseAAOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw,style) : false);  }
                       
//--- Draw an ellipse by two points using Wu algorithm while saving and restoring the background
   bool              DrawEllipseWuOnBG(const int id,                    // Frame ID
                              const int   x1,                           // X coordinate of the first point defining the ellipse
                              const int   y1,                           // Y coordinate of the first point defining the ellipse
                              const int   x2,                           // X coordinate of the second point defining the ellipse
                              const int   y2,                           // Y coordinate of the second point defining the ellipse
                              const color clr,                          // Color
                              const uchar opacity=255,                  // Opacity
                              const bool  create_new=true,              // New object creation flag
                              const bool  redraw=false,                 // Chart redraw flag
                              const uint  style=UINT_MAX)               // Line style is one of the ENUM_LINE_STYLE enumeration's values or a custom value
                       { return(this.m_animations!=NULL ? this.m_animations.DrawEllipseWuOnBG(id,x1,y1,x2,y2,clr,opacity,create_new,redraw,style) : false);  }
                       
//+------------------------------------------------------------------+

すべてのメソッドは、上記で作成したCAnimationsアニメーションオブジェクトから適切なメソッドの結果を返します。

クラスデストラクタで、アニメーションオブジェクトを削除します

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CForm::~CForm()
  {
   if(this.m_shadow_obj!=NULL)
      delete this.m_shadow_obj;
   if(this.m_animations!=NULL)
      delete this.m_animations;
  }
//+------------------------------------------------------------------+

初期化メソッドで、新しいアニメーションオブジェクトを作成します

//+------------------------------------------------------------------+
//| Initialize the variables                                         |
//+------------------------------------------------------------------+
void CForm::Initialize(void)
  {
   this.m_list_elements.Clear();
   this.m_list_elements.Sort();
   this.m_shadow_obj=NULL;
   this.m_shadow=false;
   this.m_frame_width_right=2;
   this.m_frame_width_left=2;
   this.m_frame_width_top=2;
   this.m_frame_width_bottom=2;
   this.m_animations=new CAnimations(CGCnvElement::GetObject());
  }
//+------------------------------------------------------------------+

これで、新しいフォームオブジェクトを作成するときに、新しいアニメーションオブジェクトが自動的に作成されます。新しいアニメーションフレームをアニメーションオブジェクトに動的に追加したり、事前定義されたフォームを作成したりできます。プログラムの実行が完了すると、メモリリークを回避するために、アニメーションオブジェクトが破棄されます。

作成したクラスをテストする準備ができました。

4つのフォームが描かれたテストEAがあります。4番目(下)のフォームをクリックすると、H-グラデーションラベルが移動します(H-水平塗りつぶしタイプの場合)。このラベルは、テキストアニメーションフレームオブジェクトとして作成および移動されます。3番目のフォーム(垂直塗りつぶし)は、さまざまな描画形状を表示するために使用されます。形状を描画する前に、まずフォームテキストをテキストアニメーションフレームとして表示します。その上に形状が描かれています。描画された形状の種類を切り替えるには、キーを押します。テキストには、選択した描画された形状が表示されます。形状をマウスでクリックするたびに、描画された形状の点の座標が変更されます。

検証

テストを実行するには、前の記事のEAを使用して、\MQL5\Experts\TestDoEasy\Part79\TestDoEasyPart79.mq5として保存します。

グローバル変数の領域で、描画された形状の初期座標を指定するためのマクロ置換を入力し、描画された形状のさまざまな点の座標およびそれらの変更値を格納するための変数を宣言します(合計5つの点が使用されます)

//+------------------------------------------------------------------+
//|                                             TestDoEasyPart79.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
//--- includes
#include <Arrays\ArrayObj.mqh>
#include <DoEasy\Services\Select.mqh>
#include <DoEasy\Objects\Graph\Form.mqh>
//--- defines
#define        FORMS_TOTAL (4)   // Number of created forms
#define        START_X     (4)   // Initial X coordinate of the shape
#define        START_Y     (4)   // Initial Y coordinate of the shape
//--- input parameters
sinput   bool              InpMovable     =  true;          // Movable forms flag
sinput   ENUM_INPUT_YES_NO InpUseColorBG  =  INPUT_YES;     // Use chart background color to calculate shadow color
sinput   color             InpColorForm3  =  clrCadetBlue;  // Third form shadow color (if not background color) 
//--- global variables
CArrayObj      list_forms;  
color          array_clr[];
int nx1=0, ny1=0, nx2=0, ny2=0, nx3=0, ny3=0, nx4=0, ny4=0, nx5=0, ny5=0;
int coordX1=START_X+nx1;
int coordY1=START_Y+ny1;
int coordX2=START_X+nx2*2;
int coordY2=START_Y+ny2*2;
int coordX3=START_X+nx3*3;
int coordY3=START_Y+ny3*3;
int coordX4=START_X+nx4*4;
int coordY4=START_Y+ny4*4;
int coordX5=START_X+nx5*5;
int coordY5=START_Y+ny5*5;
double RD=1;
//+------------------------------------------------------------------+

OnInit()ハンドラの最後の2つのフォームを作成するブロックでは、テキストはテキストアニメーションオブジェクトを使用して作成されます

      //--- If this is the third form
      if(i==2)
        {
         //--- Set the opacity of 200
         form.SetOpacity(200);
         //--- The form background color is set as the first color from the color array
         form.SetColorBackground(array_clr[0]);
         //--- Form outlining frame color
         form.SetColorFrame(clrDarkBlue);
         //--- Draw the shadow drawing flag
         form.SetShadow(true);
         //--- Calculate the shadow color as the chart background color converted to the monochrome one
         color clrS=form.ChangeColorSaturation(form.ColorBackground(),-100);
         //--- If the settings specify the usage of the chart background color, replace the monochrome color with 20 units
         //--- Otherwise, use the color specified in the settings for drawing the shadow
         color clr=(InpUseColorBG ? form.ChangeColorLightness(clrS,-20) : InpColorForm3);
         //--- Draw the form shadow with the right-downwards offset from the form by three pixels along all axes
         //--- Set the shadow opacity to 200, while the blur radius is equal to 4
         form.DrawShadow(3,3,clr,200,4);
         //--- Fill the form background with a vertical gradient
         form.Erase(array_clr,form.Opacity());
         //--- Draw an outlining rectangle at the edges of the form
         form.DrawRectangle(0,0,form.Width()-1,form.Height()-1,form.ColorFrame(),form.Opacity());
         
         //--- Display the text describing the gradient type and update the form
         //--- Text parameters: the text coordinates and the anchor point in the form center
         //--- Create a new text animation frame with the ID of 0 and display the text on the form
         form.TextOnBG(0,TextByLanguage("V-Градиент","V-Gradient"),form.Width()/2,form.Height()/2,TEXT_ANCHOR_CENTER,C'211,233,149',255,true,false);
        }
      //--- If this is the fourth (bottom) form
      if(i==3)
        {
         //--- Set the opacity of 200
         form.SetOpacity(200);
         //--- The form background color is set as the first color from the color array
         form.SetColorBackground(array_clr[0]);
         //--- Form outlining frame color
         form.SetColorFrame(clrDarkBlue);
         //--- Draw the shadow drawing flag
         form.SetShadow(true);
         //--- Calculate the shadow color as the chart background color converted to the monochrome one
         color clrS=form.ChangeColorSaturation(form.ColorBackground(),-100);
         //--- If the settings specify the usage of the chart background color, replace the monochrome color with 20 units
         //--- Otherwise, use the color specified in the settings for drawing the shadow
         color clr=(InpUseColorBG ? form.ChangeColorLightness(clrS,-20) : InpColorForm3);
         //--- Draw the form shadow with the right-downwards offset from the form by three pixels along all axes
         //--- Set the shadow opacity to 200, while the blur radius is equal to 4
         form.DrawShadow(3,3,clr,200,4);
         //--- Fill the form background with a horizontal gradient
         form.Erase(array_clr,form.Opacity(),false);
         //--- Draw an outlining rectangle at the edges of the form
         form.DrawRectangle(0,0,form.Width()-1,form.Height()-1,form.ColorFrame(),form.Opacity());
         
         //--- Display the text describing the gradient type and update the form
         //--- Text parameters: the text coordinates and the anchor point in the form center
         //--- Create a new text animation frame with the ID of 0 and display the text on the form
         form.TextOnBG(0,TextByLanguage("H-Градиент","H-Gradient"),form.Width()/2,form.Height()/2,TEXT_ANCHOR_CENTER,C'211,233,149',255,true,true);
        }
      //--- Add objects to the list

これらのテキストオブジェクトは事前にここで作成しました。描画された形状は、フォーム領域をクリックすると動的に作成されます。

キーストロークを処理するには、次のコードブロックをOnChartEvent()ハンドラに追加します。

//--- Drawing mode depending on the pressed key
   static ENUM_FIGURE_TYPE figure_type_prev=WRONG_VALUE;
   static ENUM_FIGURE_TYPE figure_type=figure_type_prev;
   string figure=FigureTypeDescription(figure_type);
//--- If a key is pressed
   if(id==CHARTEVENT_KEYDOWN)
     {
      //--- Get a drawn shape type depending on a pressed key
      figure_type=FigureType(lparam);
      //--- If the shape type has changed
      if(figure_type!=figure_type_prev)
        {
         //--- Get the text of the drawn shape type description
         figure=FigureTypeDescription(figure_type);
         //--- In the loop by all forms, 
         for(int i=0;i<list_forms.Total();i++)
           {
            //--- get the pointer to the next form object
            CForm *form=list_forms.At(i);
            if(form==NULL)
               continue;
            //--- If the form ID is 2,
            if(form.ID()==2)
              {
               //--- Reset all coordinate shifts to zero and display the text describing the drawn shape type
               nx1=ny1=nx2=ny2=nx3=ny3=nx4=ny4=nx5=ny5=0;
               form.TextOnBG(0,figure,form.TextLastX(),form.TextLastY(),form.TextAnchor(),C'211,233,149',255,false,true);
              }
           }
         //--- Write the new shape type
         figure_type_prev=figure_type;
        }
     }
  
//--- If clicking an object

フォームごとにクリック処理ブロックのコードを少し変更します。これで、テキストは、クリックされているフォームのテキストアニメーションオブジェクトを使用して表示されます

//--- If clicking an object
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- If the clicked object belongs to the EA
      if(StringFind(sparam,MQLInfoString(MQL_PROGRAM_NAME))==0)
        {
         //--- Get the object ID from it
         int form_id=(int)StringToInteger(StringSubstr(sparam,StringLen(sparam)-1))-1;
         //--- Find this form object in the loop by all forms created in the EA
         for(int i=0;i<list_forms.Total();i++)
           {
            CForm *form=list_forms.At(i);
            if(form==NULL)
               continue;
            //--- If the clicked object has the ID of 2 and the form has the same ID
            if(form_id==2 && form.ID()==2)
              {
               //--- Handle clicking the form - draw the corresponding shape
               FigureProcessing(form,figure_type);
              }
            
            //--- If the clicked object has the ID of 3 and the form has the same ID
            if(form_id==3 && form.ID()==3)
              {
               ////--- Get the anchor point of the last drawn text
               ENUM_TEXT_ANCHOR anchor=form.TextAnchor();
               ////--- Get the coordinates of the last drawn text
               int text_x=form.TextLastX();
               int text_y=form.TextLastY();
               //--- Set the text anchor initial point (0 = LEFT_TOP) out of nine possible ones
               static int n=0;
               //--- Depending on the n variable, set the new text anchor point
               switch(n)
                 {
                  case 0 : anchor=TEXT_ANCHOR_LEFT_TOP;     text_x=1;               text_y=1;               break;
                  case 1 : anchor=TEXT_ANCHOR_CENTER_TOP;   text_x=form.Width()/2;  text_y=1;               break;
                  case 2 : anchor=TEXT_ANCHOR_RIGHT_TOP;    text_x=form.Width()-2;  text_y=1;               break;
                  case 3 : anchor=TEXT_ANCHOR_LEFT_CENTER;  text_x=1;               text_y=form.Height()/2; break;
                  case 4 : anchor=TEXT_ANCHOR_CENTER;       text_x=form.Width()/2;  text_y=form.Height()/2; break;
                  case 5 : anchor=TEXT_ANCHOR_RIGHT_CENTER; text_x=form.Width()-2;  text_y=form.Height()/2; break;
                  case 6 : anchor=TEXT_ANCHOR_LEFT_BOTTOM;  text_x=1;               text_y=form.Height()-2; break;
                  case 7 : anchor=TEXT_ANCHOR_CENTER_BOTTOM;text_x=form.Width()/2;  text_y=form.Height()-2; break;
                  case 8 : anchor=TEXT_ANCHOR_RIGHT_BOTTOM; text_x=form.Width()-2;  text_y=form.Height()-2; break;
                  default: anchor=TEXT_ANCHOR_CENTER;       text_x=form.Width()/2;  text_y=form.Height()/2; break;
                 }
               form.TextOnBG(0,TextByLanguage("H-Градиент","H-Gradient"),text_x,text_y,anchor,C'211,233,149',255,true,true);
               //--- Increase the object click counter (and also the pointer to the text anchor point),
               //--- and if the value exceeds 8, reset the value to zero (from 0 to 8 = nine anchor points)
               n++;
               if(n>8) n=0;
              }
           }
        }
     }

3番目のフォーム(ID 2)のクリックは、FigureProcessing()関数で処理されます。4番目のフォーム(ID 3)をクリックすると、nに応じてテキストのアンカー角度を定義し、テキストを表示できます。ただし、テキストはテキストアニメーションフレームオブジェクトクラスを使用して表示されるようになりました

以下は、押されたキーに応じて形状タイプを返す補助関数です。

//+------------------------------------------------------------------+
//| Return the shape depending on the pressed key                    |
//+------------------------------------------------------------------+
ENUM_FIGURE_TYPE FigureType(const long key_code)
  {
   switch((int)key_code)
     {
      //--- "1" = Dot
      case 49  :  return FIGURE_TYPE_PIXEL;
      
      //--- "2" = Dot with AntiAlliasing
      case 50  :  return FIGURE_TYPE_PIXEL_AA;
      
      //--- "3" = Vertical line
      case 51  :  return FIGURE_TYPE_LINE_VERTICAL;
      
      //--- "4" = Vertical segment of a freehand line having a specified width using a smoothing algorithm
      case 52  :  return FIGURE_TYPE_LINE_VERTICAL_THICK;
      
      //--- "5" = Horizontal line
      case 53  :  return FIGURE_TYPE_LINE_HORIZONTAL;
      
      //--- "6" = Horizontal segment of a freehand line having a specified width using a smoothing algorithm
      case 54  :  return FIGURE_TYPE_LINE_HORIZONTAL_THICK;
      
      //--- "7" = Freehand line
      case 55  :  return FIGURE_TYPE_LINE;
      
      //--- "8" = Line with AntiAlliasing
      case 56  :  return FIGURE_TYPE_LINE_AA;
      
      //--- "9" = Line with WU
      case 57  :  return FIGURE_TYPE_LINE_WU;
      
      //--- "0" = Segment of a freehand line having a specified width using a smoothing algorithm
      case 48  :  return FIGURE_TYPE_LINE_THICK;
      
      //--- "q" = Polyline
      case 81  :  return FIGURE_TYPE_POLYLINE;
      
      //--- "w" = Polyline with AntiAlliasing
      case 87  :  return FIGURE_TYPE_POLYLINE_AA;
      
      //--- "e" = Polyline with WU
      case 69  :  return FIGURE_TYPE_POLYLINE_WU;
      
      //--- "r" = Polyline with a specified width using two smoothing algorithms
      case 82  :  return FIGURE_TYPE_POLYLINE_SMOOTH;
      
      //--- "t" = Polyline with a specified width using a smoothing algorithm
      case 84  :  return FIGURE_TYPE_POLYLINE_THICK;
      
      //--- "y" = Polygon
      case 89  :  return FIGURE_TYPE_POLYGON;
      
      //--- "u" = Filled polygon
      case 85  :  return FIGURE_TYPE_POLYGON_FILL;
      
      //--- "i" = Polygon with AntiAlliasing
      case 73  :  return FIGURE_TYPE_POLYGON_AA;
      
      //--- "o" = Polygon with WU
      case 79  :  return FIGURE_TYPE_POLYGON_WU;
      
      //--- "p" = Polygon with a specified width using two smoothing algorithms
      case 80  :  return FIGURE_TYPE_POLYGON_SMOOTH;
      
      //--- "a" = Polygon with a specified width using a smoothing algorithm
      case 65  :  return FIGURE_TYPE_POLYGON_THICK;
      
      //--- "s" = Rectangle
      case 83  :  return FIGURE_TYPE_RECTANGLE;
      
      //--- "d" = Filled rectangle
      case 68  :  return FIGURE_TYPE_RECTANGLE_FILL;
      
      //--- "f" = Circle
      case 70  :  return FIGURE_TYPE_CIRCLE;
      
      //--- "g" = Filled circle
      case 71  :  return FIGURE_TYPE_CIRCLE_FILL;
      
      //--- "h" = Circle with AntiAlliasing
      case 72  :  return FIGURE_TYPE_CIRCLE_AA;
      
      //--- "j" = Circle with WU
      case 74  :  return FIGURE_TYPE_CIRCLE_WU;
      
      //--- "k" = Triangle
      case 75  :  return FIGURE_TYPE_TRIANGLE;
      
      //--- "l" = Filled triangle
      case 76  :  return FIGURE_TYPE_TRIANGLE_FILL;
      
      //--- "z" = Triangle with AntiAlliasing
      case 90  :  return FIGURE_TYPE_TRIANGLE_AA;
      
      //--- "x" = Triangle with WU
      case 88  :  return FIGURE_TYPE_TRIANGLE_WU;
      
      //--- "c" = Ellipse
      case 67  :  return FIGURE_TYPE_ELLIPSE;
      
      //--- "v" = Filled ellipse
      case 86  :  return FIGURE_TYPE_ELLIPSE_FILL;
      
      //--- "b" = Ellipse with AntiAlliasing
      case 66  :  return FIGURE_TYPE_ELLIPSE_AA;
      
      //--- "n" = Ellipse with WU
      case 78  :  return FIGURE_TYPE_ELLIPSE_WU;
      
      //--- "m" = Ellipse arc
      case 77  :  return FIGURE_TYPE_ARC;
      
      //--- "," = Ellipse sector
      case 188 :  return FIGURE_TYPE_PIE;
      
      //--- Default = Dot
      default  :  return FIGURE_TYPE_PIXEL;
     }
  }
//+------------------------------------------------------------------+

フォームオブジェクトのクリックを処理する関数は非常にかさばりますが、描画されたフォームが対応する押された各ボタンを処理するスイッチオペレーターを備えているため、シンプルです。処理は簡単です。初期座標を設定し、許容値の範囲外であることを確認し、これらのパラメータを使用して図を描き、パラメータ値のシフトを増やします。次にフォームをクリックすると、前の形状が復元された背景で上書きされ、その点の新しい座標を使用して新しい形状が描画されます。

//+------------------------------------------------------------------+
//| Handle the selected shape                                        |
//+------------------------------------------------------------------+
void FigureProcessing(CForm *form,const ENUM_FIGURE_TYPE figure_type)
  {
   int array_x[5]={0,0,0,0,0};
   int array_y[5]={0,0,0,0,0};
   switch(figure_type)
     {
   //--- "1" = Dot
      case FIGURE_TYPE_PIXEL  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         form.SetPixelOnBG(0,coordX1,coordY1,clrWheat);
         nx1++;
         ny1++;
         break;
      
   //--- "2" = Dot with AntiAlliasing
      case FIGURE_TYPE_PIXEL_AA  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         form.SetPixelAAOnBG(0,coordX1,coordY1,clrWheat);
         nx1++;
         ny1++;
         break;
      
   //--- "3" = Vertical line
      case FIGURE_TYPE_LINE_VERTICAL  :
         coordX1=START_X+nx1;
         coordY1=START_Y;
         coordY2=form.Height()-START_Y-1;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         form.DrawLineVerticalOnBG(0,coordX1,coordY1,coordY2,clrWheat);
         nx1++;
         break;
      
   //--- "4" = Vertical segment of a freehand line having a specified width using a smoothing algorithm
      case FIGURE_TYPE_LINE_VERTICAL_THICK  :
         coordX1=START_X+nx1;
         coordY1=START_Y;
         coordY2=form.Height()-START_Y-1;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         form.DrawLineThickVerticalOnBG(0,coordX1,coordY1,coordY2,5,clrWheat,255,true,false,STYLE_SOLID,LINE_END_SQUARE);
         nx1++;
         break;
      
   //--- "5" = Horizontal line
      case FIGURE_TYPE_LINE_HORIZONTAL :
         coordX1=START_X;
         coordX2=form.Width()-START_X-1;
         coordY1=START_Y+ny1;
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         form.DrawLineHorizontalOnBG(0,coordX1,coordX2,coordY1,clrWheat);
         ny1++;
         break;
         
   //--- "6" = Horizontal segment of a freehand line having a specified width using a smoothing algorithm
      case FIGURE_TYPE_LINE_HORIZONTAL_THICK  :
         coordX1=START_X;
         coordX2=form.Width()-START_X-1;
         coordY1=START_Y+ny1;
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         form.DrawLineThickHorizontalOnBG(0,coordX1,coordX2,coordY1,5,clrWheat,255,true,false,STYLE_SOLID,LINE_END_ROUND);
         ny1++;
         break;
      
   //--- "7" = Freehand line
      case FIGURE_TYPE_LINE  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawLineOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "8" = Line with AntiAlliasing
      case FIGURE_TYPE_LINE_AA  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawLineAAOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "9" = Line with WU
      case FIGURE_TYPE_LINE_WU  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawLineWuOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "0" = Segment of a freehand line having a specified width using a smoothing algorithm
      case FIGURE_TYPE_LINE_THICK  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawLineThickOnBG(0,coordX1,coordY1,coordX2,coordY2,3,clrWheat,255,true,false,STYLE_SOLID,LINE_END_SQUARE);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "q" = Polyline
      case FIGURE_TYPE_POLYLINE  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolylineOnBG(0,array_x,array_y,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "w" = Polyline with AntiAlliasing
      case FIGURE_TYPE_POLYLINE_AA  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolylineAAOnBG(0,array_x,array_y,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "e" = Polyline with WU
      case FIGURE_TYPE_POLYLINE_WU  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolylineWuOnBG(0,array_x,array_y,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "r" = Polyline with a specified width using two smoothing algorithms
      case FIGURE_TYPE_POLYLINE_SMOOTH  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolylineSmoothOnBG(0,array_x,array_y,1,clrWheat,255,0.5,30.0,true,false,STYLE_SOLID,LINE_END_BUTT);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "t" = Polyline with a specified width using a smoothing algorithm
      case FIGURE_TYPE_POLYLINE_THICK  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolylineThickOnBG(0,array_x,array_y,3,clrWheat,255,true,false,STYLE_SOLID,LINE_END_BUTT);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "y" = Polygon
      case FIGURE_TYPE_POLYGON  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolygonOnBG(0,array_x,array_y,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "u" = Filled polygon
      case FIGURE_TYPE_POLYGON_FILL  :
         return;
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*4;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- Draw a shape
         form.DrawPolygonFillOnBG(0,array_x,array_y,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         break;
      
   //--- "i" = Polygon with AntiAlliasing
      case FIGURE_TYPE_POLYGON_AA  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolygonAAOnBG(0,array_x,array_y,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "o" = Polygon with WU
      case FIGURE_TYPE_POLYGON_WU  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolygonWuOnBG(0,array_x,array_y,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "p" = Polygon with a specified width using two smoothing algorithms
      case FIGURE_TYPE_POLYGON_SMOOTH  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolygonSmoothOnBG(0,array_x,array_y,3,clrWheat,255,0.5,10.0,true,false,STYLE_SOLID,LINE_END_BUTT);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "a" = Polygon with a specified width using a smoothing algorithm
      case FIGURE_TYPE_POLYGON_THICK  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*8;
         coordY2=coordY1;
         coordX3=coordX2;
         coordY3=coordY2+ny3*2;
         coordX4=coordX1;
         coordY4=coordY3;
         coordX5=coordX1;
         coordY5=coordY1;
         //--- Fill in the arrays with coordinate values
         array_x[0]=coordX1; array_x[1]=coordX2; array_x[2]=coordX3; array_x[3]=coordX4; array_x[4]=coordX5;
         array_y[0]=coordY1; array_y[1]=coordY2; array_y[2]=coordY3; array_y[3]=coordY4; array_y[4]=coordY5;
         //--- check x1 and y1 coordinates for being outside the form
         if(array_x[0]>form.Width()-START_X-1)
           {
            nx1=0;
            array_x[0]=START_X;
           }
         if(array_y[0]>form.Height()-START_Y-1)
           {
            ny1=0;
            array_y[0]=START_Y;
           }
         //--- check x2 and y2 coordinates for being outside the form
         if(array_x[1]>form.Width()-START_X-1)
           {
            nx2=0;
            array_x[1]=START_X;
           }
         if(array_y[1]>form.Height()-START_Y-1)
           {
            ny2=0;
            array_y[1]=array_y[0];
           }
         //--- check x3 and y3 coordinates for being outside the form
         if(array_x[2]>form.Width()-START_X-1)
           {
            nx3=0;
            array_x[2]=array_x[1];
           }
         if(array_y[2]>form.Height()-START_Y-1)
           {
            ny3=0;
            array_y[2]=array_y[1];
           }
         //--- check x4 and y4 coordinates for being outside the form
         if(array_x[3]>form.Width()-START_X-1)
           {
            nx4=0;
            array_x[3]=START_X;
           }
         if(array_y[3]>form.Height()-START_Y-1)
           {
            ny4=0;
            array_y[3]=array_y[2];
           }
         //--- check x5 and y5 coordinates for being outside the form
         if(array_x[4]>form.Height()-START_X-1)
           {
            nx5=0;
            array_x[4]=array_x[0];
           }
         if(array_y[4]>form.Height()-START_Y-1)
           {
            ny5=0;
            array_y[4]=array_y[0];
           }
         //--- Draw a shape
         form.DrawPolygonThickOnBG(0,array_x,array_y,3,clrWheat,255,true,false,STYLE_SOLID,LINE_END_BUTT);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         nx4++;
         ny4++;
         nx5++;
         ny5++;
         break;
      
   //--- "s" = Rectangle
      case FIGURE_TYPE_RECTANGLE  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawRectangleOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "d" = Filled rectangle
      case FIGURE_TYPE_RECTANGLE_FILL  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawRectangleFillOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "f" = Circle
      case FIGURE_TYPE_CIRCLE  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         RD=nx2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(RD>form.Height()/2)
           {
            nx2=0;
            RD=1;
           }
         form.DrawCircleOnBG(0,coordX1,coordY1,(int)RD,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         break;
      
   //--- "g" = Filled circle
      case FIGURE_TYPE_CIRCLE_FILL  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         RD=nx2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(RD>form.Height()/2)
           {
            nx2=0;
            RD=1;
           }
         form.DrawCircleFillOnBG(0,coordX1,coordY1,(int)RD,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         break;
      
   //--- "h" = Circle with AntiAlliasing
      case FIGURE_TYPE_CIRCLE_AA  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         RD=nx2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(RD>form.Height()/2)
           {
            nx2=0;
            RD=1;
           }
         form.DrawCircleAAOnBG(0,coordX1,coordY1,RD,clrWheat,255,true,false,STYLE_SOLID);
         nx1++;
         ny1++;
         nx2++;
         break;
      
   //--- "j" = Circle with WU
      case FIGURE_TYPE_CIRCLE_WU  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         RD=nx2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(RD>form.Height()/2)
           {
            nx2=0;
            RD=1;
           }
         form.DrawCircleWuOnBG(0,coordX1,coordY1,RD,clrWheat,255,true,false,STYLE_SOLID);
         nx1++;
         ny1++;
         nx2++;
         break;
      
   //--- "k" = Triangle
      case FIGURE_TYPE_TRIANGLE  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*4;
         coordY2=START_Y+ny2*2;
         coordX3=coordX1+nx3*2;
         coordY3=coordY2+ny3*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
           
         if(coordX3>form.Width()-START_X-1)
           {
            nx3=0;
            coordX3=START_X;
           }
         if(coordY3>form.Height()-START_Y-1)
           {
            ny3=0;
            coordY3=START_Y;
           }
         form.DrawTriangleOnBG(0,coordX1,coordY1,coordX2,coordY2,coordX3,coordY3,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         break;
      
   //--- "l" = Filled triangle
      case FIGURE_TYPE_TRIANGLE_FILL  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*4;
         coordY2=START_Y+ny2*2;
         coordX3=coordX1+nx3*2;
         coordY3=coordY2+ny3*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
           
         if(coordX3>form.Width()-START_X-1)
           {
            nx3=0;
            coordX3=START_X;
           }
         if(coordY3>form.Height()-START_Y-1)
           {
            ny3=0;
            coordY3=START_Y;
           }
         form.DrawTriangleFillOnBG(0,coordX1,coordY1,coordX2,coordY2,coordX3,coordY3,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         break;
      
   //--- "z" = Triangle with AntiAlliasing
      case FIGURE_TYPE_TRIANGLE_AA  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*4;
         coordY2=START_Y+ny2*2;
         coordX3=coordX1+nx3*2;
         coordY3=coordY2+ny3*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
           
         if(coordX3>form.Width()-START_X-1)
           {
            nx3=0;
            coordX3=START_X;
           }
         if(coordY3>form.Height()-START_Y-1)
           {
            ny3=0;
            coordY3=START_Y;
           }
         form.DrawTriangleAAOnBG(0,coordX1,coordY1,coordX2,coordY2,coordX3,coordY3,clrWheat,255,true,false,STYLE_SOLID);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         break;
      
   //--- "x" = Triangle with WU
      case FIGURE_TYPE_TRIANGLE_WU  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*4;
         coordY2=START_Y+ny2*2;
         coordX3=coordX1+nx3*2;
         coordY3=coordY2+ny3*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
           
         if(coordX3>form.Width()-START_X-1)
           {
            nx3=0;
            coordX3=START_X;
           }
         if(coordY3>form.Height()-START_Y-1)
           {
            ny3=0;
            coordY3=START_Y;
           }
         form.DrawTriangleWuOnBG(0,coordX1,coordY1,coordX2,coordY2,coordX3,coordY3,clrWheat,255,true,false,STYLE_SOLID);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         nx3++;
         ny3++;
         break;
      
   //--- "c" = Ellipse
      case FIGURE_TYPE_ELLIPSE  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawEllipseOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "v" = Filled ellipse
      case FIGURE_TYPE_ELLIPSE_FILL  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=START_X+nx2*2;
         coordY2=START_Y+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawEllipseFillOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "b" = Ellipse with AntiAlliasing
      case FIGURE_TYPE_ELLIPSE_AA  :
         return;
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*2;
         coordY2=coordY1+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawEllipseAAOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat,255,true,false,STYLE_SOLID);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "n" = Ellipse with WU
      case FIGURE_TYPE_ELLIPSE_WU  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=coordX1+nx2*2;
         coordY2=coordY1+ny2*2;
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawEllipseWuOnBG(0,coordX1,coordY1,coordX2,coordY2,clrWheat,255,true,false,STYLE_SOLID);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "m" = Ellipse arc
      case FIGURE_TYPE_ARC  :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=form.Width()-START_X-1-nx2;
         coordY2=form.Height()-START_Y-1-ny2;
         
         coordX3=coordX1;
         coordY3=coordY1;
         coordX4=coordX2;
         coordY4=coordY2;
         
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX3=coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY3=coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX4=coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY4=coordY2=START_Y;
           }
         form.DrawArcOnBG(0,coordX1,coordY1,coordX2,coordY2,coordX3,coordY3,coordX4,coordY4,clrWheat);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- "," = Ellipse sector
      case FIGURE_TYPE_PIE :
         coordX1=START_X+nx1;
         coordY1=START_Y+ny1;
         coordX2=form.Width()-START_X-1-nx2;
         coordY2=form.Height()-START_Y-1-ny2;
         
         coordX3=coordX1;
         coordY3=coordY1;
         coordX4=coordX2;
         coordY4=coordY1;
         
         if(coordX1>form.Width()-START_X-1)
           {
            nx1=0;
            coordX3=coordX1=START_X;
           }
         if(coordY1>form.Height()-START_Y-1)
           {
            ny1=0;
            coordY3=coordY4=coordY1=START_Y;
           }
         if(coordX2>form.Width()-START_X-1)
           {
            nx2=0;
            coordX4=coordX2=START_X;
           }
         if(coordY2>form.Height()-START_Y-1)
           {
            ny2=0;
            coordY2=START_Y;
           }
         form.DrawPieOnBG(0,coordX1,coordY1,coordX2,coordY2,coordX3,coordY3,coordX4,coordY4,clrWheat,clrLightSteelBlue);
         nx1++;
         ny1++;
         nx2++;
         ny2++;
         break;
      
   //--- Default = Nothing
      default  :
         
         break;
     }
  }
//+------------------------------------------------------------------+

関数のコードはシンプルでわかりやすいと思います。いずれにせよ、コメントセクションを使用してください。

簡単なテストでは同じパラメータの一般的な処理は実行していません。switch演算子のcaseですべてを明示的に記述する方がはるかに簡単で高速です。コードの反復性は重要ではありません。作成されたクラスの機能を単純に確認することがより重要です。

EAをコンパイルし、チャート上で起動します。起動後、キーをいくつか押して、描画モードが変更され、3番目のフォームのラベルに表示されていることを確認します。4番目のフォームをクリックすると、テキストは前の記事の過去のEAと同じように移動します。ただし、このテキストはアニメーションテキストフレームオブジェクトクラスを介してレンダリングされるようになっています。

必要な描画モードを選択した後、3番目のフォームをクリックし始めると(描画モードの説明が記載されたラベルが表示されます)、選択した形状がラベルの上に描画され、フォーム全体が毎回違う形状点座標で描画されます 。


すべての描画メソッドがスムーズに機能するわけではありません。たとえば、CCanvasクラスのFillPolygon()メソッドは、初期パラメータがオブジェクトクリックで指定された場合に単に無限ループに陥り、EllipseAA()メソッドはゼロ除算エラーを生成します。このメソッドには、これが発生する可能性のある潜在的な点があります。

//+------------------------------------------------------------------+
//| Draw ellipse with antialiasing                                   |
//+------------------------------------------------------------------+
void CCanvas::EllipseAA(const double x1,const double y1,const double x2,const double y2,const uint clr,const uint style=UINT_MAX)
  {
   double rx = (x2-x1)/2;
   double ry = (y2-y1)/2;
//--- preliminary calculations
   double x=(x2>x1) ? x1+rx : x2+rx;
   double y=(y2>y1) ? y1+ry : y2+ry;
   double rx2=rx*rx;
   double ry2=ry*ry;
//--- set the line style
   uint prev_style=m_style;
   if(style!=UINT_MAX)
      LineStyleSet(style);
   uint mask=1<<m_style_idx;
//--- draw
   double quarter=round(rx2/sqrt(rx2+ry2));
   for(double dx=0; dx<=quarter; dx++)
     {
      double dy=ry*sqrt(1-dx*dx/rx2);
      if((m_style&mask)==mask)
         PixelSet4AA(x,y,dx,dy,clr);
      mask<<=1;
      if(mask==0x1000000)
         mask=1;
     }
   quarter=round(ry2/sqrt(rx2+ry2));
   for(double dy=0; dy<=quarter; dy++)
     {
      double dx=rx*sqrt(1-dy*dy/ry2);
      if((m_style&mask)==mask)
         PixelSet4AA(x,y,dx,dy,clr);
      mask<<=1;
      if(mask==0x1000000)
         mask=1;
     }
//--- set the previous line style
   if(style!=UINT_MAX)
      m_style=prev_style;
  }
//+------------------------------------------------------------------+

この問題をプロファイルのスレッドで報告しました。開発者からの返答があるまで、次の記事でそのようなエラーを回避しようとします。

これに関して、一部の描画メソッドは、フォームオブジェクトのマウスクリックのハンドラで呼び出されず、代わりに、関数は単に戻ります。とにかく、これは後で修正されます。描画された形状の下の背景が復元され、すべてが意図したとおりに表示されていることがわかります。描画モードの切り替えに問題があるため、切り替え後、背景は復元されません。背景を復元して画像を削除するメソッドがないためです。これは次の記事で行います。ここでは、テストの目的で、フォームに別の形状を表示する前に、時間枠を切り替えて背景を完全に復元しています。


次の段階

次の記事では、アニメーションクラスの開発を続けます。

ライブラリの現在のバージョンのすべてのファイルは、テストおよびダウンロードできるように、MQL5のテストEAファイルと一緒に以下に添付されています。
質問や提案はコメント欄にお願いします。

目次に戻る

**連載のこれまでの記事:

DoEasyライブラリのグラフィックス(第73部): グラフィック要素のフォームオブジェクト
DoEasyライブラリのグラフィックス(第74部): CCanvasクラスを使用した基本的グラフィック要素
DoEasyライブラリのグラフィックス(第75部): 基本的なグラフィック要素でプリミティブとテキストを処理するメソッド
DoEasyライブラリのグラフィックス(第76部): フォームオブジェクトと事前定義されたカラースキーム
DoEasyライブラリのグラフィックス(第77部): 影オブジェクトクラス
DoEasyライブラリのグラフィックス(第78部): ライブラリのアニメーションの原則イメージスライス

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/9652

添付されたファイル |
MQL5.zip (4076.37 KB)
より優れたプログラマー(第01部): MQL5プログラマーとして成功するためにやめなければいけない5つのこと より優れたプログラマー(第01部): MQL5プログラマーとして成功するためにやめなければいけない5つのこと
初心者が最高のコーディングキャリアを築くのを妨げている悪い習慣はたくさんあります。これは上級プログラマーさえにも言えることです。この記事では、それらについて説明し、対処します。この記事は、MQL5で開発者として成功したいすべての人にとって必読です。
DoEasyライブラリのグラフィックス(第78部): ライブラリのアニメーションの原則イメージスライス DoEasyライブラリのグラフィックス(第78部): ライブラリのアニメーションの原則イメージスライス
この記事では、ライブラリの一部で使用されるアニメーションの原則を定義します。また、画像の一部をコピーして指定したフォームオブジェクトの場所に貼り付け、画像が重ねられるフォームの背景の一部を保存して復元するクラスを開発します。
DoEasyライブラリのグラフィックス(第80部): 「幾何学的アニメーションフレーム」オブジェクトクラス DoEasyライブラリのグラフィックス(第80部): 「幾何学的アニメーションフレーム」オブジェクトクラス
本稿では、前の記事のクラスのコードを最適化し、指定された数の頂点を持つ正多角形を描画するための幾何学的アニメーションフレームオブジェクトクラスを作成します。
取引のための組合せ論と確率論(第II部): ユニバーサルフラクタル 取引のための組合せ論と確率論(第II部): ユニバーサルフラクタル
本稿では、フラクタルの研究を続け、すべての資料の要約に特に注意を払います。これを行うために、これまでの開発をすべて、取引での実用化に便利で理解しやすいコンパクトな形にまとめてみます。