Draging an Object - problem with button being pushed

 

Hi guys,

I'm making a trade management tool. Here is the problem:

1 - I have only one selectable item - rectangle label that makes a background - you can see the little dot in top-left corner in picture 1.

2 - When i drag it around there are no signals sent to event handling function - only when dropped the code runs and aligns other components with main frame. (in this picture i'm still dragging the main frame)

3- The problem is that when i drag the main frame and accidentally drop it in a place where i have a button - that button runs the code - e.g. buys. This is shown in picture number 3. (in this picture i released the main frame but instead of running alignment code for action of frame being dragged it run a code for a pressed button)

I tried disabling buttons while moving frame but the event handling function receives signal from the frame only when i release mouse button and drop the main frame. Therefore i cannot know that i'm dragging this item.

I won't upload the code because it's very long and simple - when sparam = "MainFrame" i change coordinates of other components by ObjectSetInteger(...).

Is there any way to avoid false button signals?

(If the pictures seem vague - the only problem occurs when a mouse button is released above a button, otherwise the code runs ok. and other components align properly after mouse button have been released.)


tool

The only thing i can think of is writing a OnTimer function to check if coordinates of frame have changed every 100ms or so. But this would slow the program so much..

 
Dont you use OnChartEvent()? You could easy figure out if the mouse button went down in "your area" and the either interact or not. You will not get this done properly with the built in chart objects anyway, but thats another topic.
 

Yes, i use OnChartEvent() , tried with CHARTEVENT_OBJECT_CLICK ,CHARTEVENT_CLICK and CHARTEVENT_OBJECT_DRAG. They all receive signal only after the mouse button has been released.

There are some panels that use internal mql4 buttons and labels and hold it together during moving around on the chart, sadly i found none with open source code. (i maybe wrong, tested one and it has buttons at sides to change location, no dragging)

The function is structured as below:

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam){
   
   if(id==CHARTEVENT_OBJECT_DRAG){
      if(sparam=="Frame"){
         framex=(int)ObjectGet("Frame",OBJPROP_XDISTANCE);
         framey=(int)ObjectGet("Frame",OBJPROP_YDISTANCE);

         ObjectSet("BuyButton",OBJPROP_XDISTANCE,framex-90);
         ObjectSet("BuyButton",OBJPROP_YDISTANCE,framey);
         //... the same for other components
      }
   }
   
   if(id==CHARTEVENT_OBJECT_CLICK){
     
      //Actions for all buttons
   }
}

 
Janek6191:

Yes, i use OnChartEvent() , tried with CHARTEVENT_OBJECT_CLICK ,CHARTEVENT_CLICK and CHARTEVENT_OBJECT_DRAG. They all receive signal only after the mouse button has been released.

There are some panels that use internal mql4 buttons and labels and hold it together during moving around on the chart, sadly i found none with open source code. (i maybe wrong, tested one and it has buttons at sides to change location, no dragging)

The function is structured as below:

You need the MOUSE_MOVE event and check the button states to figure out, when the button goes down. I uploaded also a corrected version of CWndContainer which will solve your next problem too: The chart will move when the mouse goes down in the area of your panel. Please search at the code base for my upload. 
 

Buttons work fine. The problem is that i cannot get information from EA level that somebody just started dragging the Frame object.

If there is no solution on mql4 level then i'm going to stay with what i have and be careful while dragging this menu around. Thanks for you help :).

 

I told you what to do, there is a solution. 

Use the control classes, create a container with my mod of CWndContainer, create the buttons as objects, add the buttons to the container and in case of doubt use the mouse-motion event and compare the position of the mouse to the position of the container, thats all.. 

 

That's ok. I thought there was an easier way to do such a thing. Found some articles on GUI but it will take more time to implement.

https://www.mql5.com/en/articles/2126

Thanks once again.

 
Janek6191:

That's ok. I thought there was an easier way to do such a thing. Found some articles on GUI but it will take more time to implement.

https://www.mql5.com/en/articles/2126

Thanks once again.

Not really, this article describes the development of a completely different GUI. In your case its easy and can be done by using the standard controls with just a couple of lines.

Anyway, youre welcome.  

 

I found a good enough solution as i don't want to spend much more time on this project. Probably might help someone:

In OnChartEvent() i put:

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam){
   
   if(id==CHARTEVENT_OBJECT_CLICK){
      if(ObjectGetInteger(chart_ID,"Frame",OBJPROP_SELECTED)){
         observeFrame();
      }
   //code for other components..
   }
}


Then i have observeFrame() function that looks like:

void observeFrame(){
   while(ObjectGetInteger(chart_ID,"Frame",OBJPROP_SELECTED)){
   
   if(framex!=(int)ObjectGet("Frame",OBJPROP_XDISTANCE) || framey!=(int)ObjectGet("Frame",OBJPROP_YDISTANCE)){
         framex=(int)ObjectGet("Frame",OBJPROP_XDISTANCE);
         framey=(int)ObjectGet("Frame",OBJPROP_YDISTANCE);

         ObjectSet("BuyButton",OBJPROP_XDISTANCE,framex-90);
         ObjectSet("BuyButton",OBJPROP_YDISTANCE,framey);
         //The same for other components..
      }
    Sleep(25);
   }
}

This ensures that when the Frame (rectangle label) is selected (double click) it will look for changes in coordinates on the chart every 25ms -enough to be responsive. (of course a bit longer than 25ms. as the code takes time to run)

When  de-select that object (double click) it finishes.

 

You can move the other components at once when dragging the main frame.

//OnInit
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);

//OnChartEvent
if(id==CHARTEVENT_MOUSE_MOVE && sparam=="1" &&
  (framex!=(int)ObjectGet("Frame",OBJPROP_XDISTANCE) || framey!=(int)ObjectGet("Frame",OBJPROP_YDISTANCE))) 
   {
   //redraw all components ("Frame" is dragging)
   }
 
Exactly! Thank you, works great.
Reason: