Discussion of article "Making charts more interesting: Adding a background"

 

New article Making charts more interesting: Adding a background has been published:

Many workstations contain some representative image which shows something about the user. These images make the working environment more beautiful and exciting. Let's see how to make the charts more interesting by adding a background.

Many workstations contain some representative image which shows something about the user. These images make the working environment more beautiful and inspiring, as people always try to choose the vest and most beautiful images to use as wallpaper. But when we open the trading platform, we see that it is somehow boring. All we have is the graphical representation of numerical data.

 


You can look at images and photos for quite a long period without getting tired, but observing a price chart even for a few minutes can be very tiring. So, let's make it so that we can watch and analyze the chart, while the image in the background motivates us and reminds us of something good.

Author: Daniel Jose

 
Very good article Daniel, for the investment agents to put in their offices then it is top. MT5 has its limitations, of course, but it is possible to do a lot of things in the graphical part that ends up half underused.
 
Very good
 
utility is working perfect but some indicator using OnChartEvent stops working and are unclickable once I apply this EA for background
 
Arpit Tailang # : The utility works perfectly, apart from some sinalisers that OnChartEvent uses to work and become uninstallable when I apply this EA in the background


ObjectSetInteger ( Terminal.Get_ID(), szName, OBJPROP_BACK , true ); 

... If you pay attention, you will see that the bitmap image will be being plotted on the body of the candles, indicating that the bitmap object is in the foreground, again this is not the expected behaviour because of the line of code above, because of this it happens to receive any and all click events ... 🙁

 
The possibility of using it in the function that I present in this code
 //+------------------------------------------------------------------+
//|                                                   SelectFile.mqh |
//+------------------------------------------------------------------+
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#include <Controls\Edit.mqh>
#include <Controls\ListView.mqh>
#include <Controls\CheckGroup.mqh>
//+------------------------------------------------------------------+
//| defines                                                          |
//+------------------------------------------------------------------+
#define  INDENT_LEFT             ( 4 )             // indent from left
#define  INDENT_TOP              ( 4 )             // indent from top
#define  INDENT_RIGHT            ( 4 )             // indent from right
#define  BUTTON_WIDTH            ( 60 )     // size by X coordinate
#define  BUTTON_HEIGHT   ( 20 )       // size by Y coordinate
#define  EDIT_HEIGHT             ( 20 )       // size by Y coordinate
#define  COMMON_WIDTH            ( 90 )       // size by X coordinate
//+------------------------------------------------------------------+
//| Class CSelectFile                                                |
//+------------------------------------------------------------------+
class CSelectFile : public CDialog
  {
   CEdit             m_filename;
   CButton           m_button_ok;
   CButton           m_button_cancel;
   CListView         m_filelist;
   CCheckGroup       m_common;
   string             m_instance_id,
                     m_files[],
                     m_folders[],
                     m_prevfolder,
                     m_cfolder,
                     m_fullname;
   int                m_numberfiles,
                     m_numberfolders,
                     m_totalfiles,
                     m_fileflag,
                     m_pressbutton;
protected :
   CChart            m_chart;
public :
                     CSelectFile( void );
                    ~CSelectFile( void );
   virtual bool       Create( const long chart, const string name, const int x1, const int y1, const int x2, const int y2);
   int                ChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam);
   string             Filename(){ m_pressbutton= 0 ; return (m_fullname);}
   int                FileFlag(){ return (m_fileflag);}
protected :
   void               OnClickButtonOK( void );
   void               OnClickButtonCancel( void );
   virtual void       OnClickButtonClose( void );
   void               OnChangeList( void );
   void               OnCheckCommon( void );
   void               SetFolder( string m_fol= "" );
  };
//+------------------------------------------------------------------+
CSelectFile::CSelectFile( void )
  {
   m_instance_id= IntegerToString ( rand (), 5 , '0' );
   m_fileflag= 0 ;
   m_pressbutton= 0 ;
   m_fullname= "" ;
   m_cfolder= "" ;
   m_prevfolder= "" ;
   m_numberfiles= 0 ;
   m_numberfolders= 0 ;
  }
