English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
例で紹介するMQL5のOOP:警告処理とエラーコード

例で紹介するMQL5のOOP:警告処理とエラーコード

MetaTrader 5 | 6 10月 2015, 10:53
875 0
KlimMalgin
KlimMalgin

OOPの簡単なイントロダクション

開発を始める前に、この記事で使用されるOOPの特徴を紹介します。

もちろん、ストラクチャーとクラスを使用していきます。これらは、オブジェクト指向言語の基礎となっています。ストラクチャーやクラスは何を指し、それぞれはどのように異なるのでしょうか?

ストラクチャー 一連の変数と異なる種類の関数 (void以外です)を含むことができる構造です。

クラスは、ストラクチャーと同様、データフィールドの塊です。しかし、クラスはより複雑であり、「柔軟な」構造を持ちます。クラスはOOPの基礎的なコンセプトです。クラスとストラクチャーの違いは、ドキュメンテーションに記載されています。引用いたします:

  • キーワードであるクラスは、宣言にて使用されます。
  • 標準的に、すべてのクラスメンバのアクセス権は明記されていない限り、プライベートとして設定されます。ストラクチャーのデータメンバは、明記されていな限り、標準としてパブリックタイプです。
  • たとえクラス内に宣言されていなくても、クラスオブジェクトはバーチャル関数を持っています。ストラクチャーは、バーチャル関数を持ち得ません。
  • 演算子のnew は、クラスオブジェクトに適用することができ、これはストラクチャーでは不可能です。
  • クラスは、クラスのみから継承されます 。ストラクチャーは、ストラクチャーのみから継承されます。

それでは、詳細にクラスを見ていきましょう。すべてのクラスフィールドは、二種類に分けられます。変数、配列など)データメンバーとクラス内で定義される関数の二つです。

データメンバー は、基本的にプロパティと呼ばれています。なぜなら、オブジェクトがクラスから作成される時、データメンバーは、このオブジェクトのプロパティを反映するためです。例えば、これが幾何学的な形、円形であれば、そのプロパティは、半径、線幅、配色、すなわち、オブジェクトのプロパティを含んでいます。

クラス内で定義された関数は、 メソッドと呼ばれます。クラスのプロパティを扱い、また、プログラムされたアルゴリズムの実行を行うために使用されます。

オブジェクト指向言語にはカプセル化という概念があります。これは、(アプリ開発者)ユーザーの直接的な影響から、データやオブジェクトの実行を防ぎます。プログラマーは、オブジェクトプロパティの変更は不可能ですが、どのメソッドでプロパティを変更できるかについて紹介しているドキュメンテーションのみ得ることができます。

そのような保護手段は、数多くのチェックがプロパティの値の変更前に必要である際、用いられます。すべての必要なチェックは、メソッドにて実行され、成功した場合はプロパティの変更を可能とします。 そして、ユーザーが直接プロパティにアクセスしたい場合、これらのチェックは実行されず、結果としてプロパティの値が不正にセットされます。すると、MQL言語が適切に動かなくなります。

いかなるクラスのプロパティやメソッドにおいても、 三つの修飾子: privateprotectedpublicを使用し、アクセスレベルを設定できます。

もしprivate修飾子は、クラスフィールドに使用され、このフィールドへのアクセスは同じクラスのメソッドを使用することでのみ可能であり、したがって、外部から修正不可能です。protected 修飾子もまた 外部からのフィールドへのアクセスの制限を課しますが、同じクラスのメソッド、サブクラスのメソッドにおいてはクラスへのフィールドへのアクセスが可能です。逆に、 publicは、すべてのアクセス制限を除去し、クラスフィールドへのアクセスを解放します。

インクルードmqhファイルの作成

作成するクラスは、個別のmqhファイルに保存される必要があり、 (エキスパートアドバイザー、スクリプト、インジケーターなど)プログラムの中にイクルードされるようになります。.

このファイルを作成するため、MQL5ウィザードを使用しましょう。メニュー内のFile 、次に Create を選択し、Include file (*.mqh) から、 Nextを選択します。現れたウィンドウ内にて、ファイル名(私は、ControlErrorsと付けました)を入力し、 Doneを押してください。mqhファイルのテンプレートが開かれます。このファイルで作業を続けていきます。


作業を開始する

この記事を学習するプロセスにおいて便利なOOPの理論的な基礎を学びましょう。それでは始めます。

