How to make bitmap object to behave like button

 

Hi guys

I am making panel, which as background image inserted as OBJ_BITMAP_LABEL, I need to place a button which have two bitmap files (pressed / released). Need advise how to make  OBJ_BITMAP_LABEL to behave like button (press and release on mouse click).

I have tried to use CBMPButton class, it places the button, but doeasnt work as classic button, rather it is pressed on click and remains pressed unless click again. Here is the code sample.

CBmpButton buybutton;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- 
   ObjectCreate(0,name1,OBJ_BITMAP_LABEL,0,0,0);
   ObjectSetString(0,name1,OBJPROP_BMPFILE,0,"Background.bmp");
   ObjectSetInteger(0,name1,OBJPROP_XDISTANCE,20);
   ObjectSetInteger(0,name1,OBJPROP_YDISTANCE,20);
        
   //create button from CBMPButton class
   buybutton.Create(0,"BmpButton2",0,40,210,134,70);
   buybutton.BmpNames("pressed.bmp","released.bmp");
//---
   return(INIT_SUCCEEDED);
  }
OBJ_VLINE - Object Types - Objects Constants - Constants, Enumerations and Structures - MQL4 Reference
OBJ_VLINE - Object Types - Objects Constants - Constants, Enumerations and Structures - MQL4 Reference
  • docs.mql4.com
The following script creates and moves the vertical line on the chart. Special functions have been developed to create and change graphical object's properties. You can use these functions "as is" in your own applications. //| Create the vertical line                                         |              width=1,           ...
 
//+------------------------------------------------------------------+
//| Create Bitmap Label object                                       |
//+------------------------------------------------------------------+
bool BitmapLabelCreate(const long              chart_ID=0,               // chart's ID
                       const string            name="BmpLabel",          // label name
                       const int               sub_window=0,             // subwindow index
                       const int               x=0,                      // X coordinate
                       const int               y=0,                      // Y coordinate
                       const string            file_on="",               // image in On mode
                       const string            file_off="",              // image in Off mode
                       const int               width=0,                  // visibility scope X coordinate
                       const int               height=0,                 // visibility scope Y coordinate
                       const int               x_offset=10,              // visibility scope shift by X axis
                       const int               y_offset=10,              // visibility scope shift by Y axis
                       const bool              state=false,              // pressed/released
                       const ENUM_BASE_CORNER  corner=CORNER_LEFT_UPPER, // chart corner for anchoring
                       const ENUM_ANCHOR_POINT anchor=ANCHOR_LEFT_UPPER, // anchor type 
                       const color             clr=clrRed,               // border color when highlighted
                       const ENUM_LINE_STYLE   style=STYLE_SOLID,        // line style when highlighted
                       const int               point_width=1,            // move point size
                       const bool              back=false,               // in the background
                       const bool              selection=false,          // highlight to move
                       const bool              hidden=true,              // hidden in the object list
                       const long              z_order=0)                // priority for mouse click
  {
//--- reset the error value
   ResetLastError();
//--- create a bitmap label
   if(!ObjectCreate(chart_ID,name,OBJ_BITMAP_LABEL,sub_window,0,0))
     {
      Print(__FUNCTION__,
            ": failed to create \"Bitmap Label\" object! Error code = ",GetLastError());
      return(false);
     }
//--- set the images for On and Off modes
   if(!ObjectSetString(chart_ID,name,OBJPROP_BMPFILE,0,file_on))
     {
      Print(__FUNCTION__,
            ": failed to load the image for On mode! Error code = ",GetLastError());
      return(false);
     }
   if(!ObjectSetString(chart_ID,name,OBJPROP_BMPFILE,1,file_off))
     {
      Print(__FUNCTION__,
            ": failed to load the image for Off mode! Error code = ",GetLastError());
      return(false);
     }
//--- set label coordinates
   ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
   ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
//--- set visibility scope for the image; if width or height values
//--- exceed the width and height (respectively) of a source image,
//--- it is not drawn; in the opposite case,
//--- only the part corresponding to these values is drawn
   ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);
   ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);
//--- set the part of an image that is to be displayed in the visibility scope
//--- the default part is the upper left area of an image; the values allow
//--- performing a shift from this area displaying another part of the image
   ObjectSetInteger(chart_ID,name,OBJPROP_XOFFSET,x_offset);
   ObjectSetInteger(chart_ID,name,OBJPROP_YOFFSET,y_offset);
//--- define the label's status (pressed or released)
   ObjectSetInteger(chart_ID,name,OBJPROP_STATE,state);
//--- set the chart's corner, relative to which point coordinates are defined
   ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
//--- set anchor type
   ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,anchor);
//--- set the border color when object highlighting mode is enabled
   ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