//+------------------------------------------------------------------+
CSelectFile::~CSelectFile( void )
  {
   ArrayFree (m_folders);
   ArrayFree (m_files);
   m_chart.Detach();
   CDialog::Destroy();
  }
//+------------------------------------------------------------------+
bool CSelectFile::Create( const long chart, const string name, const int x1, const int y1, const int x2, const int y2)
  {
   if (x2-x1< 280 || y2-y1< 200 ) return ( false );
   m_chart_id=chart;
   m_name=name;
   m_subwin= 0 ;
//--- initialize chart object
   m_chart.Attach(chart);
//--- specify object and mouse events
   if (!m_chart.EventObjectCreate() || !m_chart.EventObjectDelete() || !m_chart.EventMouseMove())
     {
       Print ( "CSelectFile: object events specify error" );
      m_chart.Detach();
       return ( false );
     }
//--- call method of the parent class
   if (!CDialog::Create(m_chart.ChartId(),m_instance_id,m_subwin,x1,y1,x2,y2))
     {
       Print ( "CSelectFile: expert dialog create error" );
      m_chart.Detach();
       return ( false );
     }
   Caption(name);
//--- create dependent controls
//--- create list of files
   int _x1=INDENT_LEFT;
   int _y1=INDENT_TOP;
   int _x2=ClientAreaWidth()-INDENT_RIGHT;
   int _y2=_y1+(ClientAreaHeight()-INDENT_TOP* 5 -EDIT_HEIGHT* 2 );
   if (!m_filelist.Create(m_chart_id,m_name+ "FileList" ,m_subwin,_x1,_y1,_x2,_y2)) return ( false );
   if (!Add(m_filelist)) return ( false );
   m_prevfolder= "" ;
   m_cfolder= "" ;
   SetFolder(m_cfolder);
//--- create field of filename
   _x1=INDENT_LEFT;
   _y1=INDENT_TOP+_y2;
   _x2=ClientAreaWidth()-INDENT_RIGHT;
   _y2=_y1+EDIT_HEIGHT+INDENT_TOP;
   if (!m_filename.Create(m_chart_id,m_name+ "Filename" ,m_subwin,_x1,_y1,_x2,_y2)) return ( false );
   if (!Add(m_filename)) return ( false );
//--- create common check
   _x1=INDENT_LEFT;
   _y1=INDENT_TOP+_y2;
   _x2=_x1+COMMON_WIDTH;
   _y2=_y1+EDIT_HEIGHT;
   if (!m_common.Create(m_chart_id,m_name+ "Common" ,m_subwin,_x1,_y1,_x2,_y2)) return ( false );
   if (!Add(m_common)) return ( false );
   if (!m_common.AddItem( "Common" , 1 )) return ( false );
//--- create button Cancel
   _x1=ClientAreaWidth()-INDENT_RIGHT-BUTTON_WIDTH;
   _x2=_x1+BUTTON_WIDTH;
   _y2=_y1+BUTTON_HEIGHT;
   if (!m_button_cancel.Create(m_chart_id,m_name+ "Cancel" ,m_subwin,_x1,_y1,_x2,_y2)) return ( false );
   if (!m_button_cancel.Text( "Cancel" )) return ( false );
   if (!Add(m_button_cancel)) return ( false );
//--- create button OK
   _x1=_x1-INDENT_RIGHT-BUTTON_WIDTH;
   _x2=_x1+BUTTON_WIDTH;
   if (!m_button_ok.Create(m_chart_id,m_name+ "OK" ,m_subwin,_x1,_y1,_x2,_y2)) return ( false );
   if (!m_button_ok.Text( "OK" )) return ( false );
   if (!Add(m_button_ok)) return ( false );
//----
   m_pressbutton= 0 ;
   m_fullname= "" ;
   m_chart.Redraw();
//----
   if (Id(m_subwin*CONTROLS_MAXIMUM_ID)>CONTROLS_MAXIMUM_ID)
     {
       Print ( "CSelectFile: too many objects" );
       return ( false );
     }
   return ( true );
  }
