Common crappy implementation of on/off button for indys can cause MT4 hangs, slow system. Better way??

 

I notice a lot of requests by non-programmers for others to 'please implement an on/off button' in various indicators.  This is actually a nice handy feature to have.  Unfortunately there is a *terrible* template someone(?) is using to implement the on/off button that is, at best, slow and inefficient, and at worst, may HANG MT4 depending upon what *other* indicators exist on the same chart!!  Somebody who doesn't understand programming, and certainly the OnChartEvent() section, is writing some very bad code, and proliferating it all over the place.


I'll attach one such example (tagged as "BAD"), along with my "P4L:" comments with the reason why I think it's crappy code.

Then I've attached an improved version of the same (tagged as "BETTER") with a simpler implementation that accomplishes the same on/off button, but is more efficient and does not HANG MT4 (afaik).

Q: Please take a look at my "BETTER" version, then... do you have any further suggestions how to improve it?

Q: Specifically, note that "OnChartEvent() ... directly calls 'start()'.   Since an incoming tick will also call start(), might this cause any conflict or problem?  Or will the tick (or event) just be ignored until the 'start()' section is finished running.  Would it be better to rename it to 'mystart()', and then define 'int start() { return( mystart() ); }', and have the OnChartEvent now call 'mystart()' instead of 'start()'  ?   Is there any difference, or not?


===  There is an MT4 bug, either in the WindowFind function, or in the documentation for it, because it doesn't work as described ===

To avoid this bug, in my "BETTER" version, I've used the common "unique_id" variable that a user must manually set *if* they want to add >=2 of the same indy to a chart.

In the "BAD" version, there is function 'GenerateIndicatorName' that is supposed to create a unique name when >=2 have been added, BUT it doesn't work!  It relies upon the 'WindowFind' function.

// P4L: The routine below is called by OnInit.  The doc says when an indy calls itself using WindowFind, it should return "-1", but in fact, it will return "0" (if the indy is in the main window 0).  MT4 bug??
// This routine is an *attempt* to create a unique object prefix for EACH instance of the indicator, so that more than one can be used simultaneously on a chart, but it doesn't work right. 
string GenerateIndicatorName(const string target) 
{
   string name = target;
   int try = 2;
   while (WindowFind(name) != -1)
   {
      name = target + " #" + IntegerToString(try++);
   }
   return name;
}

In the documentation for WindowFind, it says: 

Returned value

If indicator with name was found, the function returns the window index containing this specified indicator, otherwise it returns -1.

Note

WindowFind() returns -1 if custom indicator searches itself when init() function works.


Either MT4 WindowFind function has a bug, or this documentation is the bug, because when run by init() (or "OnInit()"), when searching for itself, it is NOT returning "-1" as it says, but is instead returning "0"  ("0" for the main window).   

The custom 'GenerateIndicatorName' function is counting on this "-1" return to occur when the indy searches for itself, but it's not working. 

Note: You can test the "BETTER" version, but in the code, enable "debug=true", then you will see the output when testing the WindowFind function.  It never returns "-1" as is documented.

Q:  Is there any better working alternative??  It seems rather silly to still rely upon a manually-user-set "unique_id" method JUST to support >=2 instances of the same indy.   I want a better, automatic method that works.


===   The "BAD" version can HANG MT4**, depending on what *other* indicators are being run by the same chart!!

** The "HANG" condition might be just that, or might instead be something that will take many minutes to resolve.   It might return control, but given how extremely slow it is, it's a big problem to wait and is easier to just kill MT4.


Fyi, I've discussed this problem in an FF post here.  That post was a hang caused by a specific .ex4, but a very similar hang occurs using this code as well.  

It can be easily replicated with the attached files.

Start with a *completely* blank chart.  Your "default.tpl" must NOT have any other indicators in it by default. 

Add to it my 'enable_chart_event_object_DELETE_CREATE'  indicator, which does nothing but enable two types of chart events.  It turns out that this 1 indicator turning on these events will affect ALL other indicators on the same chart!!

Next, add the "CustomCandles - any tmf v1 BT BAD" indicator.   The candles should be enabled by default.   CHANGE the chart timeframe.  You might possibly have to toggle the on/off button, AND change the chart TF a few times, but fairly soon, it will HANG MT4!


You won't be able to replicate the HANG problem using the "BETTER" version, because it works just fine.  I think the most likely "fix" was the big improvement to the OnChartEvent code that now runs either "start()" or "deinit2()" just ONE time only for each button click.

However, in addition to that, in OnChartEvent I also capture and return (early) for some of the events that my code doesn't need to process.   e.g.

   if(id==CHARTEVENT_OBJECT_CREATE || id==CHARTEVENT_OBJECT_DELETE) return; // This appears to make this indy compatible with other programs that enabled CHART_EVENT_OBJECT_CREATE and/or CHART_EVENT_OBJECT_DELETE

   if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_MOUSE_WHEEL) return; // If this, or another program, enabled mouse-events, these are not needed below, so skip it unless actually needed.


In summary:

I'm open to suggestions to improve my "BETTER" version, for how to best implement a simple on/off button for this and similar indicators.

I welcome comments on whether the OnChartEvent can safely call "start()", as it currently does, or should it call some other function name, to avoid conflicts with incoming ticks, etc.

I welcome any better method to automatically detect whenever >=2 of the same indicator have been added to the same chart.   I prefer to avoid using "unique_id" if at all possible.

I mentioned how *other* indicators that enable various chart events will affect each other if added to the same chart; therefore, proper handling of id events is essential, otherwise hangs or slowness may occur.



 
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.
 
Banzai Fx #:
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.

I saw your similar post you made on forex-station and wrote my reply there with my reasons for the code fixes I made to your source.

The same fixed source is posted here.

Reason: