Discusión sobre el artículo "Interfaces gráficas X: Control "Gráfico estándar" (build 4)" - página 2

 
Artyom Trishkin:

Anatoly, dime cuál es la causa del error.

2016.10.19 03:09:04.993 TestTable (EURUSD,H1)   invalid pointer access in 'Scrolls.mqh' (698,10)

Todo funcionaba bien antes de esta actualización. Ahora al construir la tabla CTable aparece este error.

Por favor, dime dónde está mal - Ya he impreso cada línea - la interfaz se construye, pero después de algún lugar tropieza, y .... error.

Archivo con un ejemplo en el archivo.

Me olvidé de hacer una corrección, como se hizo anteriormente en la clase CCanvasTable.

En la clase CTable, es necesario reemplazar las versiones actuales de los métodos CreateScrollV() y CreateScrollH() con los que se muestran en el siguiente listado:

//+------------------------------------------------------------------+
//|| Crea una barra de desplazamiento vertical |||
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
  {
//--- Guardar el puntero del formulario
   m_scrollv.WindowPointer(m_wnd);
//--- Coordenadas
   int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
   int y=CElement::Y();
//--- Establecer dimensiones
   m_scrollv.Id(CElement::Id());
   m_scrollv.IsDropdown(CElement::IsDropdown());
   m_scrollv.XSize(m_scrollv.ScrollWidth());
   m_scrollv.YSize((m_columns_total>m_visible_columns_total)? m_y_size-m_scrollv.ScrollWidth()+1 : m_y_size);
   m_scrollv.AnchorRightWindowSide(m_anchor_right_window_side);
   m_scrollv.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- Crear una barra de desplazamiento
   if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
      return(false);
//--- Ocultar si no es necesario ahora
   if(m_rows_total<=m_visible_rows_total)
      m_scrollv.Hide();
//---
   return(true);
  }
//+------------------------------------------------------------------+
//|| Crea una barra de desplazamiento horizontal |||
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
  {
//--- Guardar el puntero del formulario
   m_scrollh.WindowPointer(m_wnd);
//--- Coordenadas
   int x=CElement::X();
   int y=(m_anchor_bottom_window_side)? m_y-m_area.Y_Size()+m_scrollh.ScrollWidth() : CElement::Y2()-m_scrollh.ScrollWidth();
//--- Establecer dimensiones
   m_scrollh.Id(CElement::Id());
   m_scrollh.IsDropdown(CElement::IsDropdown());
   m_scrollh.XSize((m_rows_total>m_visible_rows_total)? m_area.XSize()-m_scrollh.ScrollWidth()+1 : m_area.XSize());
   m_scrollh.YSize(m_scrollh.ScrollWidth());
   m_scrollh.AnchorRightWindowSide(m_anchor_right_window_side);
   m_scrollh.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- Crear una barra de desplazamiento
   if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
      return(false);
//--- Ocultar si no es necesario ahora
   if(m_columns_total<=m_visible_columns_total)
      m_scrollh.Hide();
//---
   return(true);
  }


//---

Es necesario realizar cambios similares en la clase CLabelsTable. Las correcciones estarán en la próxima actualización.

 
Anatoli Kazharski:

Olvidé hacer una corrección como se hizo anteriormente en la clase CCanvasTable.

En la clase CTable, es necesario reemplazar las versiones actuales de los métodos CreateScrollV() y CreateScrollH() por las que se muestran en el siguiente listado:

...
//---

Es necesario realizar cambios similares en la clase CLabelsTable. Las correcciones estarán en la próxima actualización.

¡О! ¡Gracias!
 
Anatoli Kazharski:

Olvidé hacer una corrección como se hizo anteriormente en la clase CCanvasTable.

En la clase CTable, necesitas reemplazar las versiones actuales de los métodos CreateScrollV() y CreateScrollH() por los que se muestran en el siguiente listado:

//+------------------------------------------------------------------+
//|| Crea una barra de desplazamiento vertical |||
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
  {
//--- Guardar el puntero del formulario
   m_scrollv.WindowPointer(m_wnd);
//--- Coordenadas
   int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
   int y=CElement::Y();
//--- Establecer dimensiones
   m_scrollv.Id(CElement::Id());
   m_scrollv.IsDropdown(CElement::IsDropdown());
   m_scrollv.XSize(m_scrollv.ScrollWidth());
   m_scrollv.YSize((m_columns_total>m_visible_columns_total)? m_y_size-m_scrollv.ScrollWidth()+1 : m_y_size);
   m_scrollv.AnchorRightWindowSide(m_anchor_right_window_side);
   m_scrollv.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- Crear una barra de desplazamiento
   if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
      return(false);
//--- Ocultar si no es necesario ahora
   if(m_rows_total<=m_visible_rows_total)
      m_scrollv.Hide();
//---
   return(true);
  }
//+------------------------------------------------------------------+
//|| Crea una barra de desplazamiento horizontal |||
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
  {
//--- Guardar el puntero del formulario
   m_scrollh.WindowPointer(m_wnd);
//--- Coordenadas
   int x=CElement::X();
   int y=(m_anchor_bottom_window_side)? m_y-m_area.Y_Size()+m_scrollh.ScrollWidth() : CElement::Y2()-m_scrollh.ScrollWidth();
//--- Establecer dimensiones
   m_scrollh.Id(CElement::Id());
   m_scrollh.IsDropdown(CElement::IsDropdown());
   m_scrollh.XSize((m_rows_total>m_visible_rows_total)? m_area.XSize()-m_scrollh.ScrollWidth()+1 : m_area.XSize());
   m_scrollh.YSize(m_scrollh.ScrollWidth());
   m_scrollh.AnchorRightWindowSide(m_anchor_right_window_side);
   m_scrollh.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- Crear una barra de desplazamiento
   if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
      return(false);
//--- Ocultar si no es necesario ahora
   if(m_columns_total<=m_visible_columns_total)
      m_scrollh.Hide();
//---
   return(true);
  }


//---

Es necesario realizar cambios similares en la clase CLabelsTable. Las correcciones estarán en la próxima actualización.

Anatoly, los cambios se han hecho. Toma el ejemplo de MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, corrige la tabla en Program.mqh para que el número de filas coincida con el número visible de filas, o el número de columnas coincida con el número visible de columnas, o ambos. Por ejemplo:

//+------------------------------------------------------------------+
//|| Crea una tabla|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
  {
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL    (15)
//--- Guardar el puntero al formulario
   m_table.WindowPointer(m_window1);
//--- Coordenadas
   int x=m_window1.X()+TABLE1_GAP_X;
   int y=m_window1.Y()+TABLE1_GAP_Y;
//--- Número de columnas y filas visibles
   int visible_columns_total =6;
   int visible_rows_total    =15;
//--- Establecer propiedades antes de la creación
   m_table.XSize(600);
   m_table.RowYSize(20);
   m_table.FixFirstRow(true);
   m_table.FixFirstColumn(true);
   m_table.LightsHover(true);
   m_table.SelectableRow(true);
   m_table.TextAlign(ALIGN_CENTER);
   m_table.HeadersColor(C'255,244,213');
   m_table.HeadersTextColor(clrBlack);
   m_table.CellColorHover(clrGold);
   m_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL);
   m_table.VisibleTableSize(visible_columns_total,visible_rows_total);
//--- Crear un control
   if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
      return(false);
//--- Rellenemos la tabla:
// La primera celda está vacía
   m_table.SetValue(0,0,"-");
//--- Títulos de las columnas
   for(int c=1; c<COLUMNS1_TOTAL; c++)
     {
      for(int r=0; r<1; r++)
         m_table.SetValue(c,r,"SYMBOL "+string(c));
     }
