記事"MQL5 クックブック: インジケーターサブウィンドウコンソールーボタン"についてのディスカッション - ページ 7

 
TheXpert:
あなたの記事は完璧だと確信していますか?

読んでいただけてとてもうれしいです。

ご質問には適切なスレッドでお答えいたします。

===

余計な誤解がないように言っておくが、私はアナトリーを恨んでいるわけではない!彼の記事に賛辞を送りたい!しかし、質問に答えることは必要だ...。

 
DC2008:

失礼ですが、ひょっとして別のチュートリアルやレシピを書くのを邪魔しているのでしょうか?

もしそうでなければ、インジケータのサブウィンドウのコントロールに関するあなたの記事について議論を続けましょう。 つまり、あなたはインジケータに便利なメニューを作るための大量の解決策(またはアイデア)を提供しているのですね。記事の趣旨はとても価値がある!しかし、「初心者」のプログラマーは、このすべての武器をどのように使うことができるのでしょうか?カスタム関数をどこに配置すればいいのか?例によってそれを示してください。そして同時に、例えば5つのボタンを使うためにコードで何を修正する必要があるのかを説明してください。初心者の質問だと思ってください。

いや、そんなことはない。まだ何も書いていない。年に1日くらいは休まないと。ただ休んでいるだけでは面白くない。)

大衆決定ではないし、書いてもいない。起こってもいないことを決めつけるのはやめよう。これが普遍的な解決策ではなく、特殊なケースであることは、議論の冒頭ですでに声があがっていた。私見では、初心者が練習 するには良い例だと思う。そして、既成の解決策をタダで手に入れ、大口を開けて笑顔で太陽に会いに走るのではない。わかりますか?私は、プログラミングを学ぶ最初の段階で、このような単純明快な例が欲しい。特に、これが人生で初めてのプログラミング言語であり、それ以前は全く別の分野で、プログラミングとは全く関係のない活動をしていたのであればなおさらだ。

この場合、5つのボタンを作るには、配列のサイズを変更し、オブジェクト・ボタンの名前、ボタンに表示されるテキスト、ボタンの状態を配列で宣言する際に不要な要素を除外する必要があります。

ボタンの状態の配列があるので、同じ原理で、どのボタンが押されたかをチェックし、ボタンの色を変えるだけでなく、他の(ユーザーが必要とする)アクションを実行することができる。これは例えば、取引機能(だけではありません):すべての保留中の注文を 削除する、すべてのポジションを決済する、などです。アイデアは無限にある。もしアイデアがないのであれば、あなたは間違った種類のアクティビティを選択したことになります。)

これを実装するためには、別の配列を作成する必要があります。この配列は、たとえばENUM_SCRIPTという 名前のカスタム列挙(これも作成する必要があります)の識別子で初期化されます。そして、例えば、SCRIPT_01=0、SCRIPT_02=2などのように識別子が呼び出されます。また、ループの中で、パネルのボタンが押されたかどうかをチェックするとき、どの識別子が押されたボタンにバインドされているか、ボタンの現在の状態を判断し、対応する関数をプログラムに渡して実行させる必要があります。

あえてサンプルコードは示さない。初心者のための宿題としてください。)

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров - Документация по MQL5
 

言われたように変更しました:

//--- ボタンに表示されるテキスト
string button_texts[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"Button 01","Button 02","Button 03","Button 04"},
     {"Button 05"}
  };
//--- オブジェクト名
string button_object_names[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"button_01","button_02","button_03","button_04"},
     {"button_05"}
  };
....
bool button_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false},
     {false}
  };

そして、これが画面に表示されたものです:

どうすれば直せますか?(私は初心者です)

 
DC2008:

言われたように変更しました:

そして、これが画面に表示されたものです:

どうすれば直せますか?(私は初心者です)

こんな感じです:

#define  BUTTON_COLUMNS 5 // 幅によるボタンの数
#define  BUTTON_ROWS    1 // 高さによるボタンの数
...
//--- ボタンに表示されるテキスト
string button_texts[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"Button 01","Button 02","Button 03","Button 04","Button 05"}
  };
//--- オブジェクト名
string button_object_names[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"button_01","button_02","button_03","button_04","button_05"}
  };
...
//--- ボタンの状態
bool button_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false,false}
  };
 

ああ、素晴らしい!うまくいった。

でも、どうやって自分の機能をボタンにつなげればいいのかわからない。例を見せて。

 
DC2008:

ああ、素晴らしい!うまくいった。

でも、どうやって自分の機能をボタンにつなげればいいのかわからない。例を見せて。

では、あなたが始めた「初心者」ゲームを続けましょう。)

どの時点で行き詰まっているのですか?今の時点でどのように理解したかを示してください。5つの識別子を持つ列挙と、それらの識別子を要素に割り当てる必要のある配列を作りなさい。

 
bool fun_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false,false}
  };
enum ENUM_SCRIPT
  {
   SCRIPT_01 =0,
   SCRIPT_02 =1,
   SCRIPT_03 =2,
   SCRIPT_04 =3,
   SCRIPT_05 =4,
  };
void F1()
  {Print("F1");}
bool F2()
  {Print("F2");return(false);}
int F3()
  {Print("F3");return(0);}
double F4()
  {Print("F4");return(0.1);}
color F5()
  {Print("F5");return(clrAliceBlue);}

では、次にどうするか?

 
DC2008:

では、次に何をすればいいのか?

これが必要な配列だ:

//--- スクリプト
ENUM_SCRIPT buttons_scripts[NUMBER_BUTTONS_HEIGHT][NUMBER_BUTTONS_WIDTH]=
  {
     {SCRIPT_01,SCRIPT_02,SCRIPT_03,SCRIPT_04,SCRIPT_05}
  };

次に、このような関数を書きます:

//+------------------------------------------------------------------+
//|| スクリプトの実行
//+------------------------------------------------------------------+
void ScriptOn()
  {
   for(int i=0; i<NUMBER_BUTTONS_WIDTH; i++)
     {
      for(int j=0; j<NUMBER_BUTTONS_HEIGHT; j++)
        {
         //--- このボタンが押されたら、対応するスクリプトを実行する。
         if(buttons_state[j][i])
           {
            if(buttons_scripts[j][i]==SCRIPT_01)
              {
               F1();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_02)
              {
               F2();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_03)
              {
               F3();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_04)
              {
               F4();
               return;
              }
            //---
            if(buttons_scripts[j][i]==SCRIPT_05)
              {
               F5();
               return;
              }
           }
        }
     }
  }

...そしてこの関数をコードのこの部分に置く:

//--- グラフィカル・オブジェクト上でのマウスの左クリックを追跡する。
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- ボタンをクリックすると
      if(InitializeButtonStates(sparam))
        {
         //--- ボタンの色を設定する
         ChangeButtonColorOnClick();
         //--- スクリプトの実行
         ScriptOn();
        }
      //--- チャートの更新
      ChartRedraw();
      return;
     }

そして、必要ならコードを最適化する方法を考えればいい。:)

 
tol64:

私はそうしている。

スタートアップ時にトラッキングが有効になっているプログラムは、アンロード時にそれをオフにする。そして、チャート上に残りトラッキングを必要とするプログラムは、トラッキングが有効かどうかをチェックし、無効であれば有効にする。

前ページの私の投稿にある Expert Advisorとインジケータのコードの例について、発言のあいまいさを排除するために、あなたの変形を示すことが望ましい。

誰かがマウスイベントのトラッキングを無効にしているかどうかを常にチェックする必要はありません。正確には、どんな状況からも身を守りたいのであればチェックすればいいのですが、それはやりすぎだと思います。

CHART_EVENT_MOUSE_MOVE が変更されたときにCHARTEVENT_CHART_CHANGE を 生成するように開発者に提案すべきでしょうか。そうすれば、Expert Advisorが動作しているときに必要な設定をエレガントに復元することが可能になります。

今のところ、このようなバリエーションがあります:

#property copyright "Copyright 2013, komposter"
#property link      "http://www.komposter.me/"
#property version   "1.00"
#property indicator_chart_window

input   bool    EnableMouseDetect = false; // true - マウストラッキングを使用、false - 使用しない。

bool PrevState = false;

//+------------------------------------------------------------------+
//| カスタムインジケータ初期化関数
//+------------------------------------------------------------------+
int OnInit()
{
        if ( EnableMouseDetect )
        {
                //--- 現在の状態を取得する
                PrevState = (bool)ChartGetInteger(0,CHART_EVENT_MOUSE_MOVE);
                //--- マウス・イベントのトラッキングを有効にする
                if ( PrevState == false ) ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
        }

        return(0);
}

//+------------------------------------------------------------------+
//| エキスパートの初期化機能
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        if ( EnableMouseDetect )
        {
                //--- マウス・イベントのトラッキングを無効にする
                if ( PrevState == false )
                {
                        ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,false);
                        ChartRedraw(); // この行がないと、ティックが到着したときだけトラッキングが無効になります。このように設計されているのでしょうか?
                }
        }
}

//+------------------------------------------------------------------+
| オンティック|
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                     const int prev_calculated,
                     const datetime& time[],
                     const double& open[],
                     const double& high[],
                     const double& low[],
                     const double& close[],
                     const long& tick_volume[],
                     const long& volume[],
                     const int& spread[])
       {
        
        return(rates_total);
       }
//+------------------------------------------------------------------+
//| チャートイベント機能|
//+------------------------------------------------------------------+
void OnChartEvent(const int    id,
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- マウスの動きとマウスの左ボタン押下を追跡する。
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      static int count=1;
      Print("CHARTEVENT_MOUSE_MOVE; EXPERT; ",count);
      count++;
     }
  }
//+------------------------------------------------------------------+

EnableMouseDetect = true - トラッキングを制御、false - トラッキングが有効な場合、イベント数を表示。


------------------
さて、もう少し考えてみたが、このオプションは機能しない。最初にマウスをトラッキングするプログラム(トラッキングを有効にする)を実行し、次に2番目のプログラム(すでに有効になっているものを見る)を実行し、最初のプログラムを削除すると、トラッキングが無効になり、2番目のプログラムは何も残らない。つまり、トラッキングが必要であることを知らせる何らかのセマフォを考え出す必要がある。

そして、ここで行われた研究(プロセッサーへの負荷について)を考慮すると、そのような松葉杖は必要ない。

というわけで、私の提案を開発者に投票することを提案し、このトピックは終了することができる。

 
ChartRedraw(); // この行がないと、ティックが到着したときだけトラッキングが無効になります。このように設計されているのでしょうか?
MT5では、チャートのプロパティは非同期で更新されます。つまり、プロパティを設定したからといって、端末がすぐにそれを読み取るわけではありません。ChartRedraw() 関数を 使用して、すべてのプロパティをターミナルに再読み込みさせます。また、ChartGet...ObjectGetを使用することもでき、この場合もプロパティは再読み込みされます。
Документация по MQL5: Операции с графиками / ChartRedraw
Документация по MQL5: Операции с графиками / ChartRedraw
  • www.mql5.com
Операции с графиками / ChartRedraw - Документация по MQL5