WindowScreenShot and Multiple Timeframes

 

Hi All,

So that I can review my trades, I would like to take a screenshot of MULTIPLE timeframes for a given Symbol. I want to do this via MQL code, so the process is all automated..

Taking a single screenshot is easy, coded that and it is all working fine.

However, all attempts at doing screenshots for higher timeframes have failed for me.

Here is what I have tried:

1. Within a script, I Used WindowHandle to get the handle for the windows for the other timeframes, then used SendMessageA to activate and maximise different timeframes (assuming they are on the profile).

This DOES work in that I can maximise the windows for each timeframe, BUT then when I do WindowScreenShot, the timeframe for which the script is attached is printed.

2. Also, on this forum I have found code to issue a SendMessageA command to change the timeframe for the window the script is attached.

However, this causes the script to end, and no screenshot is taken.

I'm a bit baffled by this and really hope someone has any ideas. Even if the solution involves calling an external dll, that takes the handle of the window I want to print.

Regards

David

 
DJW:

2. Also, on this forum I have found code to issue a SendMessageA command to change the timeframe for the window the script is attached.


Where?

May be you should combine the two scripts. In the one you mention above (the one that was to be attached :)) right after the place in the code where it changes the timeframe place your TakeTheScreenShot piece of code. Maybe that will work. Without the code itself that is the best advice anyone will be able to give.

 
DJW:

Hi All,


I'm a bit baffled by this and really hope someone has any ideas. Even if the solution involves calling an external dll, that takes the handle of the window I want to print.

Show your code and please use the SRC button to post code: How to use the SRC button.
 

pro, RaptorUK,

Thank you for your responses. I guess I wasn't clear in what I meant. Anyhow, below is code that does step 1, as originally posted. In my case, I have 15min, 30min, 1hr, 4hr, and daily charts for a given symbol. If I have this script attached to the 15min chart, then a screenshot will be made for each of the higher timeframes, BUT, all of the printed charts will be for 15 mins.

I will get an example together for point 2 and post it soon.

//+------------------------------------------------------------------+
//|                                             MultiScreenShot.mq4  |
//+------------------------------------------------------------------+

#import "user32.dll"
int GetParent(int hWnd);

#include <WinUser32.mqh>

int P;
int hwnd;
string ImageName;

int PTimeFrame[] = {1,5,15,30,60,240,1440,10080,43200};
string PTimeFrameDescriptionShort[] = {"1Min","5Min","15Min","30Min","1H","4H","Daily","Weekly","Monthly"};

void start()
{
   P = Period(); //Current Timeframe
  
   //The following will toggle through all of the possible Timeframes.
   for(int j = 0;j < ArraySize(PTimeFrame);j++)
   {
      hwnd = WindowHandle( Symbol(), P);
      
      //Only do something with the Timeframe if it exists for the given profile.
      if (hwnd > 0)
      {
         Window.activate(hwnd);
         Window.maximize(hwnd);

         //For demonstration only, show the screen "working" through the different timeframes.
         Sleep(1000);

         ImageName = StringConcatenate(Symbol(),"_",
                                       PTimeFrameDescriptionShort[ArrayBsearch(PTimeFrame,P)],".gif");

         WindowScreenShot("shots\\"+ImageName,640,480,-1,-1,CHART_CANDLE );

         //Get Next Timeframe
         P = getNextTimeframe(P);
      }
   }

}

//+---------------------------------------------------------------------+
//+                                                                     +
//+   getNextTimeframe                                                  +
//+                                                                     +
//+   Identify the higher timeframe for a given timeframe               +
//+                                                                     +
//+---------------------------------------------------------------------+
int getNextTimeframe(int TimeFrame)
{
   int NextTF, TFMaxPos, TFPos;
   
   TFMaxPos = ArraySize(PTimeFrame) - 1;
   TFPos = ArrayBsearch(PTimeFrame,TimeFrame);
   
   //Are we currently on the last element in the Time Frame Array
   if (TFPos == TFMaxPos)
      return(-1);
   
   NextTF = PTimeFrame[TFPos + 1];

   return(NextTF);
}

//+-------------------------------------------------------------------------------+

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

Ok, so here is my second code example to highlight point 2 of my original post. This example makes use of PostMessageA. However, when I run this I get the "Do you really want to Stop using script message", as per the attached image.


//+------------------------------------------------------------------+
//|                                             MultiScreenShot.mq4  |
//| Perform screenshots of different timeframes by changing the      |
//| period for the existing chart.                                   |
//+------------------------------------------------------------------+

#import "user32.dll"
int GetParent(int hWnd);
int GetAncestor (int hwnd, int gaFlags);

#include <WinUser32.mqh>

int P;
int hwnd;
int hTerminal;

string ImageName;

int PTimeFrame[]                    = {1,5,15,30,60,240,1440,10080,43200};
string PTimeFrameDescriptionShort[] = {"1Min","5Min","15Min","30Min","1H","4H","Daily","Weekly","Monthly"};
int MT4_WMCMD_PERIOD[]              = {33137 ,33138 ,33139 ,33140 ,33135 ,33136 ,33134 ,33141 ,33334 };  

void start()
{
   P = Period(); //Current Timeframe
   hwnd = WindowHandle( Symbol(), P);
   hTerminal = GetAncestor(hwnd,2);

   //The following will toggle through all of the possible Timeframes.
   for(int j = 0;j < ArraySize(PTimeFrame);j++)
   {
      
      hwnd = WindowHandle( Symbol(), P);
      //Only do something with the Timeframe if it exists for the given profile.
      if (hwnd > 0)
      {
         PostMessageA(hTerminal ,WM_COMMAND , MT4_WMCMD_PERIOD[ArrayBsearch(PTimeFrame,P)], 0); 
         
         //Window.activate(hwnd);
         //Window.maximize(hwnd);

         //For demonstration only, show the screen "working" through the different timeframes.
         Sleep(1000);

         ImageName = StringConcatenate(Symbol(),"_",
                                       PTimeFrameDescriptionShort[ArrayBsearch(PTimeFrame,P)],".gif");

         WindowScreenShot("shots\\"+ImageName,640,480,-1,-1,CHART_CANDLE );

         //Get Next Timeframe
         P = getNextTimeframe(P);
      }
   }

}

//+---------------------------------------------------------------------+
//+                                                                     +
//+   getNextTimeframe                                                  +
//+                                                                     +
//+   Identify the higher timeframe for a given timeframe               +
//+                                                                     +
//+---------------------------------------------------------------------+
int getNextTimeframe(int TimeFrame)
{
   int NextTF, TFMaxPos, TFPos;
   
   TFMaxPos = ArraySize(PTimeFrame) - 1;
   TFPos = ArrayBsearch(PTimeFrame,TimeFrame);
   
   //Are we currently on the last element in the Time Frame Array
   if (TFPos == TFMaxPos)
      return(-1);
   
   NextTF = PTimeFrame[TFPos + 1];

   return(NextTF);
}

//+-------------------------------------------------------------------------------+

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

Error message when changing timeframe

Files:
 
DJW:

Ok, so here is my second code example to highlight point 2 of my original post. This example makes use of PostMessageA. However, when I run this I get the "Do you really want to Stop using script message", as per the attached image.


The previous instance of your script did not finish running yet, you can only run one script at a time, so to run the 2nd instance you must first end the first instance, hence the message ?
 
RaptorUK:
The previous instance of your script did not finish running yet, you can only run one script at a time, so to run the 2nd instance you must first end the first instance, hence the message ?


RaptorUK,

Yes, this is my dilemma. I'm after help so that I can take screenshots of multiple timeframes of the same Symbol. Is it possible for a script to call another script ?

 
DJW:


RaptorUK,

Yes, this is my dilemma. I'm after help so that I can take screenshots of multiple timeframes of the same Symbol. Is it possible for a script to call another script ?

Why would you ? just combine the scripts into one.

Looking at your code it seems that you are trying to change window . . don't you want to change the timeframe on the current chart ? even if you change timeframe your script will exit, perhaps you need to use an Indicator to take the screen shots and remember (file, Global Variable or chart Object) which timeframe you last captured.

 

This might help: https://www.mql5.com/en/forum/140692

By the way, a Script, Indicator or EA will only take a screen shot from the chart to which it is attached.

 

RaptorUK,

Thanks for your comments. It's getting late here. I'll digest your latest comments tomorrow.

 

It's been a while since my last post. Too much stuff on the go at once :-(. Anyhow, I have come to the belief that I can't do what I want to do exclusively using MQL. So I looked into 3rd party packages that can perform screen printing. I'm including this note so that if someone else wants to do what I have described here is a solution.