//--- Encabezados para las filas, método de alineación del texto - a la derecha
   for(int c=0; c<1; c++)
     {
      for(int r=1; r<ROWS1_TOTAL; r++)
        {
         m_table.SetValue(c,r,"PARAMETER "+string(r));
         m_table.TextAlign(c,r,ALIGN_RIGHT);
        }
     }
//--- Datos y formato de la tabla (color de fondo y color de las celdas)
   for(int c=1; c<COLUMNS1_TOTAL; c++)
     {
      for(int r=1; r<ROWS1_TOTAL; r++)
        {
         m_table.SetValue(c,r,string(c)+":"+string(r));
         m_table.TextColor(c,r,(c%2==0)? clrRed : clrRoyalBlue);
         m_table.CellColor(c,r,(r%2==0)? clrWhiteSmoke : clrWhite);
        }
     }
//--- Actualizar la tabla para mostrar los cambios
   m_table.UpdateTable();
//--- Añade el objeto al array común de grupos de objetos
   CWndContainer::AddToElementsArray(0,m_table);
   return(true);
  }
//+------------------------------------------------------------------+

Compila, ejecuta el ejemplo, haz clic en la fila más baja de la tabla (todo va bien), y vuelve a hacer clic. Al segundo clic aparece un error:

2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1)       array out of range in 'Table.mqh' (1091,86)

¿Qué hacer?

 
Artyom Trishkin:

Anatoly, los cambios se han hecho. Tome el ejemplo de MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, corrija la tabla en Program.mqh para que el número de filas coincida con el número visible de filas, o el número de columnas coincida con el número visible de columnas, o ambos. Por ejemplo, así:

...

Compila, ejecuta el ejemplo, pulsa sobre la fila más baja de la tabla (todo va bien), y vuelve a pulsar sobre ella. Al segundo clic aparece un error:

2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1)       array out of range in 'Table.mqh' (1091,86)

¿Qué hacer?

En las clases CScrollH y CScrollV en los métodos ScrollBarControl(), necesitas añadir una comprobación adicional de la visibilidad del elemento como se muestra en el siguiente listado:

//+------------------------------------------------------------------+
//| Control de desplazamiento|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
  {
//--- Salir si no hay puntero al formulario
   if(::CheckPointer(m_wnd)==POINTER_INVALID)
      return(false);
//--- Salir si el formulario está bloqueado por otro elemento
   if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
      return(false);
//--- Salir si el elemento está oculto
   if(!CElement::IsVisible())
     return(false);

//--- Comprobación del foco sobre el deslizador
   m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
                      y>m_thumb.Y() && y<m_thumb.Y2());
//--- Comprueba y recuerda el estado del botón del ratón
   CScroll::CheckMouseButtonState(mouse_state);
//--- Cambiar el color de la barra de desplazamiento de la lista
   CScroll::ChangeObjectsColor();
//--- Si el control se pasa a la barra de desplazamiento, defina la posición del deslizador
   if(CScroll::ScrollState())
     {
      //--- Mover el deslizador
      OnDragThumb(x);
      //--- Cambia el número de posición del deslizador
      CalculateThumbPos();
      return(true);
     }
   return(false);
  }

//---

La corrección estará disponible en la próxima actualización de la librería.

 
Anatoli Kazharski:

En las clases CScrollH y CScrollV en los métodos ScrollBarControl(), necesitamos añadir una comprobación adicional de la visibilidad del elemento como se muestra en el siguiente listado:

...

La corrección estará disponible en la próxima actualización de la biblioteca.

Gracias. He hecho estos cambios: en el archivo Scrolls.mqh en las clases CScrollH y CScrollV he añadido líneas:

