Handling actions of SpinEdit object on a Dialog with OnChartEvent method

 

Hi,

I try to use a button and a spinedit on a control panel (Dialog).

When the following code line in OnChartEvent() function is commented out, the button works, but not the spin edit.

On the other hand, when it is commented in, the button does not work, but the spin edit.


cpInterface.OnEvent(id, lparam, dparam, sparam);


How can I correctly handle actions ?

Thanks in advance for any help.


//+------------------------------------------------------------------+
//|                                                          Tmp.mq4 |
//|                                                    fxbender 2021 |
//|                                           https://www.google.com |
//+------------------------------------------------------------------+
#property copyright "Fxbender 2021"
#property link      "https://www.google.com"
#property version   "1.00"
#property strict


#include <Controls/Dialog.mqh>

#include <Controls/Button.mqh>
#include <Controls/SpinEdit.mqh>

#include <stdlib.mqh>
#include <WinUser32.mqh> 

CAppDialog cpInterface;

CButton btn_test1;
const string btnID_test1="ButtonTest1";

CSpinEdit input_test2;
const string inputID_test2="InputTest2";

static int a_x = int(ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0)-10);  

int OnInit()
{
   const int   sub_window  = 0;           // subwindow index
   int         x           = 10;          // X coordinate
   int         y           = 10;          // Y coordinate
   int         width       = 50;          // object width
   int         height      = 20;          // object height
   const int   space       = 3;           // space between objects
   int         left=0,top=0,right=0,bottom=0;

   cpInterface.Create(0, "Tmp", 0, 200, 0, 200 + width*10, 0 + height*6);
   
   left = x + (width + space) * 2.5; top = y; right = left + width * 3; bottom = top + height;
   btn_test1.Create(0, btnID_test1, sub_window, left, top, right, bottom);
   btn_test1.Text("Test");
   btn_test1.FontSize(9);
   btn_test1.Color(clrWhite);
   btn_test1.ColorBackground(clrRed);
   btn_test1.ColorBorder(clrBlack);
   cpInterface.Add(btn_test1);
   
   left = x + width * 0.5; top = y * 4; right = left + width; bottom = top + height;
   input_test2.Create(0, inputID_test2, sub_window, left, top, right, bottom);
   input_test2.MinValue(-100);
   input_test2.MaxValue(100);
   input_test2.Value(1);
   cpInterface.Add(input_test2);
   
   cpInterface.Run();
   
   return(INIT_SUCCEEDED);
   
}


void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   
   //When this line is commented out, the button works, but not the spin edit
   //When this line is commented, the button does not work, but the spin edit
   cpInterface.OnEvent(id, lparam, dparam, sparam);
   
   if(id==CHARTEVENT_OBJECT_CLICK)
   {
      string clickedChartObjectID = sparam;
      
      if(clickedChartObjectID == btnID_test1)
      {
         // State of the button - pressed or not
         bool selected = ObjectGetInteger(0, btnID_test1, OBJPROP_STATE);
         Print("Test Button pressed = ", selected);
         string message;    
         
         // If the button is pressed
         if(selected)
         {
            message = "Test Activated";
            
            ObjectSetInteger(0, btnID_test1, OBJPROP_BGCOLOR, clrGreen);
            
         }        
         else // Button is not pressed
         {
            message="Test Deactivated";
            
            ObjectSetInteger(0, btnID_test1, OBJPROP_BGCOLOR, clrRed);
            
         }
         Print(message);
         
      } 
      
      ChartRedraw();      
   } 
}

void OnDeinit(const int reason)
{
   cpInterface.Destroy(reason);
}
 
fxforces:

Hi,

I try to use a button and a spinedit on a control panel (Dialog).

When the following code line in OnChartEvent() function is commented out, the button works, but not the spin edit.

On the other hand, when it is commented in, the button does not work, but the spin edit.

How can I correctly handle actions ?

Thanks in advance for any help.

The normal way to use a button is to perform some actions when it is clicked. Not to toggle it's state (for that, we use checkboxes).

As for spinedit, it's behavior when you call OnEvent() is expected. You call input_test2.Value() only when you need it's value.


So the behavior of both controls with OnEvent() call is expected, there is nothing wrong. 

 
Seng Joo Thio:

The normal way to use a button is to perform some actions when it is clicked. Not to toggle it's state (for that, we use checkboxes).

Thank you for your explanation. However in order to simplify the question, I just removed the business logic, (as you see the button is called as test).


Seng Joo Thio:


So the behavior of both controls with OnEvent() call is expected, there is nothing wrong. 

Actually, the first post explains what is the wrong pretty good.

If the code is executed, the wrong is easily observed.

Just try to click the button, it will not work.

Then comment out the mentioned line, execute code, at this time spinedit does not work.

Thank you.

 
fxforces:

Thank you for your explanation. However in order to simplify the question, I just removed the business logic, (as you see the button is called as test).

Actually, the first post explains what is the wrong pretty good.

If the code is executed, the wrong is easily observed.

Just try to click the button, it will not work.

Then comment out the mentioned line, execute code, at this time spinedit does not work.

Thank you.

Of course it won't work, because it wasn't designed to work that way - read my first reply again.

 

Here's what you could do if you want to use CButton as a toggle:

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   cpInterface.OnEvent(id, lparam, dparam, sparam);

   if (btn_test1.Pressed())
   {
      switch (btn_test1.ColorBackground())
      {
         case (clrGreen):
         {
            Print ("Color is Green, Spin Edit Value = ", input_test2.Value());
            btn_test1.ColorBackground(clrRed);
            break;
         }
         default:
         {
            Print ("Color is Red, do nothing");
            btn_test1.ColorBackground(clrGreen);
            break;
         }
      }
   }
}

 
Seng Joo Thio:

Here's what you could do if you want to use CButton as a toggle:

Thank you very much.

I was previously doing just like that.

The control mechanism in here is based on the background color which is not the intended way.

In other words, when I realized that the CButton class has a state() function, I wanted to utilize it.

From the definition of state() function , I understand that when I press the button it is state is changed to pressed.

When I again press it , the state is changed to unpressed.

I also confirmed this behavior with the following code.

Note: I do not want to use checkbox or radio button here.

//+------------------------------------------------------------------+
//|                                                          Tmp.mq4 |
//|                                                    fxbender 2021 |
//|                                           https://www.google.com |
//+------------------------------------------------------------------+
#property copyright "Fxbender 2021"
#property link      "https://www.google.com"
#property version   "1.00"
#property strict


#include <Controls/Dialog.mqh>

#include <Controls/Button.mqh>
#include <Controls/SpinEdit.mqh>

#include <stdlib.mqh>
#include <WinUser32.mqh> 

CAppDialog cpInterface;

CButton btn_test1;
const string btnID_test1="ButtonTest1";

CSpinEdit input_test2;
const string inputID_test2="InputTest2";

static int a_x = int(ChartGetInteger(0,CHART_WIDTH_IN_PIXELS,0)-10);  

int OnInit()
{
   const int   sub_window  = 0;           // subwindow index
   int         x           = 10;          // X coordinate
   int         y           = 10;          // Y coordinate
   int         width       = 50;          // object width
   int         height      = 20;          // object height
   const int   space       = 3;           // space between objects
   int         left=0,top=0,right=0,bottom=0;

   left = x + (width + space) * 2.5; top = y; right = left + width * 3; bottom = top + height;
   btn_test1.Create(0, btnID_test1, sub_window, left, top, right, bottom);
   btn_test1.Text("Test");
   btn_test1.FontSize(9);
   btn_test1.Color(clrWhite);
   btn_test1.ColorBackground(clrRed);
   btn_test1.ColorBorder(clrBlack);
  
   return(INIT_SUCCEEDED);
   
}


void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   
   if(id==CHARTEVENT_OBJECT_CLICK)
   {
      string clickedChartObjectID = sparam;
      
      if(clickedChartObjectID == btnID_test1)
      {
         // State of the button - pressed or not
         bool selected = ObjectGetInteger(0, btnID_test1, OBJPROP_STATE);
         Print("Test Button pressed = ", selected);
         string message;    
         
         // If the button is pressed
         if(selected)
         {
            message = "Test Activated";
            
            ObjectSetInteger(0, btnID_test1, OBJPROP_BGCOLOR, clrGreen);
            
         }        
         else // Button is not pressed
         {
            message="Test Deactivated";
            
            ObjectSetInteger(0, btnID_test1, OBJPROP_BGCOLOR, clrRed);
            
         }
         Print(message);
         
      } 
      
      ChartRedraw();      
  }
   
}


void OnDeinit(const int reason)
{
   cpInterface.Destroy(reason);
}

When I use it within a Dialog control panel, it does not work.

 
fxforces:

Thank you very much.

I was previously doing just like that.

The control mechanism in here is based on the background color which is not the intended way.

In other words, when I realized that the CButton class has a state() function, I wanted to utilize it.

From the definition of state() function , I understand that when I press the button it is state is changed to pressed.

When I again press it , the state is changed to unpressed.

I also confirmed this behavior with the following code.

Note: I do not want to use checkbox or radio button here.

When I use it within a Dialog control panel, it does not work.

Don't use background color then. I used that just for convenience...

   cpInterface.OnEvent(id, lparam, dparam, sparam);

   static bool btn_selected = false;
   if (btn_test1.Pressed())
   {
      if (btn_selected)
      {
         btn_test1.ColorBackground(clrGreen);
         Print ("Color is Green, do nothing");
         btn_selected = false;
      }
      else
      {
         btn_test1.ColorBackground(clrRed);
         Print ("Color is Red, Spin Edit Value = ", input_test2.Value());
         btn_selected = true;
      }
   }

You need to decide whether to use OBJ_BUTTON of MQL4 (where OBJPROP_STATE plays a role), or switch to the CButton of MQL5 and make use of Pressed(), and work around it (use your own bool state) so that it serves as a toggle (which isn't it's intended role) rather than on per-click basis.

 

Thank you very much for the fast response.

I understand from the latest response that the MQL$ state() function does not behave as the same when not using Dialog panel.

Although I do not have the reasoning about that yet, I will follow your advise and design a circumventing logic. 


Actually MQL4 is relatively simple than, that's why I tend to use this notion.

However I only want to leverage object oriented programming style when I create GUI elements. 

Since assigning values to attributes is more clean with MQL5.

However class logic is not like that, it is more complicated and dirty.

Anyway, again thank you.

 
Hi everybody. I need a SpinEdit directly on my chart (not on a dialog box), I tried the following code as an indicator, but everytime I click on the SpinEdit object, the value increases by one, and the decrease button doesn't work. Can anybody help me to find the problem of my code? Thank you
//+------------------------------------------------------------------+
//|                                                     SpinEdit.mq4 |
//|                        Copyright 2021, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#include <Controls/SpinEdit.mqh>

CSpinEdit   MySpin;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
    MySpin.Create(0,"MySpin",0,420,20,500,50);
    MySpin.MaxValue(30);
    MySpin.MinValue(20);
    MySpin.Value(25);     
      
    return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {  
   MySpin.OnEvent(id,lparam,dparam,sparam);  
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
 MySpin.Destroy(reason);
}