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.
 
Help me fix this "File not found." when i restart mt5
 
Paulo Tassio Da Silva Lordelo #:
Help me fix this "File not found." when i restart mt5

Got it, this error appears when using the same wallpaper in more than one graphic

Reason: