Download MetaTrader 5

Mouse focusing on a graphical control ... how to?

To add comments, please log in or register
Log in to MQL5.community using OpenID. It is convenient!
Doerk Hilger
1154
Doerk Hilger 2015.08.22 08:03 

Hi there,

 I am working with some of the classes from the cathegory "Controls". Does anyone know how it's possible to focus the mouse on an object, i.E. CPanel or CButton or a derived object, when the mouse button is held down and the mousepointer is inside the rectangle of this object?

With focusing I mean, that when I click on it and move the mouse, that the chart behind is not affected by the motion. The CDialog seems to do it somehow when dragging, but the other controls don't. And nonono, I dont want to use CDialog ;) I don't like it ;)

Thanks in advance 

Trinh Dat
37203
Trinh Dat 2015.08.22 14:05  
Use CHART_EVENT_MOUSE_MOVE
Doerk Hilger
1154
Doerk Hilger 2015.08.22 14:30  
Trinh Dat:
Use CHART_EVENT_MOUSE_MOVE

Of course I do, cause its the base for the whole signal processing compex. But that doesn't answer my question, how I get the mouse exclusive.  

Trinh Dat
37203
Trinh Dat 2015.08.22 14:54  

Example:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- enable CHART_EVENT_MOUSE_MOVE messages
   ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
  }
//+------------------------------------------------------------------+
//| MouseState                                                       |
//+------------------------------------------------------------------+
string MouseState(uint state)
  {
   string res;
   res+="\nML: "   +(((state& 1)== 1)?"DN":"UP");   // mouse left
   res+="\nMR: "   +(((state& 2)== 2)?"DN":"UP");   // mouse right 
   res+="\nMM: "   +(((state&16)==16)?"DN":"UP");   // mouse middle
   res+="\nMX: "   +(((state&32)==32)?"DN":"UP");   // mouse first X key
   res+="\nMY: "   +(((state&64)==64)?"DN":"UP");   // mouse second X key
   res+="\nSHIFT: "+(((state& 4)== 4)?"DN":"UP");   // shift key
   res+="\nCTRL: " +(((state& 8)== 8)?"DN":"UP");   // control key
   return(res);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   if(id==CHARTEVENT_MOUSE_MOVE)
      Comment("POINT: ",(int)lparam,",",(int)dparam,"\n",MouseState((uint)sparam));
  }


Doerk Hilger
1154
Doerk Hilger 2015.08.22 16:46  

Thank you very much, but I think you still got me completely wrong ;)

I only asked how to set the FOCUS of the mouse, not how to read it´s flags or position. I also talk about C++ and MQL5 and the classes, not C and MQL4. Focusing is a method of the Windows API which is surely implemented somehow in MQL5, cause CDialog Class uses it, but because of the bunch of events which occur in only one second it´s almost impossible to debug it. 

Doerk Hilger
1154
Doerk Hilger 2015.08.25 11:58  

So nobody knew ... but i figured out. For the world after me, here is the solution. It can be done by

ChartSetInteger(m_chart_id,CHART_MOUSE_SCROLL,false); 

I modified the CWndContainer class that way, that the chart behind always stops to react as soon as the mouse is moved over any container window. This works also with the CDialog class and it´s samples. Simply replace the content of WndContainer.mqh by the following code. But please be sure to have a backup, just for that case if you meet problems.


//+------------------------------------------------------------------+
//|                                                 WndContainer.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//|                                                                  |
//|                                                Modified by Doerk |
//+------------------------------------------------------------------+
#include "Wnd.mqh"
#include <Arrays\ArrayObj.mqh>
//+------------------------------------------------------------------+
//| Class CWndContainer                                              |
//| Usage: base class of the combined control                        |
//+------------------------------------------------------------------+
class CWndContainer : public CWnd
  {
private:
   CArrayObj         m_controls;            // container of the control

   
public:
                     CWndContainer(void);
                    ~CWndContainer(void);
   //--- release memory
   virtual void      Destroy(const int reason=0);
   //--- chart event handler
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   virtual bool      OnMouseEvent(const int x,const int y,const int flags);
   //--- access the contents of container
   int               ControlsTotal(void)               const { return(m_controls.Total());   }
   CWnd*             Control(const int ind)            const { return(m_controls.At(ind));   }
   virtual CWnd     *ControlFind(const long id);
   //--- for mouse cursor focus
   virtual bool      MouseFocusKill(const long id=-1);
   //--- fill
   bool              Add(CWnd *control);
   bool              Add(CWnd &control);
   //--- underflowing
   bool              Delete(CWnd *control);
   bool              Delete(CWnd &control);
   //--- geometry
   virtual bool      Move(const int x,const int y);
   virtual bool      Move(const CPoint &point);
   virtual bool      Shift(const int dx,const int dy);
   //--- ID
   virtual long      Id(const long id);
   //--- state
   virtual bool      Enable(void);
   virtual bool      Disable(void);
   virtual bool      Show(void);
   virtual bool      Hide(void);
   //--- methods for working with files
   virtual bool      Save(const int file_handle);
   virtual bool      Load(const int file_handle);

protected:
   //--- internal event handlers
   virtual bool      OnResize(void);
   virtual bool      OnActivate(void);
   virtual bool      OnDeactivate(void);
private:
   bool              m_MouseFocusLocked;    // true if the mouse focus was locked by this instance
   void              VerifyMouseFocus(const int id,const int x, const int y, const int flags);  
  };
//+------------------------------------------------------------------+
//| VerifyMouseFocus (Added)                                         |
//+------------------------------------------------------------------+
void CWndContainer::VerifyMouseFocus(const int id,const int x, const int y, const int flags)
   {
   static bool bLocked=false;
   bool bLeftButton=(flags&1)>0;
   
   if (id==CHARTEVENT_MOUSE_MOVE)
      {
//--- If left button is held and the mouse is inside the rectangle
//    of the container area, we prevent the chart behind from 
//    becoming affected by any mouse movements       
      if (Contains(x,y) && bLeftButton)
         {
         if (!bLocked)
            {
            ChartSetInteger(m_chart_id,CHART_MOUSE_SCROLL,false);
//--- Save flag for other instances            
            bLocked=true;  
            }
         }
//--- Release the focus when the mouse pointer is outside the
//    rectangular area and if the chart was locked by this
//    function         
      else if (!bLeftButton && bLocked)
         {
         if (bLocked)
            {
            ChartSetInteger(m_chart_id,CHART_MOUSE_SCROLL,true);
            bLocked=false;
            }
         }
      }
   } 

//+------------------------------------------------------------------+
//| Common handler of chart events (modified)                        |
//+------------------------------------------------------------------+
bool CWndContainer::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- if an object is being dragged, pass control to the special drag object
   if(m_drag_object!=NULL && m_drag_object.OnEvent(id,lparam,dparam,sparam))
      return(true);
//--- Mouse shall be locked whenever the pointer is inside
//    the rectangle of the container.
   VerifyMouseFocus(id,(int)lparam,(int)dparam,(int)sparam);
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=total-1;i>=0;i--)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      if(control.OnEvent(id,lparam,dparam,sparam))
         return(true);
     }
//--- not handled
   return(false);
  }

//+------------------------------------------------------------------+
//| Common handler of mouse events (modified)                        |
//+------------------------------------------------------------------+
bool CWndContainer::OnMouseEvent(const int x,const int y,const int flags)
  {
   if(!IS_VISIBLE)
      return(false);
//--- if an object is being dragged, pass control to the special drag object
   if(m_drag_object!=NULL && m_drag_object.OnMouseEvent(x,y,flags))
      return(true);
//--- Mouse shall be locked whenever the pointer is inside
//    the rectangle of the container.
   VerifyMouseFocus(CHARTEVENT_MOUSE_MOVE,x,y,flags);      
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=total-1;i>=0;i--)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      if(control.OnMouseEvent(x,y,flags))
         return(true);
     }
//--- call of the method of the parent class
   return(CWnd::OnMouseEvent(x,y,flags));
  }

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CWndContainer::CWndContainer(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CWndContainer::~CWndContainer(void)
  {
  }
//+------------------------------------------------------------------+
//| Delete group of controls                                         |
//+------------------------------------------------------------------+
void CWndContainer::Destroy(const int reason)
  {
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(0);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.Destroy();
      m_controls.Delete(0);
     }
  }
//+------------------------------------------------------------------+
//| Find control by specified ID                                     |
//+------------------------------------------------------------------+
CWnd *CWndContainer::ControlFind(const long id)
  {
   CWnd *result=CWnd::ControlFind(id);
//---
   if(result!=NULL)
      return(result);
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      result=control.ControlFind(id);
      if(result!=NULL)
         break;
     }
//--- return the result
   return(result);
  }
//+------------------------------------------------------------------+
//| Remove the mouse focus from control                              |
//+------------------------------------------------------------------+
bool CWndContainer::MouseFocusKill(const long id=-1)
  {
   if(!IS_ACTIVE)
      return(false);
   Deactivate();
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.MouseFocusKill();
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Add control to the group (by pointer)                            |
//+------------------------------------------------------------------+
bool CWndContainer::Add(CWnd *control)
  {
//--- check of pointer
   if(control==NULL)
      return(false);
//--- correct the coordinates of added control
   control.Shift(Left(),Top());
//--- "projecting" the group flag "visibility" to the added element
   if(IS_VISIBLE && control.IsVisible())
     {
      //--- element will be "visible" only if the group is "visible" and the element is completely "within" this group
      control.Visible(Contains(control));
     }
   else
      control.Hide();
//--- "projecting" the group flag "enabled" to the added element
   if(IS_ENABLED)
      control.Enable();
   else
      control.Disable();
//--- adding
   return(m_controls.Add(control));
  }
//+------------------------------------------------------------------+
//| Add control to the group (by reference)                          |
//+------------------------------------------------------------------+
bool CWndContainer::Add(CWnd &control)
  {
//--- add by pointer
   return(Add((CWnd*)GetPointer(control)));
  }
//+------------------------------------------------------------------+
//| Delete control from the group (by pointer)                       |
//+------------------------------------------------------------------+
bool CWndContainer::Delete(CWnd *control)
  {
//--- check of pointer
   if(control==NULL)
      return(false);
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *pointer=Control(i);
      //--- check of pointer
      if(pointer==NULL)
         continue;
      //--- delete item from group
      if(pointer==control)
         return(m_controls.Delete(i));
     }
//--- failure
   return(false);
  }
//+------------------------------------------------------------------+
//| Delete control from the group (by reference)                     |
//+------------------------------------------------------------------+
bool CWndContainer::Delete(CWnd &control)
  {
//--- delete by pointer
   return(Delete((CWnd*)GetPointer(control)));
  }
//+------------------------------------------------------------------+
//| Absolute movement of the controls group                          |
//+------------------------------------------------------------------+
bool CWndContainer::Move(const int x,const int y)
  {
//--- relative movement
   return(Shift(x-Left(),y-Top()));
  }
//+------------------------------------------------------------------+
//| Absolute movement of the controls group                          |
//+------------------------------------------------------------------+
bool CWndContainer::Move(const CPoint &point)
  {
//--- relative movement
   return(Shift(point.x-Left(),point.y-Top()));
  }
//+------------------------------------------------------------------+
//| Relative movement of the controls group                          |
//+------------------------------------------------------------------+
bool CWndContainer::Shift(const int dx,const int dy)
  {
//--- call of the method of the parent class
   if(!CWnd::Shift(dx,dy)) return(false);
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      //--- move the group item
      control.Shift(dx,dy);
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Set ID of control                                                |
//+------------------------------------------------------------------+
long CWndContainer::Id(const long id)
  {
//--- reserve ID for container
   long id_used=1;
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      id_used+=control.Id(id+id_used);
     }
   m_id=id;
//--- return number of used IDs
   return(id_used);
  }
//+------------------------------------------------------------------+
//| Enables event handling by the group of controls                  |
//+------------------------------------------------------------------+
bool CWndContainer::Enable(void)
  {
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.Enable();
     }
//--- call of the method of the parent class
   return(CWnd::Enable());
  }
//+------------------------------------------------------------------+
//| Disables event handling by the group of controls                 |
//+------------------------------------------------------------------+
bool CWndContainer::Disable(void)
  {
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.Disable();
     }
//--- call of the method of the parent class
   return(CWnd::Disable());
  }
//+------------------------------------------------------------------+
//| Makes the group of controls visible                              |
//+------------------------------------------------------------------+
bool CWndContainer::Show(void)
  {
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.Show();
     }
//--- call of the method of the parent class
   return(CWnd::Show());
  }
//+------------------------------------------------------------------+
//| Makes the group of controls hidden                               |
//+------------------------------------------------------------------+
bool CWndContainer::Hide(void)
  {
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.Hide();
     }
//--- call of the method of the parent class
   return(CWnd::Hide());
  }
//+------------------------------------------------------------------+
//| Handler of resizing                                              |
//+------------------------------------------------------------------+
bool CWndContainer::OnResize()
  {
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      if(!control.Align(Rect()))
         return(false);
     }
//--- handled
   return(true);
  }
//+------------------------------------------------------------------+
//| Handler of activating the group of controls                      |
//+------------------------------------------------------------------+
bool CWndContainer::OnActivate(void)
  {
   if(IS_ACTIVE)
      return(false);
   Activate();
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.Activate();
     }
//--- handled
   return(true);
  }
//+------------------------------------------------------------------+
//| Handler of deactivating the group of controls                    |
//+------------------------------------------------------------------+
bool CWndContainer::OnDeactivate(void)
  {
   if(!IS_ACTIVE)
      return(false);
   Deactivate();
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      control.Deactivate();
     }
//--- handled
   return(true);
  }
//+------------------------------------------------------------------+
//| Save                                                             |
//+------------------------------------------------------------------+
bool CWndContainer::Save(const int file_handle)
  {
   bool result=true;
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      result&=control.Save(file_handle);
     }
//--- result
   return(result);
  }
//+------------------------------------------------------------------+
//| Load                                                             |
//+------------------------------------------------------------------+
bool CWndContainer::Load(const int file_handle)
  {
   bool result=true;
//--- loop by elements of group
   int total=m_controls.Total();
   for(int i=0;i<total;i++)
     {
      CWnd *control=Control(i);
      //--- check of pointer
      if(control==NULL)
         continue;
      result&=control.Load(file_handle);
     }
//--- result
   return(result);
  }
//+------------------------------------------------------------------+

To add comments, please log in or register