Re: Indicators with ON/OFF buttons

2163
Banzai wrote: Mon May 30, 2022 1:23 am Help! I copy the code exactly like yours but it doesn't work properly.
I turn off the button. But each time I change the timeframe, the button still stays on and displays the graph.
Image
I don't promise to help with every such request (and to be honest, I don't usually monitor this website that often), but I'm willing to support your initiative to implement an on/off button using my example.

My code determines the on/off status from the actual button object. When changing timeframes, the OnDeinit section determines whether to delete objects or not, and for the buttonId, it will be deleted UNLESS the reason is just "REASON_CHARTCHANGE", which is what occurs when you just change the TF of the chart. The code:

Code: Select all

void OnDeinit(const int reason) 
{
   ObjectsDeleteAll(0, IndicatorObjPrefix);

   // If just changing a TF', the button need not be deleted, therefore the 'OBJPROP_STATE' is also preserved.
   if(reason != REASON_CHARTCHANGE) ObjectDelete(buttonId);
}
So, the problem in your code is that the buttonId object is getting deleted every time, by the FIRST line, "ObjectsDeleteAll(0, IndicatorObjPrefix);"

Why is this happening? It is because your "buttonId" does not have unique *prefix*, compared to the other created objects.

In my example code, my buttonId is defined with this line:
buttonId = "_" + IndicatorObjPrefix + "button_"; // P4L: Deliberately distinguished from other objects so the *button* can be kept (in OnDeinit) when changing TF's.

Your implementation is:
buttonId = IndicatorObjPrefix + UniqueButtonID + "_BT_";

The problem is that the *prefix* of the button object is not unique! I could have been more clear with my comment that I wasn't only making the name unique, but the *prefix* was unique.

To fix your code, you only need to change the buttonId prefix, which would be as simple as pre-pending a "_" to the name.

The fix:
buttonId = "_" + IndicatorObjPrefix + UniqueButtonID + "_BT_";

Your use of "UniqueButtonID" is ok, but likely not necessary so long as the following is true:
When you add >=2 of THIS indicator to a chart, do you ever use the SAME sub-window to display the lines? If yet, you need some unique_id. If no, an easier solution is to use "swin" as a unique id, where "swin = ChartWindowFind()"

You also happen to display the button in the main window, regardless of which sub-window is the indicator using. This is fine if you want. However, if you prefer to use the same sub-window for the button, then I've enhanced "btn_Subwindow" to support a NEGATIVE number to mean use the "swin" variable instead.

Once the button is working, then the next big problem in your code is that when going from OFF-to-ON, you must override the normal "counted_bars" value, to force it to redraw the lines. I added a "recalc" variable for this purpose.

One other nice-to-have feature is to auto-size the height of your sub-window. HOWEVER, the feature is somewhat hindered by MT4 bugs that may limit how well you can control/stretch the sub-window height, IF this feature is enabled.

Therefore, I added "Auto_Adjust_Window_Height" and set the default to "false". I also added a 2nd variable "Default_Active_Window_Height" (250), that can be any reasonable value you want.

You can experiment with that, and you may find the MT4 bugs acceptable, or you might prefer to skip it and just manually set the sub-window height like you do today.

Good luck.
These users thanked the author pips4life for the post (total 6):
Banzai, josi, kvak, BeatlemaniaSA, pipsquirrel, RodrigoRT7




Who is online

Users browsing this forum: ChatGPT [Bot], CrisBarbedo, IBM oBot [Bot], Jonex1995, levchuk, Steam1 and 70 guests