Alert или Print в "Блокнот" из эксперта? - страница 2

 

Думаю Ваш случай хорошо понимаю, сам с таким вопросом сталкивался. Для себя сделал следующим образом: из мкл вызывается функция, которая открывает окно блокнота (стандартный виндоус блокнот) и в нем отображается это сообщение. Одно сообщение, одно окно блокнота. Очень удобно, прочитал - закрыл. Если интересно, могу выложить код. Но написано на C++, т.е. нужно создать dll и подключать ее к эксперту. Вам интересно?

 
expertboss:

Опять же вопрос не теоретический а практический КАК сделать?

  =============================================================================

Как-то для себя писал функцию, которая выводит в отдельном окне пустого индикатора события, происходящие в эксперте строчку за строчкой, строчки могут иметь каждая свой цвет. Неохота тут всё расписывать. Поглядите проверочный эксперт с этой функцией. Не забудьте сначала повесить на график окно индикатора Win_Inform. Без него функция выводит в журнал. Может подойдёт вам, если разберётесь...

Эксперт пустой, я взял свой шаблончик и вписал только определения необходимых параметров для вызова функции и, соответственно сама функция. (из него потом функцию выдерните и по аналогии будете в своём вызывать)

//-----------------------------------------------------------------------------+
#property copyright "Copyright © 2012, Trishkin Artyom A."
#property link      "artmedia70@gmail.com"
//                   Skype: Artmedia70
//-----------------------------------------------------------------------------+
#include <stdlib.mqh>
#include <stderror.mqh>
#include <WinUser32.mqh>
//==============================================================================
// --------------------------- Переменные советника ---------------------------+
//==============================================================================
extern string  P_Expert= "-- Experts Variables --";
//------- Параметры исполнения торговых приказов ------------------------------+
extern string  P_Performanc= "-- Parameters for Trades --";
//-----------------------------------------------------------------------------+
double         PointX, LotsB, LotsS, Lots_New, MinLot, MaxLot, LotStp,
               Equ_Start, EquPerc, Equ_OLD, Equ_NEW;
string         sy;
int            tf, dg, sp, a,b,c;
double         pt, pa, pb;
//-----------------------------------------------------------------------------+
int            Level_old, 
               Level_new, 
               Magic;
string         New_Comm, Exp_Name, Prefix,
               message1, message2, message3, message4, 
               Mass_Name_Message[10];