//+------------------------------------------------------------------+
//| Control deslizante|
//+------------------------------------------------------------------+
bool CScrollV::ScrollBarControl(const int x,const int y,const bool mouse_state)
  {
//--- Salir si no hay puntero al formulario
   if(::CheckPointer(m_wnd)==POINTER_INVALID)
      return(false);
//--- Si el formulario no está bloqueado y los identificadores coinciden
   if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
      return(false);
//--- Salir si el elemento está oculto
   if(!CElement::IsVisible())
     return(false);

//--- Comprobación del foco sobre el deslizador
   m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
                      y>m_thumb.Y() && y<m_thumb.Y2());
//--- Comprueba y recuerda el estado del botón del ratón
   CScroll::CheckMouseButtonState(mouse_state);
//--- Cambiar el color del deslizador
   CScroll::ChangeObjectsColor();
//--- Si el control se pasa a la barra de desplazamiento, defina la posición del deslizador
   if(CScroll::ScrollState())
     {
      //--- Mover el deslizador
      OnDragThumb(y);
      //--- Cambia el número de posición del deslizador
      CalculateThumbPos();
      return(true);
     }
//---
   return(false);
  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//| Control de desplazamiento|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
  {
//--- Salir si no hay puntero al formulario
   if(::CheckPointer(m_wnd)==POINTER_INVALID)
      return(false);
   if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
      return(false);
//--- Salir si el elemento está oculto
   if(!CElement::IsVisible())
     return(false);

//--- Comprobación del foco sobre el deslizador
   m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
                      y>m_thumb.Y() && y<m_thumb.Y2());
//--- Comprueba y recuerda el estado del botón del ratón
   CScroll::CheckMouseButtonState(mouse_state);
//--- Cambiar el color de la barra de desplazamiento de la lista
   CScroll::ChangeObjectsColor();
//--- Si el control se pasa a la barra de desplazamiento, defina la posición del deslizador
   if(CScroll::ScrollState())
     {
      //--- Mover el deslizador
      OnDragThumb(x);
      //--- Cambia el número de posición del deslizador
      CalculateThumbPos();
      return(true);
     }
   return(false);
  }
//+------------------------------------------------------------------+

Compilo y ejecuto el mismo fichero de prueba de \MQL5\Indicators\Article07\ChartWindow02\ChartWindow02 .mq5, en el que he cambiado la función de construcción de tablas en Program.mqh para que el número de todas las columnas y filas coincida con el número de columnas y filas visibles:

//+------------------------------------------------------------------+
//|| Crea una tabla|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
  {
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL    (15)
//--- Guardar el puntero al formulario
   m_table.WindowPointer(m_window1);
//--- Coordenadas
   int x=m_window1.X()+TABLE1_GAP_X;
   int y=m_window1.Y()+TABLE1_GAP_Y;
//--- Número de columnas y filas visibles
   int visible_columns_total =6;
   int visible_rows_total    =15;
//--- Establecer propiedades antes de la creación
   m_table.XSize(600);
   m_table.RowYSize(20);
   m_table.FixFirstRow(true);
   m_table.FixFirstColumn(true);
   m_table.LightsHover(true);
   m_table.SelectableRow(true);
   m_table.TextAlign(ALIGN_CENTER);
   m_table.HeadersColor(C'255,244,213');
   m_table.HeadersTextColor(clrBlack);
   m_table.CellColorHover(clrGold);
   m_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL);
   m_table.VisibleTableSize(visible_columns_total,visible_rows_total);
//--- Crear un control
   if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
      return(false);
//--- Rellenemos la tabla:
// La primera celda está vacía
   m_table.SetValue(0,0,"-");
//--- Títulos de las columnas
   for(int c=1; c<COLUMNS1_TOTAL; c++)
     {
      for(int r=0; r<1; r++)
         m_table.SetValue(c,r,"SYMBOL "+string(c));
     }
//--- Encabezados para las filas, método de alineación del texto - a la derecha
   for(int c=0; c<1; c++)
     {
      for(int r=1; r<ROWS1_TOTAL; r++)
        {
         m_table.SetValue(c,r,"PARAMETER "+string(r));
         m_table.TextAlign(c,r,ALIGN_RIGHT);
        }
     }
