//+------------------------------------------------------------------+ //| Comment.mqh | //| avoitenko | //| https://login.mql5.com/en/users/avoitenko | //+------------------------------------------------------------------+ #property copyright "avoitenko" #property link "https://login.mql5.com/en/users/avoitenko" #property version "1.00" #property strict #include #include //--- #define EVENT_NO_EVENTS 0 #define EVENT_MOVE 1 #define EVENT_CHANGE 2 //+------------------------------------------------------------------+ //| TComment | //+------------------------------------------------------------------+ class TComment : public CObject { public: string text; color colour; }; //+------------------------------------------------------------------+ //| CComment | //+------------------------------------------------------------------+ class CComment { private: bool m_is_collapse; CPoint m_temp; CCanvas m_comment; CPoint m_pos; CList m_list; CSize m_size; //--- string m_name; string m_font_name; int m_font_size; bool m_font_bold; double m_font_interval; color m_border_color; color m_back_color; uchar m_back_alpha; bool m_graph_mode; bool m_auto_colors; color m_auto_back_color; color m_auto_text_color; color m_auto_border_color; color m_chart_back_color; //+------------------------------------------------------------------+ color Color2Gray(const color value) { int gray=(int)round(0.3*GETRGBR(value)+0.59*GETRGBG(value)+0.11*GETRGBB(value)); if(gray>255) gray=255; return((color)ARGB(0,gray,gray,gray)); } //+------------------------------------------------------------------+ uchar GrayChannel(const color value) { int gray=(int)round(0.3*GETRGBR(value)+0.59*GETRGBG(value)+0.11*GETRGBB(value)); if(gray>255) gray=255; return((uchar)gray); } //+------------------------------------------------------------------+ color Bright(const color value,const int percent) { int r,g,b; //--- r=GETRGBR(value); g=GETRGBG(value); b=GETRGBB(value); //--- if(percent>=0) { r+=(255-r)*percent/100; if(r>255) r=255; //--- g+=(255-g)*percent/100; if(g>255) g=255; //--- b+=(255-b)*percent/100; if(b>255) b=255; } else { r+=r*percent/100; if(r<0) r=0; //--- g+=g*percent/100; if(g<0) g=0; //--- b+=b*percent/100; if(b<0) b=0; } //--- return(ARGB(0,r,g,b)); } //+------------------------------------------------------------------+ void CalcColors() { m_auto_back_color=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND); color m_back_gray=Color2Gray(m_auto_back_color); uchar channel=GrayChannel(m_back_gray); //--- if(channel>120) { if(m_back_color==clrNONE) m_auto_border_color=clrNONE; else m_auto_border_color=Bright(m_back_gray,-30); //--- m_auto_text_color=Bright(m_back_gray,-80); } else { if(m_back_color==clrNONE) m_auto_border_color=clrNONE; else m_auto_border_color=Bright(m_back_gray,30); //--- m_auto_text_color=Bright(m_back_gray,80); } } public: //+------------------------------------------------------------------+ void CComment(void) { m_name=NULL; m_font_name="Lucida Console"; m_font_size=14; m_font_bold=false; m_font_interval=1.7; m_border_color=clrNONE; m_back_color=clrNONE; m_back_alpha=10; m_graph_mode=true; m_auto_colors=false; m_chart_back_color=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND); m_auto_back_color=clrBlack; m_auto_border_color=clrNONE; //--- ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true); }; //+------------------------------------------------------------------+ void Create(const string name,const uint x,const uint y) { m_name=name; m_pos.x=(int)x; m_pos.y=(int)y; }; //+------------------------------------------------------------------+ void Move(const uint x,const uint y) { m_pos.x=(int)x; m_pos.y=(int)y; }; //+------------------------------------------------------------------+ void SetAutoColors(const bool value) { m_auto_colors=value; if(value) CalcColors(); } //+------------------------------------------------------------------+ void SetGraphMode(const bool value) { m_graph_mode=value; }; //+------------------------------------------------------------------+ void SetText(const int row,const string text,const color colour) { if(row<0) return; //--- int total=m_list.Total(); //--- if(row=pan.x && p.x=pan.y && p.y=pan.x && p.x=pan.y && p.y=0 && m_temp.y>=0) { int new_x=p.x-m_temp.x; if(new_x>screen.cx-psize.cx) new_x=screen.cx-psize.cx; if(new_x<0) new_x=0; //--- int new_y=p.y-m_temp.y; if(new_y>screen.cy-psize.cy) new_y=screen.cy-psize.cy; if(new_y<0) new_y=0; //--- ObjectSetInteger(0,m_name,OBJPROP_XDISTANCE,new_x); ObjectSetInteger(0,m_name,OBJPROP_YDISTANCE,new_y); ChartSetInteger(0,CHART_MOUSE_SCROLL,false); #ifdef __MQL5__ ChartRedraw(); #endif return(EVENT_MOVE); } } else { m_temp.x=-1; m_temp.y=-1; ChartSetInteger(0,CHART_MOUSE_SCROLL,true); } } //--- if(m_auto_colors && id==CHARTEVENT_CHART_CHANGE) { //--- changing background color event if(m_chart_back_color!=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND)) { CalcColors(); m_chart_back_color=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND); return(EVENT_CHANGE); } } //--- if(id==CHARTEVENT_CLICK) { //beginning of: detection of a doubleclick static ulong ClickTimeMemory ; //static is crucial to remember ClickTimeMemory's content next time OnChartEvent() is called ulong ClickTime = GetTickCount() ; //GetTickCount() uses milliseconds - it's not necessary to use GetMicrosecondCount() if(ClickTime > ClickTimeMemory && ClickTime < ClickTimeMemory + 300) //the second click should appear within 300 milliseconds after the first click. That's 0.3 seconds - that's about the typical delay of the second click relative to the first click when making a doubleclick { //--- panel size CSize psize; psize.cx=(int)ObjectGetInteger(0,m_name,OBJPROP_XSIZE); psize.cy=(int)ObjectGetInteger(0,m_name,OBJPROP_YSIZE); //--- panel position CPoint pan; pan.x=(int)ObjectGetInteger(0,m_name,OBJPROP_XDISTANCE); pan.y=(int)ObjectGetInteger(0,m_name,OBJPROP_YDISTANCE); if(p.x>=pan.x && p.x=pan.y && p.ymax_width) max_width=width; } max_width+=text_height; //--- create panel if(ObjectFind(0,m_name)==-1) { //m_comment.CreateBitmapLabel(0,0,m_name,m_pos.x,m_pos.y,max_width,max_height,COLOR_FORMAT_ARGB_NORMALIZE); m_comment.CreateBitmapLabel(0,0,m_name,m_pos.x,m_pos.y,max_width,max_height,COLOR_FORMAT_ARGB_RAW); } else { //--- resize panel if(m_comment.Height()!=max_height || m_comment.Width()!=max_width) { if(!m_comment.Resize(max_width,max_height)) { ObjectDelete(0,m_name); ChartRedraw(); } } } //--- m_comment.Erase(ColorToARGB(m_auto_colors?m_auto_back_color:m_back_color,m_back_alpha)); m_comment.Rectangle(0,0,max_width-1,max_height-1,ColorToARGB(m_auto_colors?m_auto_border_color:m_border_color)); //--- int h=(int)round(text_height/2); for(int i=0; i