0

我有以下代码可以在 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;
}
4

1 回答 1

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 );因此,如果您不使用符号的自定义名称,则只需一行代码即可替换所有这些名称。

于 2016-06-19T10:15:53.193 回答