0

I have the following code to open an offline chart in metatrader 4. But all I could get it to do is open the offline file list. I am not very familiar with windows programming so can someone tell me 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 );
    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( "AUDUSD", 120 );
  return;
}
user3666197
  • 1
  • 6
  • 50
  • 92
user994572
  • 139
  • 1
  • 11

1 Answers1

0

I'm not an expert in WinApi and the question is obviously old, but it is still relevant. So the problem is that you use FindFirstFileA(), which uses ANSI strings, but after 600 release MT4 uses Unicode, so you need to use FindFirstFileW() instead. Also, instead of SendMessage() you should use PostMessage() (pls don't ask me why). So here is the working code:

#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  FindFirstFileW( string Path, ushort &Answer[] );
   bool FindNextFileW(  int handle,  ushort &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 )
  {
   ushort Buffer[300];
   int Pos=-1;
   string path = TerminalInfoString( TERMINAL_DATA_PATH ) + "\\history\\" + AccountInfoString( ACCOUNT_SERVER ) + "\\*.hst";
   int handle  = FindFirstFileW( path, Buffer );
   string name = ShortArrayToString( Buffer, 22, 152 );
   Pos++;
   if(name!=FileName) 
     {
      ArrayInitialize(Buffer,0);
      while(FindNextFileW(handle,Buffer))
        {
         name=ShortArrayToString(Buffer,22,152);
         Pos++;
         if(name==FileName) 
           {
            break;
           }
         ArrayInitialize(Buffer,0);
        }
     }

   if(handle>0)
      FindClose(handle);

   return(Pos);
  }

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

  hwnd     = GetAncestor( hwnd, GA_ROOT );
  PostMessageA( 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 ) {
    PostMessageA( hwnd1, WM_KEYDOWN, VK_DOWN, 0 );
    ChartPos--;
  }
  Sleep( PAUSE );
  PostMessageA( hwnd2, BM_CLICK, 0, 0 );
  return;
}

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

int init()
{
  OpenOfflineChart( "AUDUSD", 120 );
  return;
}

But now ( Build 970+ ) it is much simpler to go with ChartOpen( "AUDUSD", 2 ); So, if you don't use custom names for symbols, you can replace all that with just one line of code.

user3666197
  • 1
  • 6
  • 50
  • 92
Sergey
  • 26
  • 3