Discussione sull’articolo "Manuale MQL5: Controlli della finestra secondaria dell'indicatore - Pulsanti" - pagina 7

 
TheXpert:
È così sicuro che il suo articolo sia perfetto?

Mi fa molto piacere che lo abbia letto.

Sarò lieto di rispondere a tutte le domande nell'apposito thread.

===

Per evitare inutili fraintendimenti, non ho nulla contro Anatoly! Complimenti a lui per l'articolo! Ma è necessario rispondere alle domande...

 
DC2008:

Mi scusi, per caso la sto distraendo dallo scrivere un altro tutorial o una ricetta?

In caso contrario, continuiamo a parlare del tuo articolo sul controllo nella sottofinestra dell'indicatore. Quindi, proponi una soluzione di massa (o un'idea) su come realizzare un comodo menu in un indicatore. Bene, lo scopo dell'articolo è molto valido! Ma come può un programmatore "principiante" utilizzare tutto questo arsenale? Dove collocare le funzioni personalizzate? Dimostratelo con un esempio. E allo stesso tempo spiegare cosa è necessario correggere nel codice per utilizzare, ad esempio, 5 pulsanti? Consideratela una domanda da principiante.

No, non lo sei. Non sto ancora scrivendo nulla. Devo riposare almeno un giorno all'anno. Riposare e basta non è interessante, soprattutto non per molto tempo. )

Non è una decisione di massa e non ne ho scritto. Non attribuiamo a qualcosa che non è successo. Già all'inizio della discussione è stato detto che questa non è una soluzione universale, ma un caso particolare. A mio parere, è un buon esempio per un principiante per esercitarsi. E non per ottenere una soluzione già pronta gratuitamente e correre, con la bocca aperta in un ampio sorriso, incontro al sole. ) Avete capito? Vorrei un esempio così semplice e chiaro proprio all'inizio dell'apprendimento della programmazione. Soprattutto quando questo è il primo linguaggio di programmazione della vostra vita e prima di allora l'attività di tutta la vostra vita era in un campo completamente diverso, in nessun modo collegato ad esso.

Per creare 5 pulsanti, in questo caso, dobbiamo modificare la dimensione degli array ed escludere gli elementi non necessari quando dichiariamo gli array per i nomi degli oggetti-pulsanti, il testo visualizzato nei pulsanti e gli stati dei pulsanti.

Esiste un array di stati dei pulsanti, quindi lo stesso principio può essere utilizzato per verificare quale pulsante è stato premuto e, invece di cambiare semplicemente il colore del pulsante, eseguire qualche altra azione (richiesta dall'utente). Può trattarsi, ad esempio, di funzioni di trading (e non solo): cancellazione di tutti gli ordini in sospeso, chiusura di tutte le posizioni, ecc. Le idee sono infinite. E se non ci sono idee, allora avete scelto il tipo di attività sbagliato. )

Per implementare tutto ciò, è necessario creare un altro array, che sarà inizializzato con gli identificatori di un'enumerazione personalizzata (anch'essa da creare), ad esempio con il nome ENUM_SCRIPT. Gli identificatori verranno poi richiamati, ad esempio: SCRIPT_01 =0, SCRIPT_02 =2, ecc. Sempre nel ciclo, quando si controlla se il pulsante sul pannello è premuto, è necessario determinare quale identificatore è legato al pulsante premuto e lo stato attuale del pulsante, per poi passare la funzione corrispondente al programma per l'esecuzione.

Non mostrerò di proposito un esempio di codice. Lasciate che sia un compito a casa per i principianti. )

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

Ho apportato le modifiche come mi hai detto:

//--- Testo visualizzato nei pulsanti
string button_texts[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"Button 01","Button 02","Button 03","Button 04"},
     {"Button 05"}
  };
//--- Nomi degli oggetti
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}
  };

E questo è ciò che ho ottenuto sullo schermo:

Come posso risolvere il problema? (Sono un principiante)

 
DC2008:

Ho apportato le modifiche come mi hai detto:

E questo è ciò che ho ottenuto sullo schermo:

Come posso risolvere il problema? (Sono un principiante)

In questo modo:

#define  BUTTON_COLUMNS 5 // Numero di pulsanti per larghezza
#define  BUTTON_ROWS    1 // Numero di pulsanti per altezza
...
//--- Testo visualizzato nei pulsanti
string button_texts[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"Button 01","Button 02","Button 03","Button 04","Button 05"}
  };
//--- Nomi degli oggetti
string button_object_names[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {"button_01","button_02","button_03","button_04","button_05"}
  };
...
//--- Stati dei pulsanti
bool button_states[BUTTON_ROWS][BUTTON_COLUMNS]=
  {
     {true,false,false,false,false}
  };
 

Oh, fantastico! Funziona.

Ma non capisco come collegare le mie funzioni ai pulsanti. Mostratemi un esempio.

 
DC2008:

Oh, fantastico! Funziona.

Ma non capisco come collegare le mie funzioni ai pulsanti. Mostratemi un esempio.

Bene, continuiamo il gioco del "principiante" iniziato da voi. )

A che punto sei bloccato? Mostrate un tentativo di comprensione del punto attuale. Creare un'enumerazione con cinque identificatori e un array ai cui elementi devono essere assegnati tali identificatori.

 
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);}

Che cosa facciamo adesso?

 
DC2008:

Che cosa facciamo adesso?

Questo è il tipo di array di cui avete bisogno:

//--- Script
ENUM_SCRIPT buttons_scripts[NUMBER_BUTTONS_HEIGHT][NUMBER_BUTTONS_WIDTH]=
  {
     {SCRIPT_01,SCRIPT_02,SCRIPT_03,SCRIPT_04,SCRIPT_05}
  };

Quindi è necessario scrivere una funzione come questa:

//+------------------------------------------------------------------+
//|Esecuzione di script |
//+------------------------------------------------------------------+
void ScriptOn()
  {
   for(int i=0; i<NUMBER_BUTTONS_WIDTH; i++)
     {
      for(int j=0; j<NUMBER_BUTTONS_HEIGHT; j++)
        {
         //--- Se questo pulsante viene premuto, verrà eseguito lo script corrispondente
         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;
              }
           }
        }
     }
  }

...e collocare questa funzione in questa parte del codice:

//--- Tracciamento dei clic del tasto sinistro del mouse su un oggetto grafico
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- Se si fa clic sul pulsante
      if(InitializeButtonStates(sparam))
        {
         //--- Impostare i colori dei pulsanti
         ChangeButtonColorOnClick();
         //--- Eseguire lo script
         ScriptOn();
        }
      //-- Aggiornare il grafico
      ChartRedraw();
      return;
     }

E poi si può pensare a come ottimizzare il codice, se necessario. :)

 
tol64:

Questo è il modo in cui lo faccio io.

Il programma che ha attivato il tracciamento all'avvio lo disattiva quando si scarica. Il programma che rimane sul grafico e ha bisogno del tracciamento, controlla se è abilitato e, se è disabilitato, lo abilita.

È auspicabile fornire la propria variante sugli esempi di Expert Advisor e di codice dell'indicatore contenuti nel mio post alla pagina precedente, per escludere l'ambiguità delle affermazioni.

Non è necessario controllare costantemente se qualcuno ha disabilitato il tracciamento degli eventi del mouse. Per essere più precisi, se ci si vuole proteggere da qualsiasi situazione, si può controllare, ma mi sembra eccessivo.

Forse dovremmo suggerire agli sviluppatori di generare CHARTEVENT_CHART_CHANGE quando CHART_EVENT_MOUSE_MOVE cambia? In questo modo sarebbe possibile ripristinare elegantemente l'impostazione necessaria quando l'Expert Advisor è in esecuzione.

Per ora ho questa variante:

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

input   bool    EnableMouseDetect = false; // vero - funziona con il tracciamento del mouse, falso - senza

bool PrevState = false;

//+------------------------------------------------------------------+
//| Funzione di inizializzazione dell'indicatore personalizzata |
//+------------------------------------------------------------------+
int OnInit()
{
        if ( EnableMouseDetect )
        {
                //--- Ottenere lo stato corrente
                PrevState = (bool)ChartGetInteger(0,CHART_EVENT_MOUSE_MOVE);
                //--- Abilita il tracciamento degli eventi del mouse
                if ( PrevState == false ) ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
        }

        return(0);
}

//+------------------------------------------------------------------+
//| Funzione di deinizializzazione dell'esperto |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        if ( EnableMouseDetect )
        {
                //--- Disabilita il tracciamento degli eventi del mouse
                if ( PrevState == false )
                {
                        ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,false);
                        ChartRedraw(); // Senza questa riga, il tracciamento viene disabilitato solo quando arriva un tick. È questo il modo in cui è stato progettato?
                }
        }
}

//+------------------------------------------------------------------+
//| OnTick|
//+------------------------------------------------------------------+
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);
       }
//+------------------------------------------------------------------+
//| Funzione ChartEvent|
//+------------------------------------------------------------------+
void OnChartEvent(const int    id,
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- Tracciamento del movimento del mouse e della pressione del tasto sinistro del mouse
   if(id==CHARTEVENT_MOUSE_MOVE)
     {
      static int count=1;
      Print("CHARTEVENT_MOUSE_MOVE; EXPERT; ",count);
      count++;
     }
  }
//+------------------------------------------------------------------+

Ho creato un indicatore, ma con un parametro: run with EnableMouseDetect = true - controlla il tracking, false - stampa solo il numero di eventi, se il tracking è abilitato.


------------------
Ora ci ho pensato ancora un po' e devo convenire che questa opzione non funziona. Se si esegue prima un programma che traccia il mouse (abilita il tracciamento), poi il secondo (vede quello che è già abilitato) e poi si cancella il primo, si disabilita il tracciamento e il secondo rimane senza niente. In altre parole, dobbiamo trovare una sorta di semaforo per segnalare che il tracciamento è necessario.

E alla luce delle ricerche condotte qui (sul carico del processore) una stampella del genere non è necessaria.

Propongo quindi di votare la mia proposta agli sviluppatori, e l'argomento può essere chiuso.

 
ChartRedraw(); // Senza questa riga, il tracciamento viene disabilitato solo quando arriva un tick. È questo il modo in cui è stato progettato?
MT5 ha un aggiornamento asincrono delle proprietà del grafico. In altre parole, il fatto che si imposti una proprietà non significa che il terminale la rilevi immediatamente. La funzione ChartRedraw() viene utilizzata per far rileggere tutte le proprietà al terminale. Si può anche utilizzare la funzione ChartGet... ObjectGet, in questo caso anche le proprietà verranno rilette.
Документация по MQL5: Операции с графиками / ChartRedraw
Документация по MQL5: Операции с графиками / ChartRedraw
  • www.mql5.com
Операции с графиками / ChartRedraw - Документация по MQL5