Toggle (Flush/Redraw) an indicator buffer with keystroke event

 

Hi guys, 

I am trying to figure out how to flush out, or 'reset' indicator buffers on a keystroke event.

Here is what I have so far

 

void OnChartEvent(const int id,         // Event identifier  
                  const long& lparam,   // Event parameter of long type
                  const double& dparam, // Event parameter of double type
                  const string& sparam) // Event parameter of string type
                  
  {
      if(id==CHARTEVENT_KEYDOWN) {
         
         //Inside Day Toggle
         if (lparam == 73) {
            if(detect_inside_candles) { 
               detect_inside_candles = false; //external bool
               
               //flush out buffers
               ArrayInitialize(Buffer0, 0);
               ArrayInitialize(Buffer1, 0);
               ChartRedraw(ChartID());               
            }
            
            else if(!detect_inside_candles) { 
               detect_inside_candles = true; //external bool
               ChartRedraw(ChartID());
               
            }
         }// "i" key pressed
         
        
      }

 

What happens is the first keystoke does clear the buffers and the indicator from the screen, but the second keystroke doesn't work.

Is it possible to clear the  prev_calculated variable inside OnCalculate()... it's set as a constant so I don't know how that would work.

Can anyone suggest any other approach here. 

 

Move your calculations for the buffers into a separate function with a parameter for the amount of bars to calculate

Call the function from OnCalculate (if detect_inside_candles is true)to calculate on new bars only

Call the function from your if in OnChartEvent to calculate on all bars 
 

I think I understand what you're saying.

I am using the histograms to mark a line down the middle of the inside candles. What I want to do is flush out the buffers and remove all markings from the chart  - which I have achieved.

But when the keystroke 'i' turns the switch back on again - I need the indicator to go back through the entire buffer again and re-do it.

What you're saying is to use a custom variable, instead of the prev_calculated to make the code run back through all candles again?

 

Basically, yes.

You may have something like

   int limit=rates_total-prev_calculated
   //Code that loops through and fills buffers

 in OnCalculate

Instead, move your main code into a function

void MainCodeFunction(limit)
   { 
   //Code that loops through and fills buffers
   }  

 Then in OnCalculate

   int limit=rates_total-prev_calculated
   MainCodeFunction(limit);

 You pass limit to the function

 

Then in your OnChartEvent

            else if(!detect_inside_candles) { 
               detect_inside_candles = true; //external bool
               MainCodeFunction(Bars-1);
               ChartRedraw(ChartID());
                

 You can pass Bars-1 or whatever is suitable to the function to redraw all the buffers you need

 

Thanks for your help. I've got it working, I did a crude work around so I didn't have to heavily modify the code.

 

I Set a global variable 

bool redraw_buffers = false;

 

Flag it to true when the chart needs updating. I also added the RefreshRates() function, hoping that it will call onCalculate

//Inside Day Toggle
         if (lparam == 73) {
            if(detect_inside_candles) { 
               detect_inside_candles = false;
               
               //flush out buffers
               ArrayInitialize(Buffer0, 0);
               ArrayInitialize(Buffer1, 0);
               
               ChartRedraw(ChartID());               
            }
            
            else if(!detect_inside_candles) { 
               redraw_buffers = true;
               detect_inside_candles = true;               
               RefreshRates(); //try to get onCalculate to run on keystroke   
               ChartRedraw(ChartID());
               
            }
         }// "i" key pressed

 

Then before the indicator loop, I took some of your advice and reset the bar counter...

int OnCalculate( ....
int limit, i;
   int counted_bars = prev_calculated;
   
   //---
   if(counted_bars<0) return(-1);
   //----
   if(counted_bars>0) counted_bars--;
   //----
   if(counted_bars==0) counted_bars=1;
   
   if(redraw_buffers) {
      limit=Bars-1;
      redraw_buffers = false;
   }
   else { limit=rates_total-counted_bars; }
   
    
   for(i=limit-1; i>=0; i--) {   

 

Now it works as intended, however - the indicator will still need a new tick to refresh the chart.

I was hoping that refresh rates function would get onCalculate to run again.

Is there anyway to call onCalculate within the onEvent function...

 

         if (lparam == 73) {
           // 
            else if(!detect_inside_candles) { 
               redraw_buffers = true;
               detect_inside_candles = true;               
               RefreshRates(); //try to get onCalculate to run on keystroke   
               ChartRedraw(ChartID());

               onCalculate() //how will pass all the parameters to get this to work?
            }
         }// "i" key pressed

 

If I can get onCalculate to be called on the keystroke that would be great. A any solution without having to modify the code to heavily would be fantastic (y).

Thank you so much. 

 

With my suggestion, the buffers will be re-calculated without waiting for a tick.

Why would there be any need for heavy modification?

It's a simple matter to move your main code from OnCalculate into a new function, just cut and paste. 

 

Ok, help me understand the logic here. 

If I just renamed the onCalculate function to scanCandles()

Then I called scanCandles from within onCalculate and onChartEvent

Why can't I just call onCalculate from within onChartEvent? 

 
dazamate:

Ok, help me understand the logic here. 

If I just renamed the onCalculate function to scanCandles()

Then I called scanCandles from within onCalculate and onChartEvent

Why can't I just call onCalculate from within onChartEvent? 

 

Try it and see what happens.

I've never tried it 

 

It worked,

I had to make two dummy arrays to pass as the Tick_volume and Spread parameter as I don't know what global variables are normally passed to onCalculate internally.

 

Thanks very much for your help. 

 
#import "user32.dll"
   int   RegisterWindowMessageA(string lpstring);
   int   PostMessageA(int  hWnd,int  Msg,int  wParam,string lParam);
#import

//--- replace with your functions

if(true)
{
 PostMessageA (WindowHandle (_Symbol, _Period), 0x0111, 33324, 0);
 PostMessageA (WindowHandle (_Symbol, 0), RegisterWindowMessageA ("MetaTrader4_Internal_Message"), 2, 1);
}
Here you go.
 
dazamate:Is it possible to clear the  prev_calculated variable inside OnCalculate()...
  1. Right click → Refresh
  2. It's unnecessary; fix your broken indicator.
Reason: