Action on CTRL +LEFT CLICK

 

Hello,

i would like to do a specific action (like an OrderSend or others) when i press CONTROL with the LEFT MOUSE BUTTON down. I am able to use CHARTEVENT_KEYDOWN and CHARTEVENT_CLICK separatly but not togheter.

This doesn't works:

#define KEY_CTRL           17


   if(id==CHARTEVENT_KEYDOWN)
   {
      if (int(lparam)==KEY_CTRL)
      {
       if (id==CHARTEVENT_CLICK) DO SOMETHING

I hope that what i wrote is clear enough (sry for my english)

Anyone wanna help me pls?


Thanks

Alberto

 

Hello Alberto .

You can manage those events separately ,they dont need to happen at the same time.

Here is an example :

//+------------------------------------------------------------------+
//|                                               CTRL_AND_MOUSE.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#define KEY_CTRL 17
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
struct mouse_controller
{
bool   LeftButtonIsPressed,RightButtonIsPressed,MouseScrollMemory,UseMouseScrollMemory,UseClickLimiter;
bool   LeftButtonWasPressed,RightButtonWasPressed;
int    x,y,pre_x,pre_y;
string c,pre_c;
uint   last_click_event,last_event,ClickLimiterLimit;
       mouse_controller(void){
       reset(true,true,true);UseMouseScrollMemory=false;UseClickLimiter=false;
       ClickLimiterLimit=0;
       }
void   reset(bool reset_coordinates,
             bool reset_strings,
             bool reset_buttons){
       if(reset_coordinates){x=-1;y=-1;pre_x=-1;pre_y=-1;}
       if(reset_strings){c=NULL;pre_c=NULL;}
       if(reset_buttons){LeftButtonIsPressed=false;RightButtonIsPressed=false;MouseScrollMemory=false;LeftButtonWasPressed=false;RightButtonWasPressed=false;}
       }
void   propagate(){pre_x=x;pre_y=y;pre_c=c;RightButtonWasPressed=RightButtonIsPressed;LeftButtonWasPressed=LeftButtonIsPressed;}
bool   is_it_still_limited(uint now,uint last,uint limit,bool setting){
       if(setting){
       int elapsed=(int)(now-last);
       if(now<last){elapsed=(int)((UINT_MAX+now)-last);}
       if((uint)elapsed<=limit){return(false);}
       }
       return(true);
       }
void   set_scroll_memory(bool new_setting){UseMouseScrollMemory=new_setting;}
void   set_click_limiter(bool new_setting,uint new_limit){UseClickLimiter=new_setting;ClickLimiterLimit=new_limit;}
void   process_events(const int &id,const long &lparam,const double &dparam,const string &sparam){
         
         if(id==CHARTEVENT_MOUSE_MOVE){
         last_event=GetTickCount();
         propagate();
         x=(int)lparam;
         y=(int)dparam;
         c=sparam;
         if(c=="0"){LeftButtonIsPressed=false;RightButtonIsPressed=false;}
         else if(c=="1"){LeftButtonIsPressed=true;RightButtonIsPressed=false;}
         else if(c=="2"){LeftButtonIsPressed=false;RightButtonIsPressed=true;}
         else if(c=="3"){LeftButtonIsPressed=true;RightButtonIsPressed=true;}
         //if something new 
           if(c!=pre_c){
           last_click_event=GetTickCount();
           //if new button and scroll memory 
           if(UseMouseScrollMemory){
           //release , release scroll memory 
             if(c=="0"){if(MouseScrollMemory){ChartSetInteger(ChartID(),CHART_MOUSE_SCROLL,true);MouseScrollMemory=false;}}
             else 
             {MouseScrollMemory=(bool)ChartGetInteger(ChartID(),CHART_MOUSE_SCROLL);if(MouseScrollMemory){ChartSetInteger(ChartID(),CHART_MOUSE_SCROLL,false);}}
           }
           //if new button and scroll memory ends here 
         }
         //if something new ends here 
         }
       }
};
mouse_controller MC;
int OnInit()
  {
//--- create timer
  MC.set_scroll_memory(true);
  ChartSetInteger(ChartID(),CHART_EVENT_MOUSE_MOVE,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
  MC.process_events(id,lparam,dparam,sparam);
   if(id==CHARTEVENT_KEYDOWN)
   {
      if (int(lparam)==KEY_CTRL)
      {
      if(MC.LeftButtonIsPressed){Print("pundix is rising and you bought");}
      else if(!MC.LeftButtonIsPressed){Print("you forgot to buy pundix");}
      }
   }
  }
//+------------------------------------------------------------------+
there may be issues as im low on caffeinne
 

Simpliest way is via WinAPI GetAsyncKeyState() - see Ctrl + left click example:

#import "user32.dll"
   int GetKeyState(int nVirtKey); // GetKeyState() checks if the key was pressed at the same time as the WM_KEYDOWN message came, GetAsyncKeyState() checks if it is still down.
   short GetAsyncKeyState(int nVirtKey);
#import

int VK_CONTROL = 0x11; // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

void OnChartEvent(const int id,         // Event ID
                  const long& lparam,   // Parameter of type long event
                  const double& dparam, // Parameter of type double event
                  const string& sparam  // Parameter of type string events
            ) {

  if (id==CHARTEVENT_CLICK) { 
    PrintFormat("Mouse click: x = %d y = %.1f", lparam, dparam);
    datetime dt; 
    double price;
    int window = 0;
    if (ChartXYToTimePrice(0, (int)lparam, (int)dparam, window, dt, price)) {
      // TerminalInfoInteger(TERMINAL_KEYSTATE_XXX) returns the same state code of a key as the GetKeyState() function in MSDN
      // not working properly after MessageBoax has been shown! 
      double controlKeyState = TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL);
      short asyncKeyState = GetAsyncKeyState(VK_CONTROL);
      PrintFormat("Price = %s, date = %s, Control key state: %s, GetAsyncKeyState(): %d", DoubleToStr(price, _Digits), TimeToStr(dt), DoubleToStr(controlKeyState), asyncKeyState);
      if (asyncKeyState < 0) {
        //Print("Ctrl+Click"); // Warning! MessageBox(...) freezes control state!
        MessageBox("Ctrl+Click");
        //OpenOrder(price);
        return;
      }  
    } else {
      Print("ChartXYToTimePrice return error code: ", GetLastError()); 
    }
  } 
Virtual-Key Codes (Winuser.h) - Win32 apps
Virtual-Key Codes (Winuser.h) - Win32 apps
  • 2020.12.12
  • Karl-Bridge-Microsoft
  • docs.microsoft.com
The following table shows the symbolic constant names, hexadecimal values, and mouse or keyboard equivalents for the virtual-key codes used by the system. The codes are listed in numeric order.