//--- set the border line style when object highlighting mode is enabled
   ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
//--- set a size of the anchor point for moving an object
   ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,point_width);
//--- display in the foreground (false) or background (true)
   ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
//--- enable (true) or disable (false) the mode of moving the label by mouse
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
   ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
//--- hide (true) or display (false) graphical object name in the object list
   ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
//--- set the priority for receiving the event of a mouse click in the chart
   ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
//--- successful execution
   return(true);
  }
//+------------------------------------------------------------------+
 

I am trying this code abive and but I have issues.

1. Button is not appearing unless I put ofset 0.

2. And it behaves the same, after click it remains pressed unless click again. I need the button after release the mouse became to released. 

And additional question

Is it possible to put the event handler to the same function BitmapLabelCreate, for example OrderSend. 

 
Narek Kamalyan:

@Marco vd Heijden thank you for fast reponse :)

Is it possible to put the event handler to the same function BitmapLabelCreate, for example OrderSend. 

If you want to push it back you can do so in the OnChartEvent() just reset the button state when it is clicked.

Note that OnChartEvent() does not work in the tester so you need a work around for that if you want to use it in the tester.

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
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
  {
//--- the left mouse button has been pressed on the chart
   if(id==CHARTEVENT_CLICK)
     {
      Print("The coordinates of the mouse click on the chart are: x = ",lparam,"  y = ",dparam);
     }
//--- the mouse has been clicked on the graphic object
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      Print("The mouse has been clicked on the object with name '"+sparam+"'");

//--- Here you can push back the button state...
//+------------------------------------------------------------------+
// chart event reset button state
//+------------------------------------------------------------------+
         ObjectSetInteger(0,sparam,OBJPROP_STATE,0);
         ChartRedraw();
//+------------------------------------------------------------------+
     }
//--- the key has been pressed
   if(id==CHARTEVENT_KEYDOWN)
     {
      Print("The key with code ",int(lparam)," has been pressed");
     }
//--- the object has been deleted
   if(id==CHARTEVENT_OBJECT_DELETE)
     {
      Print("The object with name ",sparam," has been deleted");
     }
//--- the object has been created
   if(id==CHARTEVENT_OBJECT_CREATE)
     {
      Print("The object with name ",sparam," has been created");
     }
//--- the object has been moved or its anchor point coordinates has been changed
   if(id==CHARTEVENT_OBJECT_DRAG)
     {
      Print("The anchor point coordinates of the object with name ",sparam," has been changed");
     }
//--- the text in the Edit of object has been changed
   if(id==CHARTEVENT_OBJECT_ENDEDIT)
     {
      Print("The text in the Edit field of the object with name ",sparam," has been changed");
     }
  }
//+------------------------------------------------------------------+
 
 ObjectSetInteger(0,sparam,OBJPROP_STATE,0);
 Sleep(100);
 ChartRedraw();

In this case button behave like it should

 

@Marco vd Heijden

Note that OnChartEvent() does not work in the tester so you need a work around for that if you want to use it in the tester. 

What should I do to make the button work in tester, can you please explain.

Also, why the button doeasnt appear unless I set offset to 0. 

 
Narek Kamalyan:

In this case button behave like it should

Not really like it should, but how you like it to behave.

You can also detect the button press by reading it's state;

bool pressed = ObjectGetInteger(0,"button",OBJPROP_STATE);

This will work in the tester, in the OnTick(), whereas the OnChartEvent() will not so keep that in mind when you want to use the button in the strategy tester.

 
Marco vd Heijden:

Not really like it should, but how you like it to behave.

You can also detect the button press by reading it's state;

This will work in the tester, in the OnTick(), whereas the OnChartEvent() will not so keep that in mind when you want to use the button in the strategy tester.

Can you please show sample of code how make the button alive in tester

 
OnTick()
{
 if(ObjectGetInteger(0,"button-name",OBJPROP_STATE))
  {
   Print("Button pressed !");
   ObjectSetInteger(0,"button-name,OBJPROP_STATE,0);
   ChartRedraw();
  }
}
 

Good, thank you. The button now works on strategy tester and runs the function.

But it doesnt change the appearance to pressed/released.

Also, if I put the same function for button click into OnTick and OnChartEvent, they will not cause conflict?

 
Narek Kamalyan:

Good, thank you. The button now works on strategy tester and runs the function.

But it doesnt change the appearance to pressed/released.

Also, if I put the same function for button click into OnTick and OnChartEvent, they will not cause conflict?

Yes they will conflict.

So you use a switch to see if it's being tested or not.

MqlInfoInteger(MQL_TESTER)

If you want the image to toggle between pressed and not pressed then don't reset the button state, or simply swap the images it will need a bit more coding in that case.

Reason: