利用 MQL5 的交互式 GUI 改进您的交易图表(第 II 部分):可移动 GUI(II)·进阶篇
用鼠标拖拽面板前先抓住按下瞬间
想在 MT5 图表上做一个能被鼠标拖动的自定义面板,第一步不是画图形,而是准确捕获左键按下的那一帧坐标与对象初始位置。下面这段代码把鼠标状态、按下点、对象距离参数都先声明成全局变量,供后续移动逻辑复用。 int previousMouseState = 0; int mlbDownX = 0; int mlbDownY = 0; int mlbDownXDistance = 0; int mlbDownYDistance = 0; bool movingState = false; 核心在 OnChartEvent 里只认 CHARTEVENT_MOUSE_MOVE:用 lparam 取 X、dparam 取 Y、sparam 转成 MouseState(0=松开,1=左键按下)。通过 previousMouseState==0 且 MouseState==1 判定为「首次左键落点」,把当下 X/Y 以及对象的 XDistance、YDistance 存进 mlbDown 系列变量。 接着用 XDistance/YDistance(初始应为 100)加 XSize/YSize(初始应为 200)框出面板命中区:若按下点在范围内才把 movingState 置 true。此时顺手 ChartSetInteger(0, CHART_MOUSE_SCROLL, false) 锁掉图表随鼠标平移,避免拖面板时图表跟着跑。 开 MT5 新建 EA,把 TestRectangle 在 OnInit 里设成 XDistance=100、YDistance=100、XSize=200、YSize=200,挂上这段事件处理,就能在可视化上验证「点中面板区域才允许拖动」的触发是否准确。外汇与贵金属图表插件改造属高风险操作,参数误写可能导致界面锁死,建议先在模拟盘图表试跑。
class="type">int previousMouseState = class="num">0; class="type">int mlbDownX = class="num">0; class="type">int mlbDownY = class="num">0; class="type">int mlbDownXDistance = class="num">0; class="type">int mlbDownYDistance = class="num">0; class="type">bool movingState = class="kw">false; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnChartEvent(class="kw">const class="type">int id, class="kw">const class="type">long& lparam, class="kw">const class="type">class="kw">double& dparam, class="kw">const class="type">class="kw">string& sparam) { class=class="str">"cmt">//Verify the event that triggered the OnChartEvent was CHARTEVENT_MOUSE_MOVE because we only want to execute out code when that is the case if(id == CHARTEVENT_MOUSE_MOVE) { class=class="str">"cmt">//define X, Y, XDistance, YDistance, XSize, YSize class="type">int X = (class="type">int)lparam; class="type">int Y = (class="type">int)dparam; class="type">int MouseState = (class="type">int)sparam; class="type">class="kw">string name = "TestRectangle"; class="type">int XDistance = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_XDISTANCE); class=class="str">"cmt">//Should be class="num">100 initially as we set it in OnInit() class="type">int YDistance = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_YDISTANCE); class=class="str">"cmt">//Should be class="num">100 initially as we set it in OnInit() class="type">int XSize = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_XSIZE); class=class="str">"cmt">//Should be class="num">200 initially as we set it in OnInit() class="type">int YSize = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_YSIZE); class=class="str">"cmt">//Should be class="num">200 initially as we set it in OnInit() if(previousMouseState == class="num">0 && MouseState == class="num">1) class=class="str">"cmt">//Check if this was the MLB first click { mlbDownX = X; class=class="str">"cmt">//Set mlbDownX(Variable that stores the initial MLB X location) equal to the current X mlbDownY = Y; class=class="str">"cmt">//Set mlbDownY(Variable that stores the initial MLB Y location) equal to the current Y mlbDownXDistance = XDistance; class=class="str">"cmt">//Set mlbDownXDistance(Variable that stores the initial XDistance i.e. Width of the dashboard) equal to the current XDistance mlbDownYDistance = YDistance; class=class="str">"cmt">//Set mlbDownYDistance(Variable that stores the initial YDistance i.e. Height of the dashboard) equal to the current YDistance if(X >= XDistance && X <= XDistance + XSize && Y >= YDistance && Y <= YDistance + YSize) class=class="str">"cmt">//Check if the click was on the dashboard { movingState = true; class=class="str">"cmt">//If yes the set movingState to True } } if(movingState)class=class="str">"cmt">//if movingState is true, Update the Dashboard position { ChartSetInteger(class="num">0, CHART_MOUSE_SCROLL, class="kw">false);class=class="str">"cmt">//Restrict Chart to be moved by Mouse } } }
◍ 拖拽结束后的状态复位与类骨架
鼠标左键松开(MouseState 回到 0)时,代码把 movingState 重置为 false,并调用 ChartSetInteger(0, CHART_MOUSE_SCROLL, true) 恢复图表自身的滚轮与平移响应。若不放开这个开关,用户拖完自定义图形后图表会卡在“禁滚”状态,缩放和拖屏都失效。 前面的拖拽过程里,ObjectSetInteger 用 mlbDownXDistance + (X - mlbDownX) 实时改写 OBJPROP_XDISTANCE,Y 方向同理,最后 ChartRedraw(0) 强制重绘。这里 X、Y 是鼠标当前坐标,mlbDownX/Y 是按下瞬间坐标,差值就是位移增量。 GUI_Movable 类把 previousMouseState、mlbDownX、mlbDownY、mlbDownXDistance、mlbDownYDistance 和 movingState 收进 private,构造时全部清零或 false。公开接口只留 Name 和 OnEvent 空壳,说明这一节只是把可移动控件的“状态容器”搭好,具体事件逻辑还没填。 在 MT5 里新建 EA 把这段类声明贴进去编译,若报“previousMouseState 重定义”,多半是类内外写了两遍同名字段——原文里类定义确实出现了两次私有变量声明,需并成一份。
ObjectSetInteger(class="num">0, name, OBJPROP_XDISTANCE, mlbDownXDistance + X - mlbDownX); class=class="str">"cmt">//Update XDistance to: mlbDownXDistance + (X - mlbDownX) ObjectSetInteger(class="num">0, name, OBJPROP_YDISTANCE, mlbDownYDistance + Y - mlbDownY); class=class="str">"cmt">//Update YDistance to: mlbDownYDistance + (Y - mlbDownY) ChartRedraw(class="num">0); class=class="str">"cmt">//Redraw Chart } if(MouseState == class="num">0) class=class="str">"cmt">//Check if MLB is not pressed { movingState = class="kw">false; class=class="str">"cmt">//set movingState again to class="kw">false ChartSetInteger(class="num">0, CHART_MOUSE_SCROLL, true); class=class="str">"cmt">//allow the cahrt to be moved again } previousMouseState = MouseState; class=class="str">"cmt">//update the previousMouseState at the end so that we can use it next time and copare it with new value } } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Class GUI_Movable | class=class="str">"cmt">//+------------------------------------------------------------------+ class GUI_Movable { class="kw">private: class="type">int previousMouseState, mlbDownX, mlbDownY, mlbDownXDistance, mlbDownYDistance; class="type">bool movingState; class="kw">public: GUI_Movable() : previousMouseState(class="num">0), mlbDownX(class="num">0), mlbDownY(class="num">0), mlbDownXDistance(class="num">0), mlbDownYDistance(class="num">0), movingState(class="kw">false) {}; }; class=class="str">"cmt">//+------------------------------------------------------------------+ class="kw">public: class="type">class="kw">string Name; GUI_Movable() : previousMouseState(class="num">0), mlbDownX(class="num">0), mlbDownY(class="num">0), mlbDownXDistance(class="num">0), mlbDownYDistance(class="num">0), movingState(class="kw">false), Name(NULL) {}; class="kw">public: class="type">class="kw">string Name; class="type">void OnEvent(class="type">int id, class="type">long lparam, class="type">class="kw">double dparam, class="type">class="kw">string sparam); class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void GUI_Movable::OnEvent(class="type">int id, class="type">long lparam, class="type">class="kw">double dparam, class="type">class="kw">string sparam) { } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+
「用鼠标拖拽面板的坐标捕获逻辑」
在 MT5 的 GUI 类里,面板能不能被鼠标拖动,核心全压在 OnEvent 对 CHARTEVENT_MOUSE_MOVE 的过滤上。只处理鼠标移动事件,其他图表事件一律不进逻辑,避免无谓重绘消耗。 事件进来后先把 lparam、dparam、sparam 拆成 X、Y 和 MouseState,再用 ObjectGetInteger 读对象的 XDistance / YDistance / XSize / YSize。按初始化约定,XDistance 与 YDistance 起手是 100,XSize 与 YSize 是 200,这套基准值决定了命中判定的边框。 左键第一次按下时(previousMouseState==0 且 MouseState==1),记录按下点 mlbDownX/Y 以及当时的 XDistance/YDistance。若 X、Y 落在 [XDistance, XDistance+XSize] 与 [YDistance, YDistance+YSize] 的矩形内,才把 movingState 置真,说明抓中了面板。 拖动期间每帧用 mlbDownXDistance + X - mlbDownX 重写 OBJPROP_XDISTANCE,Y 同理,并顺手 ChartSetInteger 关掉 CHART_MOUSE_SCROLL 防止图表乱跑,最后 ChartRedraw 落地。MouseState 回 0 即清 movingState,松手就停。外汇与贵金属图表加载此类脚本属高风险操作,参数误写可能导致面板飞出可视区。 别把初始距离当默认值写死 实际项目里若 OnInit 改了初始 XDistance/YDistance,上面注释里的 100 就不能信,必须以 ObjectGetInteger 实时读数为准,否则点击命中框会整体偏移。
class="type">void GUI_Movable::OnEvent(class="type">int id, class="type">long lparam, class="type">class="kw">double dparam, class="type">class="kw">string sparam) { class=class="str">"cmt">//Verify the event that triggered the OnChartEvent was CHARTEVENT_MOUSE_MOVE because we only want to execute out code when that is the case if(id == CHARTEVENT_MOUSE_MOVE) { class=class="str">"cmt">//define X, Y, XDistance, YDistance, XSize, YSize class="type">int X = (class="type">int)lparam; class="type">int Y = (class="type">int)dparam; class="type">int MouseState = (class="type">int)sparam; class="type">class="kw">string name = Name; class="type">int XDistance = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_XDISTANCE); class=class="str">"cmt">//Should be class="num">100 initially as we set it in OnInit() class="type">int YDistance = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_YDISTANCE); class=class="str">"cmt">//Should be class="num">100 initially as we set it in OnInit() class="type">int XSize = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_XSIZE); class=class="str">"cmt">//Should be class="num">200 initially as we set it in OnInit() class="type">int YSize = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_YSIZE); class=class="str">"cmt">//Should be class="num">200 initially as we set it in OnInit() if(previousMouseState == class="num">0 && MouseState == class="num">1) class=class="str">"cmt">//Check if this was the MLB first click { mlbDownX = X; class=class="str">"cmt">//Set mlbDownX(Variable that stores the initial MLB X location) equal to the current X mlbDownY = Y; class=class="str">"cmt">//Set mlbDownY(Variable that stores the initial MLB Y location) equal to the current Y mlbDownXDistance = XDistance; class=class="str">"cmt">//Set mlbDownXDistance(Variable that stores the initial XDistance i.e. Width of the dashboard) equal to the current XDistance mlbDownYDistance = YDistance; class=class="str">"cmt">//Set mlbDownYDistance(Variable that stores the initial YDistance i.e. Height of the dashboard) equal to the current YDistance if(X >= XDistance && X <= XDistance + XSize && Y >= YDistance && Y <= YDistance + YSize) class=class="str">"cmt">//Check if the click was on the dashboard { movingState = true; class=class="str">"cmt">//If yes the set movingState to True } } if(movingState)class=class="str">"cmt">//if movingState is true, Update the Dashboard position { ChartSetInteger(class="num">0, CHART_MOUSE_SCROLL, class="kw">false);class=class="str">"cmt">//Restrict Chart to be moved by Mouse ObjectSetInteger(class="num">0, name, OBJPROP_XDISTANCE, mlbDownXDistance + X - mlbDownX);class=class="str">"cmt">//Update XDistance to: mlbDownXDistance + (X - mlbDownX) ObjectSetInteger(class="num">0, name, OBJPROP_YDISTANCE, mlbDownYDistance + Y - mlbDownY);class=class="str">"cmt">//Update YDistance to: mlbDownYDistance + (Y - mlbDownY) ChartRedraw(class="num">0); class=class="str">"cmt">//Redraw Chart } if(MouseState == class="num">0)class=class="str">"cmt">//Check if MLB is not pressed { movingState = class="kw">false;class=class="str">"cmt">//set movingState again to class="kw">false
用矩形标签搭一个可拖拽面板
想在 MT5 图表上放一块能被鼠标拖着跑的 GUI 面板,核心是先建一个 OBJ_RECTANGLE_LABEL 对象,再靠 CHART_EVENT_MOUSE_MOVE 捕获鼠标动作。下面这段初始化把矩形放在距左 100px、距顶 100px 的位置,宽高各 200px,尺寸参数直接写死,方便你改一个数就看到变化。 开启鼠标事件是关键一步:ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true) 之后,OnChartEvent 才能收到 id 为鼠标移动的事件,否则拖拽逻辑永远不触发。 把面板名传给 GUI_Movable 类的实例 Dashboard.Name = name,再把所有图表事件转交 Dashboard.OnEvent 处理,拖拽判定就交给那个封装类了。外汇与贵金属图表上做这种悬浮控件,注意高频行情下鼠标事件可能丢帧,属正常风险。 复制下面代码到 EA 的 OnInit,编译后拖上图,应该能立即看到左上角出现 200x200 的方块;用「小布盯盘」跑同款结构,可省去手写事件分发。
class="type">class="kw">string name = "TestRectangle"; class="macro">#include "GUI_Movable.mqh" GUI_Movable Dashboard; class="type">int OnInit() { class="type">class="kw">string name = "TestRectangle"; ObjectCreate(class="num">0, name, OBJ_RECTANGLE_LABEL, class="num">0, class="num">0, class="num">0); ObjectSetInteger(class="num">0, name, OBJPROP_XDISTANCE, class="num">100); ObjectSetInteger(class="num">0, name, OBJPROP_YDISTANCE, class="num">100); ObjectSetInteger(class="num">0, name, OBJPROP_XSIZE, class="num">200); ObjectSetInteger(class="num">0, name, OBJPROP_YSIZE, class="num">200); ChartSetInteger(class="num">0, CHART_EVENT_MOUSE_MOVE, true); Dashboard.Name = name; class="kw">return(INIT_SUCCEEDED); } class="type">void OnChartEvent(class="kw">const class="type">int id,class="kw">const class="type">long& lparam,class="kw">const class="type">class="kw">double& dparam,class="kw">const class="type">class="kw">string& sparam) { Dashboard.OnEvent(id, lparam, dparam, sparam); }
◍ 用矩形标签搭可拖拽面板的底子
想在 MT5 图表上做一个能跟鼠标跑的盯盘面板,第一步是把 OBJ_RECTANGLE_LABEL 这种无时间坐标的矩形标签建出来,并定死它在窗口里的初始位置与尺寸。下面这段初始化把标签放在距左边界 100px、距上边界 100px 处,宽高各 200px,相当于在图表左上区域圈出一块 200×200 的悬浮区。 ObjectCreate(0, name, OBJ_RECTANGLE_LABEL, 0, 0, 0); // 在图表 0 上创建名为 name 的矩形标签,后三个 0 表示不用绑定时间/价格坐标 ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 100); // 标签左边距图表窗口左侧 100 像素 ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 100); // 标签顶边距图表窗口顶部 100 像素 ObjectSetInteger(0, name, OBJPROP_XSIZE, 200); // 标签宽度设为 200 像素 ObjectSetInteger(0, name, OBJPROP_YSIZE, 200); // 标签高度设为 200 像素 ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true); // 开启鼠标移动事件,后续才能捕获拖拽 Dashboard.Name = name; // 把标签名交给面板类实例 return(INIT_SUCCEEDED); // 初始化完成返回成功 光有标签还不够,必须打开 CHART_EVENT_MOUSE_MOVE 才能拿到鼠标坐标流。OnChartEvent 里只做一件事:把事件透传给 Dashboard.OnEvent,由面板类判断是不是左键拖拽。 void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) { Dashboard.OnEvent(id, lparam, dparam, sparam); } GUI_Movable 类用 previousMouseState、mlbDownX/Y 等私有变量记录按下瞬间的鼠标位置和标签偏移量。OnEvent 里先卡一道 if(id == CHARTEVENT_MOUSE_MOVE),不是鼠标移动事件直接不往下走,避免无谓计算。外汇与贵金属图表挂 EA 做这类 UI 改动时波动快、点差跳变频繁,属于高风险操作环境,建议先在模拟盘验证拖拽逻辑。
ObjectCreate(class="num">0, name, OBJ_RECTANGLE_LABEL, class="num">0, class="num">0, class="num">0); class=class="str">"cmt">//Set XDistance to 100px i.e. Distance of Rectangle Label 100px from Left of the Chart Window ObjectSetInteger(class="num">0, name, OBJPROP_XDISTANCE, class="num">100); class=class="str">"cmt">//Set YDistance to 100px i.e. Distance of Rectangle Label 100px from Top of the Chart Window ObjectSetInteger(class="num">0, name, OBJPROP_YDISTANCE, class="num">100); class=class="str">"cmt">//Set XSize to 200px i.e. Width of Rectangle Label ObjectSetInteger(class="num">0, name, OBJPROP_XSIZE, class="num">200); class=class="str">"cmt">//Set YSize to 200px i.e. Height of Rectangle Label ObjectSetInteger(class="num">0, name, OBJPROP_YSIZE, class="num">200); class=class="str">"cmt">//Set CHART_EVENT_MOUSE_MOVE to true to detect mouse move event ChartSetInteger(class="num">0, CHART_EVENT_MOUSE_MOVE, true); class=class="str">"cmt">//Give dashboard&class="macro">#x27;s name to the class instance Dashboard.Name = name; class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnChartEvent(class="kw">const class="type">int id, class="kw">const class="type">long& lparam, class="kw">const class="type">class="kw">double& dparam, class="kw">const class="type">class="kw">string& sparam) { Dashboard.OnEvent(id, lparam, dparam, sparam); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Class GUI_Movable | class=class="str">"cmt">//+------------------------------------------------------------------+ class GUI_Movable { class="kw">private: class="type">int previousMouseState, mlbDownX, mlbDownY, mlbDownXDistance, mlbDownYDistance; class="type">bool movingState; class="kw">public: GUI_Movable() : previousMouseState(class="num">0), mlbDownX(class="num">0), mlbDownY(class="num">0), mlbDownXDistance(class="num">0), mlbDownYDistance(class="num">0), movingState(class="kw">false), Name(NULL) {}; class="type">class="kw">string Name; class="type">void OnEvent(class="type">int id, class="type">long lparam, class="type">class="kw">double dparam, class="type">class="kw">string sparam); }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void GUI_Movable::OnEvent(class="type">int id, class="type">long lparam, class="type">class="kw">double dparam, class="type">class="kw">string sparam) { class=class="str">"cmt">//Verify the event that triggered the OnChartEvent was CHARTEVENT_MOUSE_MOVE because we only want to execute out code when that is the case if(id == CHARTEVENT_MOUSE_MOVE)
「用鼠标拖拽面板的位置同步逻辑」
在 MT5 的图表事件回调里,左键按下那一刻要先记录初始坐标与面板距离参数。OnInit 里若把 OBJPROP_XDISTANCE 和 OBJPROP_YDISTANCE 设为 100、OBJPROP_XSIZE/YSIZE 设为 200,那么 XDistance、YDistance 初始读出来就是 100,XSize、YSize 是 200,这是后续偏移计算的基准。 判定点击是否落在面板区域内,用 X 在 [XDistance, XDistance+XSize]、Y 在 [YDistance, YDistance+YSize] 之间即可。命中就把 movingState 置真,并暂时关掉 CHART_MOUSE_SCROLL,避免拖面板时图表跟着滚。 移动时每帧把 XDistance 更新为 mlbDownXDistance + (X - mlbDownX),YDistance 同理,再 ChartRedraw 刷新。左键松开(MouseState==0)就把 movingState 复位、重新打开滚动。外汇与贵金属图表波动剧烈,这种自定义面板拖动在高波动时可能漏帧,建议在模拟盘先验证手感。
{
class=class="str">"cmt">//define X, Y, XDistance, YDistance, XSize, YSize
class="type">int X = (class="type">int)lparam;
class="type">int Y = (class="type">int)dparam;
class="type">int MouseState = (class="type">int)sparam;
class="type">class="kw">string name = Name;
class="type">int XDistance = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_XDISTANCE); class=class="str">"cmt">//Should be class="num">100 initially as we set it in OnInit()
class="type">int YDistance = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_YDISTANCE); class=class="str">"cmt">//Should be class="num">100 initially as we set it in OnInit()
class="type">int XSize = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_XSIZE); class=class="str">"cmt">//Should be class="num">200 initially as we set it in OnInit()
class="type">int YSize = (class="type">int)ObjectGetInteger(class="num">0, name, OBJPROP_YSIZE); class=class="str">"cmt">//Should be class="num">200 initially as we set it in OnInit()
if(previousMouseState == class="num">0 && MouseState == class="num">1) class=class="str">"cmt">//Check if this was the MLB first click
{
mlbDownX = X; class=class="str">"cmt">//Set mlbDownX(Variable that stores the initial MLB X location) equal to the current X
mlbDownY = Y; class=class="str">"cmt">//Set mlbDownY(Variable that stores the initial MLB Y location) equal to the current Y
mlbDownXDistance = XDistance; class=class="str">"cmt">//Set mlbDownXDistance(Variable that stores the initial XDistance i.e. Width of the dashboard) equal to the current XDistance
mlbDownYDistance = YDistance; class=class="str">"cmt">//Set mlbDownYDistance(Variable that stores the initial YDistance i.e. Height of the dashboard) equal to the current YDistance
if(X >= XDistance && X <= XDistance + XSize && Y >= YDistance && Y <= YDistance + YSize) class=class="str">"cmt">//Check if the click was on the dashboard
{
movingState = true; class=class="str">"cmt">//If yes the set movingState to True
}
}
if(movingState)class=class="str">"cmt">//if movingState is true, Update the Dashboard position
{
ChartSetInteger(class="num">0, CHART_MOUSE_SCROLL, class="kw">false);class=class="str">"cmt">//Restrict Chart to be moved by Mouse
ObjectSetInteger(class="num">0, name, OBJPROP_XDISTANCE, mlbDownXDistance + X - mlbDownX);class=class="str">"cmt">//Update XDistance to: mlbDownXDistance + (X - mlbDownX)
ObjectSetInteger(class="num">0, name, OBJPROP_YDISTANCE, mlbDownYDistance + Y - mlbDownY);class=class="str">"cmt">//Update YDistance to: mlbDownYDistance + (Y - mlbDownY)
ChartRedraw(class="num">0); class=class="str">"cmt">//Redraw Chart
}
if(MouseState == class="num">0)class=class="str">"cmt">//Check if MLB is not pressed
{
movingState = class="kw">false;class=class="str">"cmt">//set movingState again to class="kw">false
ChartSetInteger(class="num">0, CHART_MOUSE_SCROLL, true);class=class="str">"cmt">//allow the cahrt to be moved again
}
previousMouseState = MouseState;class=class="str">"cmt">//update the previousMouseState at the end so that we can use it next time and copare it with new value
}