//--- Datos y formato de la tabla (color de fondo y color de las celdas)
   for(int c=1; c<COLUMNS1_TOTAL; c++)
     {
      for(int r=1; r<ROWS1_TOTAL; r++)
        {
         m_table.SetValue(c,r,string(c)+":"+string(r));
         m_table.TextColor(c,r,(c%2==0)? clrRed : clrRoyalBlue);
         m_table.CellColor(c,r,(r%2==0)? clrWhiteSmoke : clrWhite);
        }
     }
//--- Actualizar la tabla para mostrar los cambios
   m_table.UpdateTable();
//--- Añade el objeto al array común de grupos de objetos
   CWndContainer::AddToElementsArray(0,m_table);
   return(true);
  }
//+------------------------------------------------------------------+

Compilar y ejecutar ChartWindow02.ex5

Varias veces hacemos clic en la fila más baja de la tabla y obtenemos un vuelo fuera de la matriz:

2016.10.25 01:39:22.899 ChartWindow02 (USDCHF,H1)       array out of range in 'Table.mqh' (1096,86)
¿Parece que no ha cambiado nada?
 
Artyom Trishkin:

...

Entonces, ¿no ha cambiado nada?

Después de los cambios que hice, ya no se reproduce. Puede que haya hecho algún otro cambio, pero no me acuerdo. No tengo un historial de ediciones menores.

Por si acaso, intenta reemplazar los métodos CScroll::Show() y CScroll::Hide() por estas versiones, si son diferentes:

//+------------------------------------------------------------------+
//| Muestra el elemento de menú|
//+------------------------------------------------------------------+
void CScroll::Show(void)
  {
//--- Salir si el número de elementos de la lista no es mayor que el número de la parte visible de la lista
   if(m_items_total<=m_visible_items_total)
      return;
//---
   m_area.Timeframes(OBJ_ALL_PERIODS);
   m_bg.Timeframes(OBJ_ALL_PERIODS);
   m_inc.Timeframes(OBJ_ALL_PERIODS);
   m_dec.Timeframes(OBJ_ALL_PERIODS);
   m_thumb.Timeframes(OBJ_ALL_PERIODS);
//--- Actualizar la posición de los objetos
   Moving(m_wnd.X(),m_wnd.Y(),true);
//--- Estado de visibilidad
   CElement::IsVisible(true);
  }
//+------------------------------------------------------------------+
//| Oculta el elemento de menú|
//+------------------------------------------------------------------+
void CScroll::Hide(void)
  {
   m_area.Timeframes(OBJ_NO_PERIODS);
   m_bg.Timeframes(OBJ_NO_PERIODS);
   m_inc.Timeframes(OBJ_NO_PERIODS);
   m_dec.Timeframes(OBJ_NO_PERIODS);
   m_thumb.Timeframes(OBJ_NO_PERIODS);
//--- Estado de visibilidad
   CElement::IsVisible(false);
  }


//---

Si no ayuda, tendrás que esperar a la próxima actualización.

 
Anatoli Kazharski:

Pero después de los cambios que hice, ya no se reproduce. Puede que haya hecho otros cambios, pero no me acuerdo. No marco el historial de ediciones menores.

Por si acaso, prueba a sustituir los métodos CScroll::Show() y CScroll::Hide() por estas versiones, si son diferentes:

//+------------------------------------------------------------------+
//| Muestra el elemento de menú|
//+------------------------------------------------------------------+
void CScroll::Show(void)
  {
//--- Salir si el número de elementos de la lista no es mayor que el número de la parte visible de la lista
   if(m_items_total<=m_visible_items_total)
      return;
//---
   m_area.Timeframes(OBJ_ALL_PERIODS);
   m_bg.Timeframes(OBJ_ALL_PERIODS);
   m_inc.Timeframes(OBJ_ALL_PERIODS);
   m_dec.Timeframes(OBJ_ALL_PERIODS);
   m_thumb.Timeframes(OBJ_ALL_PERIODS);
//--- Actualizar la posición de los objetos
   Moving(m_wnd.X(),m_wnd.Y(),true);
//--- Estado de visibilidad
   CElement::IsVisible(true);
  }
//+------------------------------------------------------------------+
//| Oculta el elemento de menú|
//+------------------------------------------------------------------+
void CScroll::Hide(void)
  {
   m_area.Timeframes(OBJ_NO_PERIODS);
   m_bg.Timeframes(OBJ_NO_PERIODS);
   m_inc.Timeframes(OBJ_NO_PERIODS);
   m_dec.Timeframes(OBJ_NO_PERIODS);
   m_thumb.Timeframes(OBJ_NO_PERIODS);
//--- Estado de visibilidad
   CElement::IsVisible(false);
  }


//---

Si no ayuda, tendrás que esperar a la próxima actualización.

Gracias, parece que ayuda. Faltaban líneas sobre el estado de visibilidad en Show():

//--- Estado de visibilidad
   CElement::IsVisible(true);

: y Hide():

//--- Estado de visibilidad
   CElement::IsVisible(false);
 
Artyom Trishkin:

Gracias, parece que ha funcionado. Faltaban líneas sobre el estado de visibilidad en Show()

//--- Estado de visibilidad
   CElement::IsVisible(true);

y Hide():

//--- Estado de visibilidad
   CElement::IsVisible(false);

Se necesita una corrección más. La visibilidad debería establecerse antes de actualizar la posición del elemento. Así:

...
//--- Estado de visibilidad
   CElement::IsVisible(true);
//--- Actualizar la posición de los objetos
   Moving(m_wnd.X(),m_wnd.Y(),true);
...
 

La interactividad de los elementos de la interfaz implementada a través de un temporizador es una solución extraña. - ¿Por qué debería implementarse a través de (o con) un temporizador? - Por supuesto, consumirá muchos recursos.

No necesitas un temporizador en absoluto para controlar los estados de los controles.

1. Registrar las coordenadas actuales de todos los elementos del array (mapa). Realiza ajustes en las coordenadas de ubicación de todos los objetos del formulario a medida que mueves la ventana.

2. 2. Crea una función para encontrar elementos por coordenadas (localizador). La función hará un bucle a través de las coordenadas actuales de los elementos registrados y encontrará el elemento que está ahora bajo el cursor.

3. Llame al localizador desde el evento "CHARTEVENT_MOUSE_MOVE" (en el evento de movimiento del cursor).

4. Pasar el nombre del objeto devuelto por el localizador a la función de interactividad, donde se aplicará al objeto la función ObjectSetInteger(), que le obligará a cambiar de color.


Como puedes ver, en este esquema no hay temporizador, por lo que no hay consumo innecesario de recursos.

 
Реter Konow:

La interactividad de los elementos de la interfaz implementada a través de un temporizador es una solución extraña. - ¿Por qué debería implementarse a través de (o con) un temporizador? - Por supuesto, consumirá muchos recursos.

...

Como puede ver, no hay temporizador en este esquema, por lo que no hay consumo innecesario de recursos.

Te equivocas. Ya he respondido con suficiente detalle en los comentarios anteriores por qué se ha hecho así.

No consume muchos recursos ahora (ahora en Windows 10 también). Has leído el artículo (y los comentarios también) ?

//---

P.D. Por cierto, el consumo de recursos de CPU en diferentes terminales (MT4/MT5) y versiones de SO (Windows) es muy diferente en igualdad de condiciones. En Windows 7 el terminal MetaTrader 4 se mostró significativamente mejor que MetaTrader 5. Lamentablemente, ahora no puedo darte las cifras, pues ya he cambiado completamente a Windows 10.

En cuanto a la optimización, todavía no he agotado todas las opciones. Todavía hay algo que optimizar y entender cómo.