//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
int CSelectFile::ChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   if (id==(ON_CLICK+ CHARTEVENT_CUSTOM ) && lparam==m_button_ok.Id()) OnClickButtonOK();
   else if (id==(ON_CLICK+ CHARTEVENT_CUSTOM ) && lparam==m_button_cancel.Id()) OnClickButtonCancel();
   else if (id==(ON_CHANGE+ CHARTEVENT_CUSTOM ) && lparam==m_filelist.Id()) OnChangeList();
   else if (id==(ON_CHANGE+ CHARTEVENT_CUSTOM ) && lparam==m_common.Id()) OnCheckCommon();
   else if (!CDialog::OnEvent(id,lparam,dparam,sparam)) return ( 0 );
   m_chart.Redraw();
   return (m_pressbutton);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CSelectFile::OnClickButtonOK( void )
  {
   m_fullname=m_filename.Text();
   StringTrimLeft (m_fullname);
   StringTrimRight (m_fullname);
   if ( StringLen (m_fullname)> 0 )
     {
      m_fullname=m_cfolder+m_fullname;
      m_pressbutton= 1 ;
     }
  }
//+------------------------------------------------------------------+
void CSelectFile::OnClickButtonCancel( void )
  {
   m_pressbutton=- 1 ;
   m_fullname= "" ;
  }
//+------------------------------------------------------------------+
void CSelectFile::OnClickButtonClose( void )
  {
   OnClickButtonCancel();
  }
//+------------------------------------------------------------------+
void CSelectFile::OnChangeList( void )
  {
   int i=( int )m_filelist.Value();
   if (i< 0 ) return ;
   else if (i== 0 )
     {
       string s;
       if (m_cfolder==m_prevfolder || s==m_prevfolder)
        {
         m_cfolder= "" ;
         m_prevfolder=m_cfolder;
         SetFolder(m_cfolder);
        }
       else
        {
         s= "\\" +m_prevfolder;
         StringReplace (m_cfolder,s, "\\" );
         m_prevfolder=m_cfolder;
         if (m_cfolder== "\\" ) m_cfolder= "" ;
         SetFolder(m_cfolder+ "\\" );
        }
      m_filename.Text( "" );
     }
   else if (i<m_numberfolders)
     {
      m_prevfolder=m_folders[i];
      m_cfolder+=m_prevfolder;
      SetFolder(m_cfolder+ "\\" );
      m_filename.Text( "" );
     }
   else m_filename.Text(m_filelist.Select());
  }
//+------------------------------------------------------------------+
void CSelectFile::OnCheckCommon( void )
  {
   m_fileflag=m_common.Value()> 0 ? FILE_COMMON : 0 ;
   if (m_fileflag== 0 )
     {
      m_prevfolder= "" ;
      m_cfolder= "" ;
      SetFolder(m_cfolder);
      m_filename.Text( "" );
     }
   else
     {
      m_prevfolder= "" ;
      m_cfolder= "" ;
      SetFolder(m_cfolder);
      m_filename.Text( "" );
     }
  }
