risk-position-tool/mql5/Include/ChartKit/CkObj.mqh
103 lines
3.5 KiB
MQL5
//+------------------------------------------------------------------+
//| CkObj.mqh |
//| Copyright 2026, Allan Niñal |
//| https://www.allanninal.dev/mql5 |
//+------------------------------------------------------------------+
//| Chart kit object helpers: create once (hidden from the object |
//| list, not selectable), then set a property only when its value |
//| changed, so a redraw with nothing new sends nothing. Every name |
//| carries the product's own prefix; CkDeleteAll(prefix) cleans up. |
//| g_ck_dirty turns true when something was sent: call ChartRedraw |
//| once per handler, not per object. |
//+------------------------------------------------------------------+
#ifndef CK_OBJ_MQH
#define CK_OBJ_MQH
bool g_ck_dirty=false;
//--- the non-visual Strategy Tester has no chart to draw on
bool CkCanDraw(void) { return(!(MQLInfoInteger(MQL_TESTER) && !MQLInfoInteger(MQL_VISUAL_MODE))); }
bool CkEnsure(const string name,const ENUM_OBJECT type)
{
if(ObjectFind(0,name)>=0)
return(true);
if(!ObjectCreate(0,name,type,0,0,0))
return(false);
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
g_ck_dirty=true;
return(true);
}
void CkSetI(const string name,const ENUM_OBJECT_PROPERTY_INTEGER p,const long v,const int mod=0)
{
if(ObjectGetInteger(0,name,p,mod)!=v)
{
ObjectSetInteger(0,name,p,mod,v);
g_ck_dirty=true;
}
}
void CkSetD(const string name,const ENUM_OBJECT_PROPERTY_DOUBLE p,const double v,const int mod=0)
{
if(MathAbs(ObjectGetDouble(0,name,p,mod)-v)>1e-12)
{
ObjectSetDouble(0,name,p,mod,v);
g_ck_dirty=true;
}
}
void CkSetS(const string name,const ENUM_OBJECT_PROPERTY_STRING p,const string v)
{
if(ObjectGetString(0,name,p)!=v)
{
ObjectSetString(0,name,p,v);
g_ck_dirty=true;
}
}
//--- a filled rectangle behind the candles (time t1..t2, price p1..p2)
void CkRect(const string name,const datetime t1,const double p1,const datetime t2,const double p2,const color fill,const string tip="")
{
if(!CkEnsure(name,OBJ_RECTANGLE))
return;
CkSetI(name,OBJPROP_BACK,1);
CkSetI(name,OBJPROP_FILL,1);
CkSetI(name,OBJPROP_COLOR,fill);
CkSetI(name,OBJPROP_TIME,t1,0);
CkSetD(name,OBJPROP_PRICE,p1,0);
CkSetI(name,OBJPROP_TIME,t2,1);
CkSetD(name,OBJPROP_PRICE,p2,1);
CkSetS(name,OBJPROP_TOOLTIP,tip=="" ? "\n" : tip);
}
//--- a text anchored at a time and price
void CkText(const string name,const datetime t,const double p,const string text,const color clr,const ENUM_ANCHOR_POINT anchor,
const int size=8,const string font="Segoe UI Semibold",const string tip="")
{
if(!CkEnsure(name,OBJ_TEXT))
return;
CkSetI(name,OBJPROP_BACK,0);
CkSetI(name,OBJPROP_ANCHOR,anchor);
CkSetI(name,OBJPROP_FONTSIZE,size);
CkSetS(name,OBJPROP_FONT,font);
CkSetI(name,OBJPROP_COLOR,clr);
CkSetI(name,OBJPROP_TIME,t,0);
CkSetD(name,OBJPROP_PRICE,p,0);
CkSetS(name,OBJPROP_TEXT,text=="" ? " " : text);
CkSetS(name,OBJPROP_TOOLTIP,tip=="" ? "\n" : tip);
}
void CkDelete(const string name)
{
if(ObjectFind(0,name)>=0 && ObjectDelete(0,name))
g_ck_dirty=true;
}
void CkDeleteAll(const string prefix)
{
if(ObjectsDeleteAll(0,prefix)>0)
g_ck_dirty=true;
}
#endif
//+------------------------------------------------------------------+