使用[user32.dll]和[kernel32.dll] Win-API调用在MQL4中打开一个离线图表

时间:2015-07-12 11:03:55

标签: winapi metatrader4

我有以下代码在metatrader 4中打开离线图表。 但我能做的就是打开离线文件列表。我不是 非常熟悉Windows编程,所以有人能告诉我我做错了什么吗?

#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;
}

1 个答案:

答案 0 :(得分:0)

我不是WinApi的专家,问题显然是陈旧的,但它仍然是相关的。所以问题是你使用FindFirstFileA(),它使用ANSI字符串,但是在600版本之后MT4使用Unicode,所以你需要使用 FindFirstFileW() 。另外,您应该使用 SendMessage() 代替PostMessage()(请不要问我为什么)。所以这是工作代码:

#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;
}

但现在 ( Build 970+ ) ChartOpen( "AUDUSD", 2 );一起使用起来要简单得多。因此,如果您不使用自定义名称作为符号,则可以将所有内容替换为只需一行代码。