I am using Gadwin Screenprint (http://www.gadwin.com/printscreen/). The program can be called from a command line. The following is code that I have written to achieve my aim:

//+------------------------------------------------------------------+
//|                                             MultiScreenShot.mq4  |
//+------------------------------------------------------------------+

#import "user32.dll"
int GetParent(int hWnd);
#import

#import "shell32.dll"
int ShellExecuteA(int hwnd,string Operation,string File,string Parameters,string Directory,int ShowCmd);
#import

#include <WinUser32.mqh>

#define VK_F11 0x7A
#define DELAY  500 //1/2 sec

int P;
int hwnd, rc;
string ImageName, Parameters;

int PTimeFrame[] = {1,5,15,30,60,240,1440,10080,43200};
string PTimeFrameDescriptionShort[] = {"1Min","5Min","15Min","30Min","1H","4H","Daily","Weekly","Monthly"};

void start()
{
   P = Period(); //Current Timeframe
  
   //The following will toggle through all of the possible Timeframes.
   for(int j = 0;j < ArraySize(PTimeFrame);j++)
   {
      hwnd = WindowHandle( Symbol(), P);
      
      //Only do something with the Timeframe if it exists for the given profile.
      if (hwnd > 0)
      {
         Window.activate(hwnd);
         Window.maximize(hwnd);

         //The following logic will simulate pressing F11, to display chart in Full screen. This is so the 
         //screen shot will ONLY include the chart
         keybd_event(VK_F11,0,0,0);
         Sleep(10);
         keybd_event(VK_F11,0,2,0);

         ImageName = StringConcatenate(Symbol(),"_",
                                       PTimeFrameDescriptionShort[ArrayBsearch(PTimeFrame,P)]);
          
         Parameters = "/file="+ImageName;

         //Screen is maximised, at this point - call screen shot etc
         
         //Gadwin Printscreen has been configured for all of the common parameters. However, we need to specify 
         //the name of the screen shot. This can't be done at the same time as performing the actual screenprint.
         rc = ShellExecuteA(0, 
                              "open",
                              "C:\Program Files (x86)\Gadwin Systems\PrintScreen\PrintScreen.exe", 
                              Parameters,
                              "",
                              1);
         Sleep(DELAY);

         //Perform the screenshot
         rc = ShellExecuteA(0, 
                              "open",
                              "C:\Program Files (x86)\Gadwin Systems\PrintScreen\PrintScreen.exe", 
                              "/justnow",
                              "",
                              1);
         Sleep(DELAY);

         //Exit out, so next time it is ready to be modified for the next screen name
         rc = ShellExecuteA(0, 
                              "open",
                              "C:\Program Files (x86)\Gadwin Systems\PrintScreen\PrintScreen.exe", 
                              "/exit",
                              "",
                              1);

         Sleep(DELAY);

         //Issue F11 to display chart in Normal Screen    
         keybd_event(VK_F11,0,0,0);
         Sleep(10);
         keybd_event(VK_F11,0,2,0);

         //Get Next Timeframe
         P = getNextTimeframe(P);
      }
   }

}

//+---------------------------------------------------------------------+
//+                                                                     +
//+   getNextTimeframe                                                  +
//+                                                                     +
//+   Identify the higher timeframe for a given timeframe               +
//+                                                                     +
//+---------------------------------------------------------------------+
int getNextTimeframe(int TimeFrame)
{
   int NextTF, TFMaxPos, TFPos;
   
   TFMaxPos = ArraySize(PTimeFrame) - 1;
   TFPos = ArrayBsearch(PTimeFrame,TimeFrame);
   
   //Are we currently on the last element in the Time Frame Array
   if (TFPos == TFMaxPos)
      return(-1);
   
   NextTF = PTimeFrame[TFPos + 1];

   return(NextTF);
}

//+-------------------------------------------------------------------------------+

int Window.activate(int hwnd) {
   int p = GetParent(hwnd);
   SendMessageA(GetParent(p), WM_MDIACTIVATE, p, 0);
}
int Window.maximize(int hwnd) {
   int p = GetParent(hwnd);
   SendMessageA(GetParent(p), WM_MDIMAXIMIZE, p, 0);
}
Files:
Reason: