Kiedyś ktoś mnie o to pytał, szczególnie pod kątem samo-optymalizującego się EA

Ogólnie, aby uruchomić jakiś nowy program w MQL wystarczy funkcja ShellExecute() z shell32.dll:
http://msdn.microsoft.com/en-us/library ... s.85).aspx
Implementacja:
Kod: Zaznacz cały
#import "shell32.dll"
int ShellExecuteA(int hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
#import
Wywołanie:
Kod: Zaznacz cały
ShellExecuteA(0, "Open", "cmd.exe", "", "C:\", 1);
Albo np... restart komputera:
Kod: Zaznacz cały
ShellExecuteA(0, "Open", "shutdown.exe", "-r", "", 1);
Kod: Zaznacz cały
ShellExecuteA(0, "Open", "terminal.exe", "", "C:\Program Files\Metatrader\", 1);
Kod: Zaznacz cały
ShellExecuteA(0, "Open", "terminal.exe", "mojkonfig.txt", "C:\Program Files\Metatrader\", 1);
Powyższa linia uruchomi terminal wskazując mu plik mojkonfig.txt jako zawierający szczegóły testu do wykonania (to przykład z help):
Kod: Zaznacz cały
mojkonfig.txt:
TestExpert=Moving Average
TestExpertParameters=ma0.set
TestSymbol=EURUSD
TestPeriod=H1
TestModel=2
TestOptimization=false
TestDateEnable=true
TestFromDate=1970.01.01
TestToDate=2006.06.06
TestReport=MovingAverageReport
TestReplaceReport=false
TestShutdownTerminal=true

A teraz, jak ponownie uruchomić ten sam terminal?
MT4 sprawdza czy jest już uruchomiony i nie pozwala na duplikaty z tej samej lokalizacji więc samo uruchomienie tego samego programu nic nie da.
Trzeba go najpierw zamknąć, a następnie uruchomić ponownie.
Ręcznie nie ma problemu. Ale jak ma to zrobić skrypt czy EA? Przecież przestanie działać wraz z zamknięciem gospodarza...
W zasadzie prosto - EA czy skrypt musi wpierw... uruchomić terminal.exe w lokalizacji w której aktualnie pracuje, a następnie zamknąć poprzednią postać w której działa. Coś nie tak - przed chwilą napisałem, że tak nie zadziała bo program sprawdzi i nie pozwoli... No cóż, jest logika maszynowa i logika zdarzeń - tutaj mamy do czynienia z tą drugą.
Trick polega na tym, że uruchamianie trwa znacznie dłużej niż zamykanie więc zanim nowa postać dojdzie to tego żeby cokolwiek sprawdzić, poprzednia już nie powinna istnieć ;-)
Aby uruchomić terminal wystarczy:
Kod: Zaznacz cały
ShellExecuteA(0, "Open", "terminal.exe", "", TerminalPath(), 1);
Tutaj podeprę się dwoma funkcjami z user32.dll:
http://msdn.microsoft.com/en-us/library ... s.85).aspx
http://msdn.microsoft.com/en-us/library ... s.85).aspx
Implementacja:
Kod: Zaznacz cały
#import "User32.dll"
int GetAncestor(int hWnd, int gaFlags);
bool EndTask(int hWnd, bool fShutDown, bool fForce);
#import
Pierwsza pozwoli mi znaleźć uchwyt głównego okna na podstawie uchwytu okna wykresu w którym pracuje skrypt/EA - MQL dostarcza funkcję podającą uchwyt bieżącego okna:
Kod: Zaznacz cały
int hwnd = WindowHandle(Symbol(),Period()); // pobierz uchwyt okna wykresu
int terminalHwnd = GetAncestor(hwnd, 2); // znajdz główne okno właściciela
Kod: Zaznacz cały
EndTask(terminalHwnd, false, false); // drugi parametr określa tryb wyłączenia. TRUE = wymuszenie natychmiastowego przerwania pracy i zamknięcia, FALSE = normalne zamknięcie
Kod: Zaznacz cały
void panic()
{
int hwnd = WindowHandle(Symbol(),Period());
int terminalHwnd = GetAncestor(hwnd, 2);
ShellExecuteA(0, "Open", "terminal.exe", "", TerminalPath(), 1);
EndTask(terminalHwnd, false, false);
}
Albo np. uruchomienie ze wskazanym skryptem. Jak kto lubi