//==============================================================================
//---------------------- Переменные для функций--------------------------------+
//==============================================================================
//+----------------------------------------------------------------------------+
int init() {
   if(Digits==5 || Digits==3) PointX = Point * 10; // Корректировка Point под трёх- пятизнак
   if(Digits==4 || Digits==2) PointX = Point;
   Exp_Name=WindowExpertName(); 
   Prefix=Exp_Name;  
   Magic=GetMagic(Exp_Name+Symbol(),Period()); 
   return;                                         // Выход из init() 
}
//+----------------------------------------------------------------------------+
int deinit() {
   if (!IsTesting()) {
      Comment("");
   // -------- Блок удаления всех объектов, построенных на графике --------
      string Name_Del[1]; 
      int Quant_Del=0;                    
      int Quant_Objects=ObjectsTotal();   
      int LenPref=StringLen(Prefix);
      ArrayResize(Name_Del,Quant_Objects);
      for(int k=0; k<Quant_Objects; k++) {
         string Obj_Name=ObjectName(k);   
         string Head=StringSubstr(Obj_Name,0,LenPref);
         if (Head==Prefix) {                              
            Quant_Del+=1;        
            Name_Del[Quant_Del-1]=Obj_Name;
            }
        }
      for(int i=0; i<Quant_Del; i++)    
         ObjectDelete(Name_Del[i]); 
// ----- Конец блока удаления всех объектов, построенных на графике -----
      }
   return;                                // Выход из deinit()
}
//+----------------------------------------------------------------------------+
int start() {
   sy=Symbol();
   tf=Period();
   dg=MarketInfo(sy,MODE_DIGITS);
   sp=MarketInfo(sy,MODE_SPREAD);
   pt=MarketInfo(sy,MODE_POINT);
   pa=MarketInfo(sy,MODE_ASK);
   pb=MarketInfo(sy,MODE_BID);
//----------- Инициализация флагов ------------   

//----------- Инициализация лотов -------------   

//----------- Имена глоб. переменных ----------   

//----------- Инициализация глоб. переменных ------------   

//-------------------------------------------------------
   message1=StringConcatenate("Тик: ",GetTickCount()," ");
   message2=StringConcatenate("Цена Bid: ", DoubleToStr(Bid,dg));
   iPrint(false, message1, message2, "", "", 9, Aqua, DarkOrange);
   b=4; c=7;
   a=b+c;
   message1=StringConcatenate("a=",a," ");
   message2=StringConcatenate("b=",b," ");
   message3=StringConcatenate("c=",c);
   iPrint(false, message1, message2, message3, "", 9, Aqua, LimeGreen, DarkOrange);
   
   message1=StringConcatenate("Время: ", TimeToStr(TimeCurrent())," ");
   message2=StringConcatenate("Тик: ",GetTickCount()," ");
   message3=StringConcatenate("Время бара: ",TimeToStr(Time[0])," ");
   message4=StringConcatenate("Цена Bid: ", DoubleToStr(Bid,dg));
   iPrint(false, message1, message2, message3, message4, 9, Aqua, Aqua, Aqua, DarkOrange);
   return;                                // Выход из start()
}
//+----------------------------------------------------------------------------+
void iPrint(bool print, string mess1, string mess2="", string mess3="", string mess4="", 
            int sz=9, color cl1=Aqua, color cl2=Aqua, color cl3=Aqua, color cl4=Aqua) {
   string   NameGrafText, message, nm;
   int      i, y, k, LenStr, shift, Win_Num=-1, num=0;
   color    cl;
   if (mess1=="") {
      Print("Func iPrint: Передана пустая строка, выходим");
      return;
      }
   Win_Num=WindowFind("Win_Inform");
   if (print || Win_Num<0) {
      message=mess1+mess2+mess3+mess4;
      Print(message); 
      return;
      }
   k=ArraySize(Mass_Name_Message)-1;
   if (StringLen(mess1)>0) num++;
   if (StringLen(mess2)>0) num++;
   if (StringLen(mess3)>0) num++;
   if (StringLen(mess4)>0) num++;
   for (i=k; i>=0; i--) {                             
      NameGrafText=Mass_Name_Message[i];           
      if (StringLen(NameGrafText)>0)
      if (ObjectFind(NameGrafText)==Win_Num) {
         if (i+num>k) {
            ObjectDelete(NameGrafText);  
            Mass_Name_Message[i]="";
            }
         else if (i+num<=k) {
            Mass_Name_Message[i+num]=Mass_Name_Message[i];
            y=ObjectGet(NameGrafText, OBJPROP_YDISTANCE);               // координата Y
            ObjectSet  (NameGrafText, OBJPROP_YDISTANCE, y+(sz+1)*num); // координата Y
            ObjectSet  (NameGrafText, OBJPROP_COLOR, LightSeaGreen);    // цвет
            }
         }
      }
   shift=num;
   int v=GetTickCount();
   for (i=0; i<num; i++) {
      shift--;
      NameGrafText=Prefix+"_Graf_Text_"+i+"_"+sy+"_"+v;
      int app=0;
      while (ObjectFind(NameGrafText)==Win_Num) {
         app++;
         NameGrafText=Prefix+"_Graf_Text_"+i+"_"+sy+"_"+v+"_"+app;
         }
      Mass_Name_Message[num-1-i]=NameGrafText;
      switch (i) {
         case 0: message=mess1; cl=cl1; break;
         case 1: message=mess2; cl=cl2; break;
         case 2: message=mess3; cl=cl3; break;
         case 3: message=mess4; cl=cl4; break;
         default:message=mess1; cl=cl1; break;
         }
      ObjectCreate (NameGrafText, OBJ_LABEL, Win_Num, 0, 0);
      ObjectSetText(NameGrafText, message, sz, "Courier New", cl);
      ObjectSet    (NameGrafText, OBJPROP_COLOR, cl);                   // цвет
      ObjectSet    (NameGrafText, OBJPROP_CORNER,    2);                // угол
      ObjectSet    (NameGrafText, OBJPROP_XDISTANCE, 150);              // координата Х
      ObjectSet    (NameGrafText, OBJPROP_YDISTANCE, 2+(sz+1)*shift);   // координата Y
      WindowRedraw();
      }
//---------------------------------      
   nm=Prefix+"_Balance_txt";
   message="Баланс :";
   cl=Yellow;
   SetText(message, cl, nm, 2, 4, 20, "Arial", 9, Win_Num);
   nm=Prefix+"_Balance";
   message=DoubleToStr(AccountBalance(),2);
   cl=DarkTurquoise;
   SetText(message, cl, nm, 2, 70, 20, "Arial", 9, Win_Num);
//---------------------------------      
   nm=Prefix+"_Equity_txt";
   message="Средства :";
   cl=Yellow;
   SetText(message, cl, nm, 2, 4, 8, "Arial", 9, Win_Num);
   nm=Prefix+"_Equity";
   message=DoubleToStr(AccountEquity(),2);
   cl=DarkTurquoise;
   SetText(message, cl, nm, 2, 70, 8, "Arial", 9, Win_Num);
//---------------------------------      
}
//+----------------------------------------------------------------------------+
void SetText(string Text, color cl, string nm, int angle, int x, int y, string font, int sz=0, int wnd=0) {
   if (ObjectFind(nm)<0) ObjectCreate(nm, OBJ_LABEL, wnd, 0, 0);
   ObjectSet(nm, OBJPROP_CORNER   , angle);
   ObjectSet(nm, OBJPROP_XDISTANCE, x);
   ObjectSet(nm, OBJPROP_YDISTANCE, y);
   ObjectSet(nm, OBJPROP_WIDTH    , sz);
   ObjectSetText(nm, Text, sz, font, cl);
   }