//+------------------------------------------------------------------+
void CSelectFile::SetFolder( string fol= "" )
  {
   string fl,ff,fld=fol;
   StringReplace (fld, "\\\\" , "\\" );
   int i;
   m_filelist.Select( 0 );
   m_filelist.ItemsClear();
   ArrayResize (m_folders, 1 );
   ArrayResize (m_files, 1 );
   if (fld== "Files\\" ) fl= "" ; else fl=fld;
   //---folders
   long   hfind= FileFindFirst (fl+ "*" ,ff,m_fileflag);
   if (hfind== INVALID_HANDLE )
     { //empty folder
      m_numberfiles= 0 ;
      m_numberfolders= 1 ;
      m_folders[ 0 ]= "Files\\" +fld;
      m_filelist.ItemAdd(m_folders[ 0 ]);
      m_totalfiles= 0 ;
     }
   else
     {
      m_numberfiles= 0 ;
      m_numberfolders= 0 ;
       do
        {
         if ( StringFind (ff, "\\" )> 1 ) m_numberfolders++;
         m_numberfiles++;
        }
       while ( FileFindNext (hfind,ff));
       FileFindClose (hfind);
       ArrayResize (m_folders,m_numberfolders+ 1 );
      hfind= FileFindFirst (fl+ "*" ,ff,m_fileflag);
       if (hfind== INVALID_HANDLE ) return ;
      m_numberfolders= 1 ;
       do
        {
         if ( StringFind (ff, "\\" )> 1 ){ m_folders[m_numberfolders]=ff; m_numberfolders++;}
        }
       while ( FileFindNext (hfind,ff));
       FileFindClose (hfind);
       if (fld== "" )
        {
         m_folders[ 0 ]= "Files\\" ;
         ff= "" ;
        }
       else
        {
         m_folders[ 0 ]=fld;
         ff= "Files\\" ;
        }
      m_filelist.ItemAdd(ff+m_folders[ 0 ]);
       int nn=m_numberfolders;
       for (i= 1 ; i<nn; i++) m_filelist.ItemAdd(m_folders[i]);
       //---files
      hfind= FileFindFirst (fl+ "*.*" ,ff,m_fileflag);
      m_numberfiles= 0 ;
       do
        {
         if ( StringFind (ff, "\\" )< 0 ) m_numberfiles++;
        }
       while ( FileFindNext (hfind,ff));
       FileFindClose (hfind);
       if (m_numberfiles> 0 )
        {
         ArrayResize (m_files,m_numberfiles);
         m_numberfiles= 0 ;
         hfind= FileFindFirst (fl+ "*.*" ,ff,m_fileflag);
         if (hfind!= INVALID_HANDLE )
           {
             do
              {
               if ( StringFind (ff, "\\" )< 0 ) { m_files[m_numberfiles]=ff; m_numberfiles++;}
              }
             while ( FileFindNext (hfind,ff));
             FileFindClose (hfind);
           }
         for (i= 0 ; i<m_numberfiles; i++) m_filelist.ItemAdd(m_files[i]);
        }
      m_totalfiles=m_numberfiles+m_numberfolders+ 1 ;
     }
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                              Test_SelectFile.mq5 |
//+------------------------------------------------------------------+
#include <class_SelectFile.mqh>
//+------------------------------------------------------------------+
CSelectFile *SelectFile= NULL ;
//+------------------------------------------------------------------+
int OnInit ()
  {
   SelectFile= new CSelectFile();
   if (!SelectFile.Create( 0 , "Select a file" , 20 , 20 , 350 , 300 )) return (- 1 );
   return ( 0 );
  }
//+------------------------------------------------------------------+
void OnDeinit ( const int reason)
  {
   if (SelectFile!= NULL ) delete SelectFile;
  }
//+------------------------------------------------------------------+
void OnChartEvent ( const int id,         // event ID  
                   const long & lparam,   // event parameter of the long type
                   const double & dparam, // event parameter of the double type
                   const string & sparam) // event parameter of the string type
  {
   if (SelectFile!= NULL )
     {
       int key=SelectFile.ChartEvent(id,lparam,dparam,sparam);
       if (key> 0 )
        { //press button OK
         string file=SelectFile.Filename();
         int flag=SelectFile.FileFlag();
         delete SelectFile;
         SelectFile= NULL ;
         Print ( "The selected file - " ,flag== FILE_COMMON ? "[Common]" : "" ,file);
         int handle= FileOpen (file,flag);
         if (handle> 0 )
           {
             Print (file, " - open" );
             FileClose (handle);
           }
         else Print (file, " - failed to open" );
        }
       else if (key< 0 )
        { //press button Cancel
         delete SelectFile;
         SelectFile= NULL ;
         Print ( "No file selected" );
        }
     }
   if (SelectFile== NULL )
     {
       Print ( "The program is completed" );
       ExpertRemove ();
     }
  }
//+------------------------------------------------------------------+
type change the imem in the graph when clicking on the file. I wanted to know if it's possible, if it's not possible and it's complex I avoid breaking my neurons kkkkkk
 
Daniel Jose #:

De hecho, something happened involving the MT5 updates, that transform the Wallpaper in something different from the expected and shown in the article, since the correct that it be displayed in the GRAPHIC BACKGROUND, because in the C_WallPaper class you will find the following line:

This informs that the object will have to stay in the background, more strangely, it is coming to the front, because of this the OBJECT that receives or BitMap starts to receive the clicks, a solution would be to increase the Status of all objects, or try to lower the Bitmap status, in the case this second one would be simpler, this would be achieved by changing the value of the OBJPROP_ZORDER property in the object that receives the Wallpaper, I tried both solutions, but I couldn't stabilize the whole thing in a way to correct the problem, therefore, and INFELIZMENTE, the wallpaper must be discarded for now ... If you pay attention you will see that the bitmap image is being plotted on the candles body, indicating that the bitmap object is in the foreground, again this is not the expected behaviour because of the above line of code, because of this it happens to receive any and all click events ... 🙁


Daniel,

Is it possible if you put a timer and run a function to disable and enable the wallpaper again or something that "reaffirm" the function by putting the wallpaper in the background (back) ?
A GUI panel I use, I had to go for this solution. Some graphic elements need to be deleted and created again to be in the background or in the front depending on the object type.

 
Thanks for this useful article. Very informative.
 

Daniel, congratulations on your work, I have been using MT4 for years and with the limitation of assets by liquidity providers and brokers I was forced to migrate to MT5 and for some time I have been looking for something to customise my template with images as I use in MT4 and I have the Chart Wall for MT4, follow the download link in MQL5: https://www.mql5.com/en/market/product/2767?source=External%3Ahttps%3A%2F%2Fwww.google.com%2F

And a Youtube video to help anyone who needs it: https: //www.youtube.com/watch?v=AMNhI45EZ2o

Once again, congratulations on your work and open source code.

Best wishes.

COMO MUDAR A IMAGEM DE FUNDO NO MT4 | COLOQUE UM BACKGROUND NO SEU META TRADER 4
COMO MUDAR A IMAGEM DE FUNDO NO MT4 | COLOQUE UM BACKGROUND NO SEU META TRADER 4
  • 2021.06.02
  • www.youtube.com
Aprenda a deixar seu meta trader 4 personalizado, escolha a imagem que desejar e use como plano de fundo, simples e fácil. No vídeo mostro passo a passo como...
 

Hello, Daniel. What's up?

Sorry to resurrect the thread... I'm using your code in my E.A and I'm getting the following error: "file not found", I've read the code several times and I can't find the error, I've done all the steps you left... And I also used the image files you downloaded and the same error occurred. Could you help me? Thanks in advance!

 
leandronetto011 #:

Hello, Daniel. What's up?

Sorry to resurrect the thread... I'm using your code in my E.A and I'm getting the following error: "file not found", I've read the code several times and I can't find the error, I've done all the steps you left... And I also used the image files you downloaded and the same error occurred. Could you help me? Thanks in advance!

I don't understand 🤔🤔 ... you need to download and unzip the file in the MQL5 folder. To do this properly: Open MetaEditor. In the right-hand corner you'll see the folder browser. Right-click on ROOT ( MQL5 ) and select OPEN FOLDER. The Explorer will open in the MQL5 folder. In this folder, unzip the ZIP file. This way the images will be found when you launch the system on the chart.