Switching between charts - code

 

Hi all,

first of all, English is not my native language so I hope you won't get angry, if some misunderstandings occur in this thread ;-). Furthermore I want to give you a realistic view about my programming capabilities - well there are almost none. I can print "Hello world" in Python and know about "if-else" or the "for" operators, but there is not much more.....

I hope you can help me to find a solution for my problem.

I'm tired of switching through the charts with my mouse and switching with "CTRL+TAB" doesn't work for me, since the order of the "Chart-Tabs" gets messed up as soon as you go to another tab, that is not the next one.

So I thought that a script could help me achieving that. This script I wanted to bind to a hot-key combination, that I could use via a macro-key on my keyboard. So I was looking around for such a script and found this: https://forum.mql4.com/31024#297786

Now I tried to customize the code for my needs. Therefore I used an array containing the symbols of my charts in the right order, together with some other things, this came up:

#property copyright "Copyright 2014, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
#property show_inputs
#import "user32.dll"
int GetParent(int hWnd);
int SendMessageA(int hWnd, int Msg, int wParam, int lParam);
#import

#define WM_MDIACTIVATE 0x222
 
string charts[13] = {"EURUSD", "GBPUSD", "USDCHF", "USDJPY", "EURJPY", "GBPJPY", "AUDUSD", "AUDJPY", "NZDUSD", "USDCAD", "GBPCHF", "EURGBP", "EURCHF"};

int Window.activate(int hwnd) 
   {
   int p = GetParent(hwnd);
   SendMessageA(GetParent(p), WM_MDIACTIVATE, p, 0);
   }

int Window.getHandle() 
   {
   int i, hwnd;
   string chart = Symbol();
      
   if (chart==charts[ArraySize(charts)-1])
      {
      hwnd=WindowHandle(charts[0], 0);
      }else
      {
      for (i=0; chart != charts[i]; i++) 
         {
         hwnd = WindowHandle(charts[i+1], 0);
         if (hwnd != 0) break;
         }
      }
   return (hwnd);
   }

void start()
   {
   int hwnd = Window.getHandle();
   Window.activate(hwnd);
   }

The problem is, when starting this script, I get this notification:

When clicking "OK", nothing happens.....

So my questions are:

1. What do I have to do to avoid this notification? I later want to simply push my macro-button and the chart switches to the next one. (Later I also want to make a script where I can jump to the chart before)

2. Are there any other mistakes in "my code"?

Maybe it is important to know, that the charts often times have different time frames, so it should be no problem to switch from a 1 min. chart to a 5 min. chart and vice versa...


Any help is highly appreciated!

Thanks and best regards

kensho

 
from the new version B600 > Winapi is no need to use for that use CHART_BRING_TO_TOP
 

Hi gjol,

thank you very much for your input. I'll try implement it this evening.

Thanks

kensho

 

Hi again,

with the tip from gjol I wrote a new script that works.

But i'd like to increase its responsiveness. Because sometimes it needs 3-4 seconds to switch to the next chart.... maybe you have some tips.

Are there ways to improve the loading, initialization and deinitialization of the script? Maybe there is the possibility to let the script open/running for the time MetaTrader is running and implement the hot-key directly in the code?

Also other tips to improve the code are highly appreciated.

So here is my code:

//--- array of open charts in right order
string charts[13] = {"EURUSD", "GBPUSD", "USDCHF", "USDJPY", "EURJPY", "GBPJPY", "AUDUSD", "AUDJPY", "NZDUSD", "USDCAD", "GBPCHF", "EURGBP", "EURCHF"};

int chartsSize = ArraySize(charts);
string tSymbol;

//--- search for the symbol of the targeted chart
string zielsymbol()
  {  
   string aktuell = Symbol();
   int i;
  
   if(aktuell == charts[chartsSize - 1])
     {
      tSymbol = charts[0];
     }
   else
     {
      for(i = 0; i <= (chartsSize - 1); i++)
        {
         if(aktuell == charts[i])
           {
            tSymbol = charts[i+1];
            break;
           }
        }
     }
   return tSymbol;
  }

//--- search of ChartId of the chart with the targeted symbol
long sucheChartID()
  {
  int i;
  long altID;
  long aktID = ChartFirst();
  
  for(i = 0; i <= (chartsSize - 1); i++)
    {
     if(ChartSymbol(aktID) != tSymbol)
       {
        altID = aktID;
        aktID = ChartNext(altID);
       }
     else
       {
        break;
       }
    }
   return aktID; 
  }

 
void OnStart()
  {
   zielsymbol();
   ChartSetInteger(sucheChartID(), CHART_BRING_TO_TOP, 0, true);
  }
 

So a little and probably last update in this thread:

I think I have found the reason for the lack of responsiveness that occurred sometimes. I believe for switching a new tick for the targeted chart was necessary. Depending on the times of the day, this can take some good time.

So a ChartRedraw() was inserted, that made the script switch a lot faster.

Here is my final code:

#property copyright "kensho"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+

//--- array of open charts in right order
string charts[13] = {"EURUSD", "GBPUSD", "USDCHF", "USDJPY", "EURJPY", "GBPJPY", "AUDUSD", "AUDJPY", "NZDUSD", "USDCAD", "GBPCHF", "EURGBP", "EURCHF"};

int chartsSize = ArraySize(charts);
string tSymbol;
long zielID;

//--- search for the symbol of the targeted chart
string zielsymbol()
  {  
   string aktuell = Symbol();
   int i;
  
   if(aktuell == charts[chartsSize - 1])
     {
      tSymbol = charts[0];
     }
   else
     {
      for(i = 0; i <= (chartsSize - 1); i++)
        {
         if(aktuell == charts[i])
           {
            tSymbol = charts[i+1];
            break;
           }
        }
     }
   return tSymbol;
  }

//--- search of ChartId of the chart with the targeted symbol
long sucheChartID()
  {
  int i;
  long altID;
  long aktID = ChartFirst();
  
  for(i = 0; i <= (chartsSize - 1); i++)
    {
     if(ChartSymbol(aktID) != tSymbol)
       {
        altID = aktID;
        aktID = ChartNext(altID);
       }
     else
       {
        break;
       }
    }
   return aktID; 
  }

 
void OnStart()
  {
   zielsymbol();
   zielID = sucheChartID();
   ChartSetInteger(zielID, CHART_BRING_TO_TOP, 0, true);
   ChartRedraw(zielID);
  }

Best regards

kensho

 

Hello kensho,

You can found solution for your problem here: https://www.mql5.com/en/code/11060?source=terminal4_codebase

 

Hi,

since I had the very same thought lately, I stumbled over this thread.

And since the thread is quite old I don't know if it is still of interest but this is how I did it. Feel free to use it.

//+------------------------------------------------------------------+
//|                                                 SwitchCharts.mq4 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   BitmapLabelCreate(0,"btn_next",0,40,5,"\\Images\\gfx_next.bmp","\\Images\\gfx_next.bmp",33,20,0,0,true,CORNER_RIGHT_LOWER,ANCHOR_LEFT_LOWER);
   BitmapLabelCreate(0,"btn_prev",0,75,5,"\\Images\\gfx_prev.bmp","\\Images\\gfx_prev.bmp",33,20,0,0,true,CORNER_RIGHT_LOWER,ANCHOR_LEFT_LOWER);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(ObjectFind("btn_next")>=0) ObjectDelete("btn_next");
   if(ObjectFind("btn_prev")>=0) ObjectDelete("btn_prev");
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   if(id==CHARTEVENT_OBJECT_CLICK) 
   {
     if(sparam=="btn_next")
     {
      ChartSetInteger(GetChartID("next"),CHART_BRING_TO_TOP,0,true);
     }
     if(sparam=="btn_prev")
     {
      ChartSetInteger(GetChartID("prev"),CHART_BRING_TO_TOP,0,true);
     }
   }
//---
  }
//+------------------------------------------------------------------+
//| Get Chart ID function                                            |
//+------------------------------------------------------------------+
long GetChartID(string type)
  {
//---
   long currChart, prevChart=ChartFirst();
   long nextChart, thisChart = ChartID();
   int i=0,limit=100;
   if(type=="this")
   {
    return(thisChart);
   }
   nextChart = ChartNext(thisChart)<0 ? prevChart:ChartNext(thisChart);
   if(type=="next")
   {
    return(nextChart);
   }
   while(i<limit)
   {
    currChart=ChartNext(prevChart);
    if(currChart<0 || currChart==thisChart) break;
    prevChart=currChart;
    i++;
   }
//---
   return(prevChart);
  }
//+------------------------------------------------------------------+
//| Create Bitmap label function                                     |
//+------------------------------------------------------------------+
bool BitmapLabelCreate(
            const long              chart_ID=0,                         // chart's ID
            const string            name="",                            // label name
            const int               sub_window=0,                       // subwindow index
            const int               x=00,                               // X coordinate
            const int               y=00,                               // Y coordinate
            const string            file_on="",                         // image in On mode
            const string            file_off="",                        // image in Off mode
            const int               width=000,                          // visibility scope X coordinate
            const int               height=000,                         // visibility scope Y coordinate
            const int               x_offset=0,                         // visibility scope shift by X axis
            const int               y_offset=0,                         // visibility scope shift by Y axis
            const bool              state=false,                        // pressed/released
            const ENUM_BASE_CORNER  corner=CORNER_RIGHT_UPPER,          // chart corner for anchoring
            const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER,           // anchor type 
            const color             clr=clrNONE,                        // border color when highlighted
            const ENUM_LINE_STYLE   style=STYLE_SOLID,                  // line style when highlighted
            const int               point_width=1,                      // move point size
            const bool              back=false,                         // in the background
            const bool              selection=false,                    // highlight to move
            const bool              hidden=true,                        // hidden in the object list
            const long              z_order=0)                          // priority for mouse click
  {
//---
 // reset errors
    ResetLastError();
 // create object
    if(!ObjectCreate(chart_ID,name,OBJ_BITMAP_LABEL,sub_window,0,0))
    {
     Print(__FUNCTION__,
     ": failed to create \"Bitmap Label\" object! Error code = ",GetLastError());
     return(false);
    }
 // set on/off states of buttons
    if(!ObjectSetString(chart_ID,name,OBJPROP_BMPFILE,0,file_on))
    {
     Print(__FUNCTION__,
     ": failed to load the image for On mode! Error code = ",GetLastError());
     return(false);
    }
    if(!ObjectSetString(chart_ID,name,OBJPROP_BMPFILE,1,file_off))
    {
     Print(__FUNCTION__,
     ": failed to load the image for Off mode! Error code = ",GetLastError());
     return(false);
    }
 // set coordinates
    ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
    ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
 // set visibility scope for the image; if width or height values
 // exceed the width and height (respectively) of a source image,
 // it is not drawn; in the opposite case,
 // only the part corresponding to these values is drawn
    ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);
    ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);
 // set the part of an image that is to be displayed in the visibility scope
 // the default part is the upper left area of an image; the values allow
 // performing a shift from this area displaying another part of the image
    ObjectSetInteger(chart_ID,name,OBJPROP_XOFFSET,x_offset);
    ObjectSetInteger(chart_ID,name,OBJPROP_YOFFSET,y_offset);
 // define the label's status (pressed or released)
    ObjectSetInteger(chart_ID,name,OBJPROP_STATE,state);
 // set the chart's corner, relative to which point coordinates are defined
    ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
 // set anchor type
    ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
 // set the border color when object highlighting mode is enabled
    ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
 // set the border line style when object highlighting mode is enabled
    ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
 // set a size of the anchor point for moving an object
    ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,point_width);
 // display in the foreground (false) or background (true)
    ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
 // enable (true) or disable (false) the mode of moving the label by mouse
    ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
    ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
 // hide (true) or display (false) graphical object name in the object list
    ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
 // set the priority for receiving the event of a mouse click in the chart
    ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
 // successful execution
    return(true);
//---
  }
 
yoshiFX:

Hi,

since I had the very same thought lately, I stumbled over this thread.

And since the thread is quite old I don't know if it is still of interest but this is how I did it. Feel free to use it.

I compiled your code and attached it to a chart but nothing seems to happen, the code implies the indicator should exist in it's own window. Yet no window is coming up, even though the terminal reports the indicator was attached successfully. Is this normal or am I missing something?

 
Chidera Anakpe: the code implies the indicator should exist in it's own window. Yet no window is coming up, even though the terminal reports the indicator was attached successfully. Is this normal or am I missing something?
  1. #property indicator_chart_window
    You're missing something. The code does not say separate window.

  2. Do you have the required:
    \\Images\\gfx_next.bmp
    \\Images\\gfx_prev.bmp
 
William Roeder #:
  1. You're missing something. The code does not say separate window.

  2. Do you have the required:

The images are just raster images and can be substituted for place holders with the same name so as not to crash the script

 
yoshiFX #:

Hi,

since I had the very same thought lately, I stumbled over this thread.

And since the thread is quite old I don't know if it is still of interest but this is how I did it. Feel free to use it.

Hi. i looking something like that. I try use your idicator but after include nothing to do.