すべてのプロパティ、メソッドの宣言を持つコードを紹介します。

class ControlErrors
{
private:

   // Flags determining what types of statements should be introduced
   bool _PlaySound;    // Play or don't play a sound when an error occurs
   bool _PrintInfo;    // Enter error data the the journal of Expert Advisors
   bool _AlertInfo;    // Generate Alert alert with error data
   bool _WriteFile;    // Write reports on errors onto a file or not
   
   // A structure for storing error data and elements that use this structure
   struct Code
   {
      int code;      // Error code
      string desc;   // Description of an error code
   };
   Code Errors[];    // Array that contains error codes and their descriptions
   Code _UserError;  // Stores information about a custom error
   Code _Error;      // Stores information about the last error of any type   
   
   // Different service properties
   short  _CountErrors;     // Number of errors stored in array Errors[]
   string _PlaySoundFile;   // File that will be played for an alert sound
   string _DataPath;        // Path to the log storing directory

   
public:
   // Constructor
   ControlErrors(void);
   
   // Methods for setting flags
   void SetSound(bool value);          // Play or don't play a sound when an error occurs
   void SetPrint(bool value);          // Enter error data the the journal of Expert Advisors or not
   void SetAlert(bool value);          // Generate an Alert message or not
   void SetWriteFlag(bool flag);       // Set the writing flag. true - keep logs, false - do not keep
   
   // Methods for working with errors
   int  mGetLastError();            // Returns contents of the system variable _LastError
   int  mGetError();                // Returns code of the last obtained error
   int  mGetTypeError();            // Returns error type (Custom = 1 ore predefined = 0)
   void mResetLastError();          // Resets the contents of the system variable _LastError
   void mSetUserError(ushort value, string desc = "");   // Sets the custom error
   void mResetUserError();          // Resets class fields that contain information about the custom error
   void mResetError();              // Resets the structure that contains information about the last error
   string mGetDesc(int nErr = 0);   // Returns error description by the number, or that of the current error of no number
   int Check(string st = "");       // Method to check the current system state for errors
   
   // Alert methods(Alert, Print, Sound)
   void mAlert(string message = "");
   void mPrint(string message = "");
   void mSound();
      
   // Various service methods
   void SetPlaySoundFile(string file); // Method sets the file name to play an sound
   void SetWritePath(string path);     // Set the path to store logs  
   int mFileWrite();                   // Record into a file the available information about the last error
};


クラスプロパティ

クラスプロパティの宣言文の最初に位置する修飾子private は、すべてのプロパティに適用され、クラスの外部から直接プロパティを扱うことは不可能です。プロパティは、都合のため3つのクラスに分かれています:

  1. レポートの種類を決定するフラッグが保存されている必要があります。これらすべてのフラッグは、二つの変数のみを保持します: True - このタイプのレポートは(忠告)は、可能を意味し、False - この種類は不可能を意味します。
    • _PlaySound - エラー発生時に、選択されたメロディや音の演奏の停止、開始を決める変数です。
    • _PrintInfo - エキスパートアドバイザーの記事にエラーの詳細についての追加を担当しています。
    • _AlertInfo - エラー情報とともにアラートの出力を可能/不可能にします。
    • _WriteFile - ファイルへのエラー情報の記録を可能/不可能にします。
  2. エラーデータを保管するストラクチャーや、このストラクチャーを使用する要素
    • Code - ストラクチャー配列に保管されるエラーデータの都合のために作成されました。
    • Errors - Codeの種類における配列、つまり、それぞれの配列要素は、Codeストラクチャーです。
    • _UserError - Codeの種類における変数カスタムエラーを使用するために用いられます。
    • _Error - Codeの種類に関する変数最後に生じたエラーは、この変数に格納され、さらなるエラーへの処理は、この変数を経由して行われます。
  3. 他のサービスプロパティ
    • _CountErrors - 変数は、Errors配列に格納されるデータのエラー数を含む変数です。配列の大きさを特定するために用いられます。
    • _PlaySoundFile - 警告音が鳴らされるファイルの名前を含んでいます。
    • _DataPath - エラーデータが記載されているログファイルの名前やパスが保管されています。

最初のグループのプロパティはすべて明確だと思います:特定のレポートの保持を続けるか、停止するかを決定します。二番目のグループでは、Codeストラクチャーが興味深いです。それは何で、なぜこのストラクチャーが配列に使用されているのでしょうか?すべて単純です!各エラーコードやその詳細を個別の配列にセットするよりも、単純配列に必要な全データを保管はより便利な方法です。ストラクチャーは、可能性を実現するために使用されます。全ての必要なフィールドは、ストラクチャー内にて宣言されます。それらは以下のようになります:

  • code - エラーコードを含む int型のフィールドです
  • desc - String型のフィールドですエラーの詳細を含んでいます。

実は、ストラクチャーは、複合のデータ型であり、すなわち、変数やすでに紹介した配列の宣言に用いられます。結果として、Code型の変数それぞれは、このストラクチャーのフィールドを保持します。同様に、Code型の配列要素は、コードやその詳細について保持する二つのフィールドを持ちます。したがって、単一の位置にて異なるオブジェクトデータを保存する便利な方法は、MQL5にて実行されます。

_UserErrorや _Errorなどの変数があります。これらは、_UserErrorがカスタムエラーについての情報を保持し、_Errorが全てのエラーについての情報を保持しますが、最後に発生したエラーについての情報を保持します。

そして、三番目のプロパティグループについてです。ここでは、最初のグループや二番目グループに所属しない残りのプロパティを含んでいます。3つあります一番目- _CountErrorsは、情報が配列_Errorsに格納されるエラーの数を保持します。このプロパティは、コンストラクタや、配列を呼ぶメソッドの中の_Errors配列のサイズを設定するために使用されます。二番目のプロパティは、_PlaySoundFileです。エラー発生時にかけられる音声ファイル名を保持しています。三番目のプロパティは、_DataPathです。ログを管理するファイルの名前やパスを格納しています。


クラスメソッドコンストラクタ

次は、コンストラクタやクラスメソッドの詳細です。コンストラクタについて詳しく見ながら、理解を進めていきましょう。メソッドと同じく、これは、クラスに定義されている共通の関数ですが、特別な機能を実行します。

  • コンストラクタはクラス名と合致しています。
  • コンストラクタは、return値がありません(void型が明記されます)
  • コンストラクタは、入力パラメー ターを持ちません。

普通クラスメンバは、コンストラクタにて初期化されます。例えば、私たちのクラスコンストラクタでは、レポートの保持を停止する全フラッグに、音声ファイル名がセットされ、ログファイルが明記され、_Errors配列のサイズが設定されます。この配列は、データが格納されていきます。以下にて、コンストラクタコードの一部分を記載しております。というのも、大きすぎ、主要な部分は_Erros配列に占められ同様なものであるためです。全コード内容は、この記事に添付されています。