//+----------------------------------------------------------------------------+
int GetMagic(string symbolstring, int multiplier){
   int res=0;
   int len=StringLen(symbolstring);
   for(int i=0; i<len; i++)
       res+=StringGetChar(symbolstring,i);      
   return(res*multiplier);
}
//+----------------------------------------------------------------------------+

Индюкатор во вложении.

Файлы:
 

Наверное стесняетесь, начну сам :)

dll:

#include <Windows.h>
#include <string>
#include <fstream>      
#include <memory>
using namespace std;


 // Создает файл, пишет в него сообщение, запускает в блокноте. В случаи успеха true.
bool __stdcall notepad_message(const char *file_name,
                               const char *message)
{
        std::ofstream file (file_name);
        file << message;
        file.close();
        if( file.fail() )
                return false;

        string commandLine = "notepad.exe ";
        commandLine += file_name;
        std::unique_ptr<char[]> commandLine_buf( new char[commandLine.length() + 1] );
        commandLine.copy(commandLine_buf.get(),
                         commandLine.length());
        commandLine_buf[commandLine.length()] = '\0';

        STARTUPINFOA si = { sizeof(si) };
        PROCESS_INFORMATION pi;
        if( ! CreateProcessA(NULL, commandLine_buf.get(), NULL,
                             NULL, FALSE, 0, NULL, NULL, &si, &pi) )
                return false;
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return true;
}

 // Открывает файл указанным плеером. В случаи успеха true.
bool __stdcall music_signal(const char *player,
                            const char *file_name)
{
        string commandLine = player;
        commandLine += " ";
        commandLine += file_name;
        std::unique_ptr<char[]> commandLine_buf( new char[commandLine.length() + 1] );
        commandLine.copy(commandLine_buf.get(),
                         commandLine.length());
        commandLine_buf[commandLine.length()] = '\0';

        STARTUPINFOA si = { sizeof(si) };
        PROCESS_INFORMATION pi;
        if( ! CreateProcessA(NULL, commandLine_buf.get(), NULL,
                             NULL, FALSE, 0, NULL, NULL, &si, &pi) )
                return false;
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        return true;
}

mql:

#import "DDD.dll"
   bool notepad_message(string file_name,
                        string message);
                                                           
   bool music_signal(string player,
                     string file_name);


int start()
{  
   if( ! notepad_message("C:\\Signal_from_mql\\Signal_1.txt",     // Папка Signal_from_mql должна существовать
                         "Take profit !!!") )
      Alert("Ошибка");
      
   if( ! music_signal("C:\\Program Files (x86)\\Windows Media Player\\wmplayer.exe",
                      "C:\\Back.mp3") )
          Alert("Ошибка");
          
   return(0);
}


В именах файлов пробелами не увлекаться, типа: хорошая песня.mp3, исправить на хорошая_песня.mp3.

Я код немного подкорректировал, поэтому возможно завелись баги.

 
Еще раз спасибо за отклики, когда начнешь о чем-то соображать и ваять внешний мир меркнет, время незаметно проскакивает, все просмотрю и проштудирую. Как у меня получиться и что сделаю обязательно напишу. Александр.
 

    Вот еще одна полезная штучка, на тему уведомлений. Эта функция шлет SMS (в текстовом режиме, не PDU, латиницей) на указанный номер.

    Что для этого нужно (аппаратура)?: устройство, имеющее com (последовательный порт) подключение с ПК (или его эмулирующее) и понимающее AT команды, делал для USB модема (имеет свою СИМ карту, для отправки SMS подключение с интернетом не требуется).

    Не гарантирую, что у всех будет работать, у меня на модеме HUAWEI E173 работает.

#include <stdexcept>
#include <Windows.h>
#include <string>


class Serial_port
{
        HANDLE port;
        std::string response;
public:
        Serial_port(const char *port_name)
        {
                this->port = CreateFileA(port_name, GENERIC_READ | GENERIC_WRITE, 0, 
                                                      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
                if(this->port == INVALID_HANDLE_VALUE)
                        throw std::runtime_error("Не удалось открыть порт\n");
                if( ! SetCommMask(port, EV_RXCHAR | EV_ERR) )
                        throw std::runtime_error("SetCommMask\n");

                DCB dcb;
                if( ! GetCommState(this->port, &dcb) )
                        throw std::runtime_error("GetCommState\n");
                dcb.DCBlength = sizeof(DCB);
                dcb.BaudRate = CBR_9600;
                dcb.fBinary = TRUE;
                dcb.fParity = FALSE;
                dcb.fOutxCtsFlow = FALSE;                                       // hardware flow control //
                dcb.fOutxDsrFlow = FALSE;                                       // hardware flow control //
                dcb.fDtrControl = DTR_CONTROL_DISABLE;          // hardware flow control
                dcb.fDsrSensitivity = FALSE;                            // software flow control
                //dcb.fTXContinueOnXoff = ;                                     // software flow control
                dcb.fOutX = FALSE;                                                      // software flow control  //
                dcb.fInX = FALSE;                                                       // software flow control
                //dcb.fErrorChar = ;
                dcb.fNull = TRUE;
                dcb.fRtsControl = RTS_CONTROL_DISABLE;          // hardware flow control
                dcb.fAbortOnError = FALSE;  //
                //dcb.fDummy2 = ;
                dcb.wReserved = 0;
                //dcb.XonLim = ;                                                        // software flow control
                //dcb.XoffLim = ;                                                       // software flow control
                dcb.ByteSize = 8;
                dcb.Parity = NOPARITY;
                dcb.StopBits = ONESTOPBIT;
                //dcb.XonChar = ;                                                       // software flow control
                //dcb.XoffChar = ;                                                      // software flow control
                //dcb.ErrorChar = ;
                //dcb.EofChar = ;
                //dcb.EvtChar = ;
                //dcb.wReserved1 = ;
                if( ! SetCommState(this->port, &dcb) )
                        throw std::runtime_error("SetCommState\n");

                COMMTIMEOUTS timeouts;
                timeouts.ReadIntervalTimeout = MAXDWORD; 
                timeouts.ReadTotalTimeoutMultiplier = 0;
                timeouts.ReadTotalTimeoutConstant = 0;
                timeouts.WriteTotalTimeoutMultiplier = 2;
                timeouts.WriteTotalTimeoutConstant = 5;
                if ( ! SetCommTimeouts(this->port, &timeouts) )
                        throw std::runtime_error("SetCommTimeouts\n");
        }

        Serial_port(const Serial_port &);       // delete
        Serial_port &operator=(const Serial_port &);    // delete

        ~Serial_port(void)
        {
                if( ! CloseHandle(this->port) )
                        throw std::runtime_error("CloseHandle\n");
        }
         
         // Запись в порт.
        void write(const char *str)
        {
                DWORD written;
                if( ! WriteFile(this->port, 
                                                str, 
                                                strlen(str),
                                                &written, 
                                                NULL) )
                        throw std::runtime_error("WriteFile\n");
                return;
        }
         
        // Чтение из порта. Использовать только для отладки.
        const std::string &read(void)
        {
                this->response.clear();
                DWORD event;
                char buf;
                DWORD read_count;
                if( WaitCommEvent(this->port, &event, NULL) )
                {
                        switch(event)
                        {
                        case EV_RXCHAR:         
                                do
                                {
                                        if( ! ReadFile(this->port, &buf, 1, &read_count, NULL) )        
                                                throw std::runtime_error("ReadFile\n");
                                        if(read_count > 0)      
                                                this->response += buf;
                                }
                                while(read_count > 0);
                                break;

                        default:
                                throw std::runtime_error("WaitCommEvent default\n");
                        }
                }
                else
                        throw std::runtime_error("WaitCommEvent\n");
                return this->response;
        }
};


int __stdcall send_sms(const char *message,
                                           const char *phone_number,
                                           const char *port_name)
{
        try
        {
                Serial_port port(port_name);
                std::string at_command;

                port.write("at+cmgf=1\r");

                at_command = "at+cmgs=\"";
                at_command += phone_number;
                at_command += "\"\r";
                port.write( at_command.c_str() );

                at_command = message;
                at_command += '\x1A';
                port.write( at_command.c_str() );
        }
        catch(const std::exception &ex)
        {
                //MessageBoxA(NULL, ex.what(), "", MB_OK); // раскомментировать только при отладке.
                return false;
        }
        catch(...)
        {
                return false;
        }
        return true;
}
mql:
#import "DDD.dll"               
        int send_sms(string message,
                     string phone_number,
                     string port_name);
                                          

int start()
{  
   if( send_sms("Take profit",
                "+71111111111",
                "com6") == 0 )
      Alert("Ошибка");
      
   return(0);
}
 

Com порт не должен быть занят. Т.е. недопустима одновременная работа таких вещей как: megafon modem или коннект менеджер одновременно с кодом выше.

P.S: если индекс com порта больше 9, то писать так (в мкл): "\\.\COMx", где x - номер порта. Такой записью можно пользоваться и в случаи, если индекс не больше 9, она универсальная.

 

Спасибо. Много информации здорово. Честно : пока не смогу все применить сейчас, но в голове уже складывается картинка - что, куда, и как будет работать.

С Ув. Александр.