Open an offline chart programmatically !

 

Hi,

I have the following program from the net modified to open an offline chart. But all it does it

open the offline chart-list. The key down and selecting the chart-list entry does not work.

If someone who is familiar with windows programming please let me know what am I doing wrong ?


#import "user32.dll"
  int PostMessageA( int hWnd, int Msg, int wParam, int lParam );
  int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
  int GetAncestor( int hWnd, int gaFlags );
  int GetLastActivePopup( int hWnd );
  int GetDlgItem( int hDlg, int nIDDlgItem );
#import

#import "kernel32.dll"
  int  FindFirstFileA( string Path, int& Answer[] );
  bool FindNextFileA( int handle, int& Answer[] );
  bool FindClose( int handle );
#import

#define WM_COMMAND 0x0111
#define WM_KEYDOWN 0x0100
#define VK_DOWN 0x28
#define BM_CLICK 0x00F5
#define GA_ROOT 2
#define PAUSE 100

string BuffToString( int& Buffer[] )
{
  string Str = "";
  int Pos = 11;

  while (Pos < 75)
  {
    while (Buffer[Pos] != 0)
    {
      Str = Str + CharToStr(Buffer[Pos] & 0xFF);

      Buffer[Pos] /= 0x100;
    }
    Pos++;
  }

  return(Str);
}

int GetChartPos( string FileName )
{
  int Buffer[79];
  int Pos = 0;
  int handle = FindFirstFileA(TerminalPath() + "\history\\"  + AccountServer() + "\\*.hst", Buffer);

  if (BuffToString(Buffer) != FileName)
  {
    Pos++;

    while (FindNextFileA(handle, Buffer))
    {
      if (BuffToString(Buffer) == FileName)
        break;

      Pos++;
    }
  }

  if (handle > 0)
    FindClose(handle);

  return(Pos);
}

int OpenOfflineList()
{
  int hwnd = WindowHandle(Symbol(), Period());

  hwnd = GetAncestor(hwnd, GA_ROOT);

  SendMessageA(hwnd, WM_COMMAND, 33053, 0);
  Sleep(PAUSE);

  hwnd = GetLastActivePopup(hwnd);

  return(hwnd);
}

void OpenOfflineChartbyNum( int ChartPos )
{
  int hwnd1 = OpenOfflineList();
  int hwnd2 = GetDlgItem(hwnd1, 1);

  hwnd1 = GetDlgItem(hwnd1, 0x487);

  while (ChartPos >= 0)
  {
    //SendMessageA(hwnd1, WM_KEYDOWN, VK_DOWN, 0);
    PostMessageA(hwnd1, WM_COMMAND,0x33197,0);
    ChartPos--;
  }

  Sleep(PAUSE);
  SendMessageA(hwnd2, BM_CLICK, 0, 0);

  return;
}

void OpenOfflineChart( string Symb, int period )
{
  OpenOfflineChartbyNum(GetChartPos(Symb + period + ".hst"));

  return;
}

int init()
{
  OpenOfflineChart("AUDCAD", 120);
  return;
} 
 
maindoor:

Hi,

I have the following program from the net modified to open an offline chart. But all it does it

open the offline chart-list. The key down and selecting the chart-list entry does not work.

If someone who is familiar with windows programming please let me know what am I doing wrong ? 

Here you have the function for opening the offline chart using the chart list popup (without dependencies, I explain why later). The trick is to force the US keyboard (users have different layouts, different sorting) and fill in the input buffer with proper key strokes. Because the offline list opens with significant delay, you have to use a timer to release the US layout with some delay (900 ms in the code).

            void openOffline745() {
               TRACEIN_;               
               // message to open menu File -> Open Offline
               PostMessageW(GetAncestor((HWND)ChartGetInteger(0,CHART_WINDOW_HANDLE),2), WM_COMMAND, 33053, 0);

               // keep current locale
               HKL origH = GetKeyboardLayout(0);
               
               // set US English locale
               string uslayout = "00000409";               
               HKL h = LoadKeyboardLayoutW(uslayout, 0x00000001);
                  
              // ctrl up
               keybd_event(0xA0, 0x2A, KEYEVENTF_KEYUP,0); // ‘left ctrl’ Release
               keybd_event(0xA1, 0x36, KEYEVENTF_KEYUP,0); // ‘righ ctrl’ Release
                              
               // fill keyboard buffer with the offline list item, append TAB and RETURN to press the Open button
               sendStringToKeyboard(offscope.getSymbol().name() + "," + OfflineUtil::getTfString(offscope.getTimeframe()*60)+"\t"+"\r", h);             

               class DelayedKeyboardSwitch: public MT4TimerSingleListener {
                  // locale
                  HKL handle;
                  
                  public:
                  DelayedKeyboardSwitch(HKL aHandle) :MT4TimerSingleListener(NULL, 900), handle(aHandle) {}
                  
                  // timer event handler
                  void run() {
                     TRACEIN("ActivateKeyboardLayout");
                     ActivateKeyboardLayout(handle,0);
                     TRACEOUT_;
                  }
               };
               
               // return recent locale after short delay
               manager.add(new DelayedKeyboardSwitch(origH));
               
               TRACEOUT_;
            }
           
            /** For codes see http://www.codeproject.com/Articles/7305/Keyboard-Events-Simulation-using-keybd-event-funct */
            void sendStringToKeyboard(string keyboardString, HKL h) {
               TRACEIN_;
               
               ushort charArray[];
               StringToShortArray(keyboardString, charArray);
               
               for(int i = 0; i < ArraySize(charArray); i++) {
                  switch (charArray[i]) {
                  case 0:
                     //if(charArray[i] == NULL) continue;                  
                     continue;
                     break;
                  case '_': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("-",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '#': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("3",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '!': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("1",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '%': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("5",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '&': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("7",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '$': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("4",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '@': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("2",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '^': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("6",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '*': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("8",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '(': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("9",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case ')': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("0",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '?': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("/",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '<': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard(",",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '>': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard(".",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '~': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("`",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '+': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("=",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case ':': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard(";",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '"': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("\'",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '|': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("\\",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '}': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("]",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  case '{': {
                     keybd_event(0xA0,0x2A, 0 , 0); // shift down
                     sendStringToKeyboard("[",h);
                     keybd_event(0xA0,0x2A, KEYEVENTF_KEYUP,0); // shift release                  
                     }
                     break;
                  default: {
                     TRACE("VkKeyScanExW " + charArray[i]);
                     uchar vkey = (uchar)VkKeyScanExW(charArray[i], h);                  
                     TRACE("MapVirtualKeyW " + vkey);
                     uchar skey = (uchar)MapVirtualKeyW(vkey, 0);
                     TRACE("skey " + skey);
                     MT4String d;
                     d + "letter, char: "+ ShortToString(charArray[i])+ ", "+  charArray[i] 
                        //+ ", "+  vkey + ", "+ skey
                        ;
                     DEBUG(d.toString());
                     keybd_event(vkey,skey,0 , 0); // ‘A’ Press
                     keybd_event(vkey,skey, KEYEVENTF_KEYUP,0); // ‘A’ Release                  
                     }
                     break;
                  }
               }
               
               TRACEOUT_;
            }

 

Fortunately, the public builds following the build 745 have implemented ChartOpen(symbol, timeframe) command even for the offline charts, so if you are above the 745, you may ignore the inserted code.

 

Thank you very much for that information stranger.

I got misled by this information: https://forum.mql4.com/65762#1000456

BTW, how do you get such updated information where as all I get is this: https://docs.mql4.com/chart_operations/chartopen ?

 

BTW, how do we open time shifted offline charts using chartopen ? I am using a build above 75.

Time shifted charts of the format AUDCAD-75M480.hst

 
maindoor:

Thank you very much for that information stranger.

I got misled by this information: https://forum.mql4.com/65762#1000456

BTW, how do you get such updated information where as all I get is this: https://docs.mql4.com/chart_operations/chartopen ?

 

The information was correct at that time.

The change's been listed under the paragraph 17:  https://forum.mql4.com/65974

 

maindoor:

BTW, how do we open time shifted offline charts using chartopen ? I am using a build above 75.

Time shifted charts of the format AUDCAD-75M480.hst


I did not test such artificial symbols (not listed in the symbol.sel), so it could be your turn. If you find out, I am eager to hear the statement.