void ControlErrors::ControlErrors(void)
{
   SetAlert(false);
   SetPrint(false);
   SetSound(false);
   SetWriteFlag(false);
   SetPlaySoundFile("alert.wav");
   SetWritePath("LogErrors.txt");
   
   _CountErrors = 150;
   ArrayResize(Errors, _CountErrors);

   // Return codes of a trade server
   Errors[0].code = 10004;Errors[0].desc = "Requote";
   Errors[1].code = 10006;Errors[1].desc = "Request rejected";
   Errors[2].code = 10007;Errors[2].desc = "Request canceled by trader";
   Errors[3].code = 10008;Errors[3].desc = "Order placed";
   Errors[4].code = 10009;Errors[4].desc = "Request is completed";
   Errors[5].code = 10010;Errors[5].desc = "Request is partially completed";
   Errors[6].code = 10011;Errors[6].desc = "Request processing error";
   Errors[7].code = 10012;Errors[7].desc = "Request canceled by timeout";
   Errors[8].code = 10013;Errors[8].desc = "Invalid request";
   Errors[9].code = 10014;Errors[9].desc = "Invalid volume in the request";
   Errors[10].code = 10015;Errors[10].desc = "Invalid price in the request";
   Errors[11].code = 10016;Errors[11].desc = "Invalid stops in the request";
   Errors[12].code = 10017;Errors[12].desc = "Trade is disabled";
   Errors[13].code = 10018;Errors[13].desc = "Market is closed";
   Errors[14].code = 10019;Errors[14].desc = "There is not enough money to fulfill the request";
   Errors[15].code = 10020;Errors[15].desc = "Prices changed";
   Errors[16].code = 10021;Errors[16].desc = "There are no quotes to process the request";
   Errors[17].code = 10022;Errors[17].desc = "Invalid order expiration date in the request";
   Errors[18].code = 10023;Errors[18].desc = "Order state changed";
   Errors[19].code = 10024;Errors[19].desc = "Too frequent requests";
   Errors[20].code = 10025;Errors[20].desc = "No changes in request";
   Errors[21].code = 10026;Errors[21].desc = "Autotrading disabled by server";
   Errors[22].code = 10027;Errors[22].desc = "Autotrading disabled by client terminal";
   Errors[23].code = 10028;Errors[23].desc = "Request locked for processing";
   Errors[24].code = 10029;Errors[24].desc = "Order or position frozen";
   Errors[25].code = 10030;Errors[25].desc = "Invalid order filling type";

   // Common Errors
   Errors[26].code = 4001;Errors[26].desc = "Unexpected internal error";
   Errors[27].code = 4002;Errors[27].desc = "Wrong parameter in the inner call of the client terminal function";
   Errors[28].code = 4003;Errors[28].desc = "Wrong parameter when calling the system function";
   Errors[29].code = 4004;Errors[29].desc = "Not enough memory to perform the system function";
   Errors[30].code = 4005;Errors[30].desc = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes";
   Errors[31].code = 4006;Errors[31].desc = "Array of a wrong type, wrong size, or a damaged object of a dynamic array";
   Errors[32].code = 4007;Errors[32].desc = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array";
   Errors[33].code = 4008;Errors[33].desc = "Not enough memory for the relocation of string";
   Errors[34].code = 4009;Errors[34].desc = "Not initialized string";
   Errors[35].code = 4010;Errors[35].desc = "Invalid date and/or time";
   Errors[36].code = 4011;Errors[36].desc = "Requested array size exceeds 2 GB";
   Errors[37].code = 4012;Errors[37].desc = "Wrong pointer";
   Errors[38].code = 4013;Errors[38].desc = "Wrong type of pointer";
   Errors[39].code = 4014;Errors[39].desc = "System function is not allowed to call";

}

実行の記述は、クラス外で行われていることに注意してください!メソッドのみがクラス内部にて宣言されています。ただ、これは必ずしも必要ではありません。もし望むのであれば、クラスの各メソッドの内容を記述することができます。しかし、個人的には、理解しずらく不便ではあります。

申し上げたとおり、メソッド関数のヘッダー部分のみクラスのボディに宣言されており、一方詳細はクラス外部にて実行されます。メソッドを記述する際は、どのクラスに所属するのかを明記する必要があります。コンテクスト許可演算子 ::が使用されています。上記のコードからわかるように、まずメソッドのリターンのタイプは明記されています(コンストラクタに関してはvoid型です)、そして、(メソッドが属するコンテクスト名)クラス名が次に来ます。そして、コンテクスト許可演算子の次にクラス名、入力パラメタを持つメソッド名が記載されています。この後、メソッドのアルゴリズムの記述が始まります。

まず、コンストラクタでは、全てのフラッグが設定され、音とログファイルが明記されています:

SetAlert(false);
SetPrint(false);
SetSound(false);
SetWriteFlag(false);
SetPlaySoundFile("alert.wav");
SetWritePath("LogErrors.txt");

これらそれぞれのメソッドは、特定のクラスプロパティを扱います。これは、プロパティにユーザーにより設定された値をフィルターにかける必要性がある場合、意図的になされます。例えば、カスタムファイル名やパスが一致する場所に特定のマスクを設定できます。マスクと相応する場合、ユーザーはそれについて知らされます。

おそらく気づいたかもしれませんが、全てのフラッグがfalse値を取っています。すなわち、クラスサンプルが作成された際、レポートは保管されません。ユーザーは、どのレポートが保管されるべきが選択し、OnInit()関数内の同様の名の「Set」メソッドを使用し、起動させてください。同様に、名前やログファイルへのパスを変更することができます。(パスは、「MetaTrader 5\MQL5\Files\」ディレクトリから相対的に設定されています。) そして、音声ファイルも変更可能です(パスは、 「MetaTrader 5\Sounds\」相対的に設定されています。).

フラッグが設定されたのち、_CountErrors変数を初期化し、150の値が割り当てられます。(149配列についての情報は、配列内に格納されます。)そして、ArrayResize()関数を使用し、必要な配列サイズを設定してください。その後、配列の挿入を始めます。


フラッグ設定メソッド

コンストラクタの詳細は、フラッグ設定メソッドや音声ファイル・ログファイル名の設定に関する詳細の次に述べられています。

void ControlErrors::SetAlert(bool value)
{
   _AlertInfo = value;
}

void ControlErrors::SetPrint(bool value)
{
   _PrintInfo = value;
}

void ControlErrors::SetSound(bool value)
{
   _PlaySound = value;
}

void ControlErrors::SetWriteFlag(bool flag)
{
   _WriteFile = flag;
}

void ControlErrors::SetWritePath(string path)
{
   _DataPath = path;
}

void ControlErrors::SetPlaySoundFile(string file)
{
   _PlaySoundFile = file;
}

コードからご覧のとおり、パラメータメソッドに簡単に渡されるクラスプロパティです。フラッグは、チェックを必要としません、というのも二つの値のみだからです。しかし、ファイル名やパスは、割り当て前にチェックなされる必要があります。

これらのメソッドを呼ぶことは、ほかと同様、以下のようになります。

type Class_name::Function_Name(parameters_description)
{
   // function body
}

次に、エラーを扱うメソッドの記述を紹介します。始めは、mGetLastError()とmrResetLastError()の二つのメソッドです。


mGetLastError()やmResetLastError()

メソッド名、mGetLastError() それ自身が内容を語ります。GetLastError()関数を複製します。しかし、GetLastErrorの呼び出しに加えて、記述は_Errorsの配列獲得されたエラーコードにおいて検索され、_Error変数に保管されます。GetLastError()を呼ぶ代わりに毎度保管された値を使用します。

メソッドコード:

int ControlErrors::mGetLastError(void)
{
   _Error.code = GetLastError();
   _Error.desc = mGetDesc(_Error.code);
   return _Error.code;
}

mResetLastError()メソッドはResetLastError():関数を複製します。

void ControlErrors::mResetLastError(void)
{
   ResetLastError();
}


最後のエラーメッセージを扱うメソッド

これらは、二つのメソッドからなります:mGetError()とmResetError().

mGetError()メソッドは、_Errorコードに含まれるコードを返します:

int ControlErrors::mGetError(void)
{
   return _Error.code;
}

mResetError()メソッドは、_Error変数の内容をリセットします。

void ControlErrors::mResetError(void)
{
   _Error.code = 0;
   _Error.desc = "";
}


エラー型決定メソッド、mGetTypeError()

次のメソッドは、mGetTypeError()です。最後に生じたエラーがカスタム版であるか、もしくは、(_errors配列にある)事前定義されているものかをチェックします。

メソッドコード:

int ControlErrors::mGetTypeError(void)
{
   if (mGetError() < ERR_USER_ERROR_FIRST)
   {
      return 0;
   }
   else if (mGetError() >= ERR_USER_ERROR_FIRST)
   {
      return 1;
   }
   return -1;
}

コンスタントなERR_USER_ERROR_FIRSTは、65536値を持ちます。これらのコードからカスタムで定義されたエラーが開始します。メソッド内にて、最後に受け取られたエラーコードがチェックされます。もしメソッドが0を返せば、これは再定義されたエラーです。もし、1が返されれば、それはカスタムエラーです。


カスタムエラーを扱うメソッド

MQL5では、ユーザーがプログラム内にてエラーを設定することができます。カスタムコードが適切な記述内容で追加されるために、 _UserErrorプロパティがクラス内にて使用可能です。2つのメソッドがこのプロパティを使用するために用いられます。

mSetUserError()メソッドは、コードを設定し、カスタムエラーを設定するために用いられます。

void ControlErrors::mSetUserError(ushort value, string desc = "")
{
   SetUserError(value);
   _UserError.code = value;
   _UserError.desc = desc;
}

まず、SetUserError()関数は、_LastErrorの定義された変数を ERR_USER_ERROR_FIRSTと等しい値に設定します。そして、と適切に割り当てられた詳細が _UserError変数に保管されます。

二番目のメソッドmResetUserError()は、 _UserError変数のフィールドをリセットします。

void ControlErrors::mResetUserError(void)
{
   _UserError.code = 0;
   _UserError.desc = "";
}

このメソッドは、_UserError変数のみ扱うことができます。システム変数_LastErrorの値をリセットするために、別のメソッドが使用されます: 上述されているmResetLastError()メソッドです。


エラーコードの詳細の取得用メソッド

mGerDesc()メソッドがクラスにあり、エラーがユーザーにより引き起こされた場合、呼ばれればErrors配列から、もしくは、_UserError変数から、エラーコードの詳細を返してくれます。

string ControlErrors::mGetDesc(int nErr=0)
{
   int ErrorNumber = 0;
   string ReturnDesc = "";
   
   ErrorNumber = (mGetError()>0)?mGetError():ErrorNumber;
   ErrorNumber = (nErr>0)?nErr:ErrorNumber;
   
   if ((ErrorNumber > 0) && (ErrorNumber < ERR_USER_ERROR_FIRST))
   {
      for (int i = 0;i<_CountErrors;i++)
      {
         if (Errors[i].code == ErrorNumber)
         {
            ReturnDesc = Errors[i].desc;
            break;
         }
      }
   }
   else if (ErrorNumber > ERR_USER_ERROR_FIRST)
   {
      ReturnDesc = (_UserError.desc=="")?"Cusrom error":_UserError.desc;
   }
      
   if (ReturnDesc == ""){return "Unknown error code: "+(string)ErrorNumber;}
   return ReturnDesc;
}

このメソッドは、nErrというパラメーターを持ちます。標準として、0に違い値を持ちます。もしメソッドの呼び出し中に値がパラメーターに設定されれば、設定された値の中で詳細の情報の検索がなされます。もしパラメーターがセットされていなければ、最後に受け取ったエラーコードの中から検索されます。

まず、二つの変数がメソッド内にて宣言されます:ErrorNumber - この変数を用い、エラーコードが処理されます:そして、ReturnDesc - ErrorNumberのため取得された詳細が保管され、次の二行において、ErrorNumberに値を割り当てる際、コンディショナル演算子?: が用いられます。これは、単純化されたif-else 構造の類似形です。

ErrorNumber = (mGetError()>0)?mGetError():ErrorNumber;
ErrorNumber = (nErr>0)?nErr:ErrorNumber;

最初の行にて、もしエラーが修復された場合。つまり、mGetError()が0ではない結果を返した場合、取得されたエラーコード(mGetError()メソッドによて返された値)がErrorNumber変数に挿入されます、さもなくば、ErrorNumber変数の値が割り当てられます。二行目に、同じチェックがなされますが、メソッドのパラメータにおいてのみです。もしnErrの値が0でなければ、ErrorNumber変数に割り当てられます。

エラーコードを受け取れば、このコードにて詳細の検索を開始してください。もし取得されたコードが0より大きく、 ERR_USER_ERROR_FIRSTより小さい、すなわち、カスタムエラーでない場合、ループ内にて詳細を検索します。そして、もし取得したコードがERR_USER_ERROR_FIRSTより大きければ、_UserError変数のdescフィールドから記述を取ります。

最後に、記述が見つかったかをチェックします。もしなければ、Unknownエラーコードについてのメッセージを返してください。.


シグナルメソッド

シグナルメソッドは、mAlert()、mPrint()、mSound()を含みます。調整では、これらのメソッドはとても類似しています:

void ControlErrors::mAlert(string message="")
{
   if (_AlertInfo == true)
   {
      if (message == "")
      {
         if (mGetError() > 0)
         {
            Alert("Error №",mGetError()," - ",mGetDesc());
         }
      }
      else
      {
         Alert(message);
      }   
   }
}

void ControlErrors::mPrint(string message="")
{
   if (_PrintInfo == true)
   {
      if (message == "")
      {
         if (mGetError() > 0)
         {
            Print("Error №",mGetError()," - ",mGetDesc());
         }
      }
      else
      {
         Print(message);
      }
   }
}

void ControlErrors::mSound(void)
{
   if (_PlaySound == true)
   {
      PlaySound(_PlaySoundFile);
   }
}

全ての3つのメソッドでは、はじめにレポートやシグナルを可能にするフラッグがチェックされます。それから、mAlert()メソッドとmPrint()メソッドでは、入力パラメーター message がAlertダイアログで表示されるべき、もしくはjounarlに追加されるべきメッセージがあるかチェックします。もしメッセージがmessageにセットされ、最後のエラーコードが0より大きければ、表示されます。そうでなければ、標準のメッセージが表示されます。mSound()はいかなるパラメータを持たず、そのためフラッグのチェック後、すぐにPlaySound() が音を出すために呼び出されます。


Check()メソッド

このメソッドは単純に正しい順番でクラスの関数を呼び出します。したがって、新しいエラーの発生がチェックされ、全てのレポートが発行され、直ちにエラーコードとその詳細が削除されますCheck()メソッドは包括的なチェックです:

int ControlErrors::Check(string st="")
{
   int errNum = 0;
   errNum = mGetLastError();
   mFileWrite();
   mAlert(st);
   mPrint(st);
   mSound();
   mResetError();
   mResetLastError();
   mResetUserError();
   return errNum;
}

Check()はString型のパラメータを持ちます。これは、レポートに記述されるためにmAlert()、mPrint()メソッドに渡されるカスタムメッセージです。


ログファイルにメッセージを書き込むウィンドウ

このメソッドはmFileWrite()と言います。もしログファイルが可能であり、ファイルへのパスが正しく明記されているなら、このメソッドは特定のファイルの記録を行います。.

int ControlErrors::mFileWrite(string message = "")
{
   int      handle  = 0,
            _return = 0;
   datetime time    = TimeCurrent();
   string   text    = (message != "")?message:time+" - Error №"+mGetError()+" "+mGetDesc();
   
   if (_WriteFile == true)
   {
      handle = FileOpen(_DataPath,FILE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
      if (handle != INVALID_HANDLE)
      {
         ulong size = FileSize(handle);
         FileSeek(handle,size,SEEK_SET);
         _return = FileWrite(handle,text);
         FileClose(handle);
      }
   }
   return _return;
}

まずはじめに、4つの変数が宣言されます:handle - オープンファイルのハンドラを保管します、 _return - 現在時刻(ファイルを記録するための時間)を保持した時間、返却値を保管します、text - ファイルに記述されるメッセージテキストです。mFileWrite()メソッドは、一つ入力パラメーター、messageを持ち、ユーザーは、ファイルに記述されるべきStringを渡すことができます。.

この特徴は、特定の瞬間のインジケーター値、価格、その他必要なデータに使用されます。

変数が宣言されたら、_WriteFileのフラッグがチェックされます。そして、もしログファイルの管理が許されれば、ファイルは、FileOpen()関数を使用し、再度書き換えのためにオープンになります。 FileOpen()の最初のパラメータは、ファイル名とそれへのパスを持つDataPathプロパティです。二番目のパラメータは、 フラッグを扱う方法を決定するflags です。4つのフラッグが使用されています。

  • FILE_READ、FILE_WRITE は、ともにデータを追加することができるファイルへの直接管理を行います。
  • FILE_TXTは作業がシンプルなテキストファイルで実行されることを表します。
  • FILE_ANSIはデータがANSI型 (single-byte symbols)Stringとして、ファイルに記述されることを指します。

次のステップには、ファイルがうまく開かれたのかをチェックします。そうでなければ、ハンドラは INVALID_HANDLEという値を持ち、メソッドの実行は終了します。もし成功していれば、 FileSize()を使用し、ファイルサイズを取得、 FileSeek() 使用し、ファイルポインターの位置を移動し、 FileWrite()で、メッセージをファイルに追加します。その後、FileClose()関数を使用し、ファイルを閉じます。

入力パラメターとして、サイズを返すべきファイルのハンドラをFileSize()関数へ渡してください。これがこの関数の唯一のパラメーターです。

これらのパラメータは、FileSeek()関数の実行のため明記される必要があります。

  • 使用するファイルのハンドラ
  • ファイルポインターのシフト
  • シフトにおける参照点ENUM_FILE_POSITIONの一つのバリューを用います。

少なくとも二つのパラメーターをFileWrite()の処理に必要とします。これは、テキストデータを必要とするファイルのハンドラです。二番目は、記述されるべきテキストラインとファイルに記述される次のテキストラインです。パラメーター数は63を超えないようにしなければなりません。

FileClose()関数は、ファイルを閉じるためのハンドラを必要とします。


例:

それでは、作成したクラスを使用したいくつかの一般的な例を紹介したいと思います。オブジェクト作成と必要なレポートの管理から始めましょう

クラスオブジェクト作成します;

#include <ControlErrors.mqh>

ControlErrors mControl;

オブジェクトを作成する前に、クラスの詳細を含むファイルをエキスパートアドバイザーへ追加する必要があります。これは#includeによりプログラムの初期にて行われます。そして、オブジェクトが作成されると新しい変数を作成したのと同じような形になります。しかし、データ型の代わりにクラス名が挿入されます。

それでは、受け取りたいエラーレポートを作成しましょう。これはOnInit()関数で行います

int OnInit()
{
//---
mControl.SetAlert(true);
mControl.SetPrint(true);
mControl.SetSound(false);
mControl.SetWriteFlag(true);
mControl.SetPlaySoundFile("news.wav");
//---
return(0);
}

標準的に、オブジェクト作成時、フラッグは、falseが設定されます。つまり、すべてのレポートが停止されている状態です。そのため、OnInit()では、false値を持ったメソッドを呼ぶ必要がありません。というのも、上記の例(SetSound()メソッド).にて行われているためです。これらのメソッドは、他のプログラムでも呼ばれます。例えば、特定の状態を維持するレポートを停止する必要があれば、これらの状態をプログラムで表現し、必要な値にフラッグを設定することができます。

そして、もう一つ紹介すべき点として、エラーの「取得」、プログラムの実行時におけるメソッドの呼び出しです。この部分は、難しくありません。なぜなら、その前にフラッグを設定し、Check()メソッドを使用することができるからです。

mControl.Check();

このメソッドは、上述の通り、発生したエラーのコードを特定し、レポートを管理するメソッドをすべて呼び出します。そして、最後に発生したエラーについての情報を持つ変数の値をすべてリセットします。エラーの処理方法は、 Check()により提供されており、その方法がなんらかの理由で作動しない場合、クラスメソッドを使用し、自分のレポートを生成することだできます。

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

添付されたファイル |
controlerrors.mqh (19.82 KB)
MetaTrader 5:ビログやSNS、専門サイトなどのトレーディング予想とライブトレーディング内容のメール配信 MetaTrader 5:ビログやSNS、専門サイトなどのトレーディング予想とライブトレーディング内容のメール配信
この記事は、Meta Trader 5を使用したトレード予想の投稿に関する完成されたソリューションについて紹介することを目的としています。様々なアイディアをカバーしており、Meta Traderにおける記述文を投稿する専門サイトを使用することから、Webプログラミングなしで視覚的にWebサイトを構築したり、分析者を読者がフォローすることができるSNSサービスとの統合まで行うことができます。ここで紹介されているソリューションは、完全無料提供されており、eメールやftpサービスの基礎的な知識を持っている人なら誰でもセットアップすることが可能です。専門的なホスティング技術や、トレーディング予想サービスと同様のものを使用することができ、全く障害がありません。
市場分析のための実践的なデーターベースの活用 市場分析のための実践的なデーターベースの活用
データを扱うことは、現代のソフトウェアのメインの業務となっています。これは、スタンドアロン系、ネットワーク系のアプリ双方において言えることです。この問題を解決するために、特別なソフトウェアが開発されました。それは、データベース管理システム(DBMS)です。コンピューター内ストレージや、その処理においてデータを整理し、構築します。トレーディングにおいて、多くの分析はデータベースを使用しません。しかし、ソリューションがより便利になる必要のある業務があります。この記事では、クライアントサーバー、ファイルサーバー構造の両方において、データベースからデータをロードし、保存できるインジケーターの例を紹介します。
MQL4からMQL5への移植 MQL4からMQL5への移植
本稿はMQL4言語関数の簡単なガイドです。MQL4からMQL5へプログラムを移植するのに役立つことでしょう。MQL4関数(トレーディング関数以外)にはそれぞれ記述とMQL5実装が存在します。そのため移行時間が大幅に削減されます。利便性を考え、MQL4関数はグループ分けされておりMQL4参照に似た形になっています。
MQL4からMQL5へのインディケータ変換 MQL4からMQL5へのインディケータ変換
本稿では、MQL4で書かれた価格コンストラクションをMQL5に変換する特徴に特化して述べます。 MQL4からMQL5へのインディケータ変換計算プロセスを簡単にする手法として関数のmql4_2_mql5.mqhライブラリを提案します。その使用法はMACD、ストキャスティック、RSIインディケータの変換基礎に記載されています。