第二十八章 工作事件
本章包含用于处理自定义事件和计时器事件的函数。除了这一组函数之外,还有用于处理预定义事件的特殊功能。
函数 | 功能 |
---|---|
EventSetMillisecondTimer | 启动高精度的计时器事件的生成器,当前图表的周期小于1秒 |
EventSetTimer | 以当前图表的指定周期启动计时器事件生成器(最小周期为 1 秒) |
EventKillTimer | 停止当前图表中的计时器事件时,生成的事件 |
EventChartCustom | 为指定图表生成自定义事件 |
相关参考
图表事件类型
# 28.1 EventSetMillisecondTimer
在EA交易程序 或 指标 中调用该函数,用于在客户端中指定小于一秒间隔的频率生成定时器事件。
bool EventSetMillisecondTimer(
int milliseconds // 毫秒数
);
2
3
参数
milliseconds
[in] 定义定时器事件的频率,单位为:毫秒。
返回值
若成功返回true,否则false。想获得错误代码的详细信息,请调用函数GetLastError()。
注意
此函数是为需要高精度的计时器的情况而设计的。换句话说,定时器事件应当比每秒一次更频繁的发生。如果频率为一秒的常规计时器已经足够,请使用 EventSetTimer().
策略测试器中使用的最小间隔为1000毫秒。通常,当计时器周期减少时,测试时间增加,因为更频繁地调用计时器事件的处理程序。在实时模式下工作时,由于硬件限制,定时器事件在10-16毫秒内生成的时间不超过1次。
一般情况下,这个函数必须从函数OnInit() 或者 从类构造函数中调用。若为处理定时器事件,EA交易必须有OnTimer()函数。
每个EA交易 及 指标使用自己的定时器工作,且仅从那里接收事件。一旦mql5程序停止运行,如果定时器不能通过EventKillTimer()函数创建和禁止,则会被强制销毁。
对于每一个程序只能运行一个定时器。每个mql5程序以及每个图表都有其自己的事件队列,其中放置了所有最近收到的事件。如果 Timer 事件正在队列或者正被处理中,新的Timer事件将不会被放置在mql5程序队列中。
# 28.2 EventSetTimer
该函数应用于客户端,对于 指标 或 EA交易程序,必须以指定的周期生成来自定时器的事件。
bool EventSetTimer(
int seconds // 秒数
);
2
3
参数
seconds
[in] 决定定时器事件发生的频率,单位为:秒。
返回值
若成功返回true,否则false。想获得错误代码的详细信息,请调用函数GetLastError()。
注意
一般情况下,这个函数必须从函数OnInit() 或者 从类构造函数中调用。若为处理定时器事件,EA交易必须有OnTimer()函数。
每个EA交易 及 指标 使用自己的定时器工作,且仅从那里接收事件。一旦mql5程序停止运行,如果定时器不能通过EventKillTimer()函数创建和禁止,则会被强制销毁。
对于每一个程序只能运行一个定时器。每个mql5程序以及每个图表都有其自己的事件队列,其中放置了所有最近收到的事件。如果 Timer 事件正在队列或者正被处理中,新的Timer事件将不会被放置在mql5程序队列中。
# 28.3 EventKillTimer
指定客户端停止从Timer生成的事件。
void EventKillTimer();
返回值
无返回值
注意
特别是,如果函数OnInit()从函数EventSetTimer()调用,该函数必须从函数OnDeinit()调用。如果函数EventSetTimer()在类构造函数中调用,那么该函数也可以从类析构函数调用。
每个EA交易 及 指标 使用自己的定时器工作,且仅从那里接收事件。一旦mql5程序停止运行,如果定时器不能通过EventKillTimer()函数创建和禁止,则会被强制销毁。
# 28.4 EventChartCustom
该函数为指定图表生成自定义事件。
bool EventChartCustom(
long chart_id, // 接收图表事件的标识符
ushort custom_event_id, // 事件标识符
long lparam, // 长整型参量
double dparam, // 双精度型参量
string sparam // 事件的字符串参量
);
2
3
4
5
6
7
参数
chart_id
[in] 图表标识符。 0 意味着当前图表。
custom_event_id
[in] 用户事件ID。这个标识符自动添加到CHARTEVENT_CUSTOM值中且转化成整数型。
lparam
[in] 传递到OnChartEvent函数的 长整型 事件参数。
dparam
[in] 传递到OnChartEvent函数的 双精度型 事件参数。
sparam
[in] 传递到OnChartEvent函数的 字符串型 事件参数。如果字符串超过63个字符,则会被删节。
返回值
如果一个自定义事件已经成功被放置在接收到事件的图表队列事件中,返回 true. 若成功返回true,否则false。调用函数GetLastError() 可获得错误代码的详细信息。
注意
附在指定图表的EA交易或者指标处理使用OnChartEvent函数(int event_id,long& lparam,double& dparam,string& sparam)的事件。
对于每一种事件类型,OnChartEvent()函数的输入参量有事件需要过程的定值。通过这个参量传递的事件和值列在以下表格中。
事件 | id参量值 | lparam 参量值 | dparam 参量值 | sparam 参量值 |
---|---|---|---|---|
击键事件 | CHARTEVENT_KEYDOWN | 击键代码 | 重复计数(用户按住按键的重复击键次数) | 描述键盘按键状态的位掩码的字符串值 |
鼠标事件 (if property CHART_EVENT_MOUSE_MOVE=true is set for the chart) | CHARTEVENT_MOUSE_MOVE | X 坐标 | Y 坐标 | 描述鼠标按键状态的位掩码的字符串值 |
图解物件创建事件 (if CHART_EVENT_OBJECT_CREATE=true is set for the chart) | CHARTEVENT_OBJECT_CREATE | — | — | 创建的图解物件名称 |
通过属性对话框改变物件属性事件 | CHARTEVENT_OBJECT_CHANGE | — | — | 更改的图解物件名称 |
图解物件删除事件 (if CHART_EVENT_OBJECT_DELETE=true is set for the chart) | CHARTEVENT_OBJECT_DELETE | — | — | 删除的图解物件名称 |
图表上鼠标点击事件 | CHARTEVENT_CLICK | X 坐标 | Y 坐标 | — |
附属于图表的图解物件鼠标点击事件 | CHARTEVENT_OBJECT_CLICK | X 坐标 | Y 坐标 | 事件发生的图解物件名称 |
用鼠标拖拽图解物件事件 | CHARTEVENT_OBJECT_DRAG | — | — | 移动的图解物件名称 |
LabelEdit图解物件输入框中完成文本编辑事件 | CHARTEVENT_OBJECT_ENDEDIT | — | — | 完成文本编辑的LabelEdit图解物件名称 |
图表中的更改事件 | CHARTEVENT_CHART_CHANGE | — | — | — |
N号码下用户ID事件 | CHARTEVENT_CUSTOM+N | 通过EventChartCustom() 函数设置的值 | 通过EventChartCustom() 函数设置的值 | 通过 EventChartCustom() 函数设置的值 |
示例:
//+------------------------------------------------------------------+
//| ButtonClickExpert.mq5 |
//| Copyright 2009, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
string buttonID="Button";
string labelID="Info";
int broadcastEventID=5000;
//+------------------------------------------------------------------+
//| 专家初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 创建按钮发送自定义事件
ObjectCreate(0,buttonID,OBJ_BUTTON,0,100,100);
ObjectSetInteger(0,buttonID,OBJPROP_COLOR,clrWhite);
ObjectSetInteger(0,buttonID,OBJPROP_BGCOLOR,clrGray);
ObjectSetInteger(0,buttonID,OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,buttonID,OBJPROP_YDISTANCE,100);
ObjectSetInteger(0,buttonID,OBJPROP_XSIZE,200);
ObjectSetInteger(0,buttonID,OBJPROP_YSIZE,50);
ObjectSetString(0,buttonID,OBJPROP_FONT,"Arial");
ObjectSetString(0,buttonID,OBJPROP_TEXT,"Button");
ObjectSetInteger(0,buttonID,OBJPROP_FONTSIZE,10);
ObjectSetInteger(0,buttonID,OBJPROP_SELECTABLE,0);
//--- 创建标签展示信息
ObjectCreate(0,labelID,OBJ_LABEL,0,100,100);
ObjectSetInteger(0,labelID,OBJPROP_COLOR,clrRed);
ObjectSetInteger(0,labelID,OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,labelID,OBJPROP_YDISTANCE,50);
ObjectSetString(0,labelID,OBJPROP_FONT,"Trebuchet MS");
ObjectSetString(0,labelID,OBJPROP_TEXT,"No information");
ObjectSetInteger(0,labelID,OBJPROP_FONTSIZE,20);
ObjectSetInteger(0,labelID,OBJPROP_SELECTABLE,0);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 专家无法初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
ObjectDelete(0,buttonID);
ObjectDelete(0,labelID);
}
//+------------------------------------------------------------------+
//| 专家订单号函数 |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- 通过按下鼠标键检测事件
if(id==CHARTEVENT_OBJECT_CLICK)
{
string clickedChartObject=sparam;
//--- 如果点击带有按键ID名的物件
if(clickedChartObject==buttonID)
{
//--- 按键状态-按或者不按
bool selected=ObjectGetInteger(0,buttonID,OBJPROP_STATE);
//--- 调试信息日志
Print("Button pressed = ",selected);
int customEventID; // 发送的自定义事件数
string message; // 事件中被发送的信息
//--- 如果按下按键
if(selected)
{
message="Button pressed";
customEventID=CHARTEVENT_CUSTOM+1;
}
else // 不按按键
{
message="Button in not pressed";
customEventID=CHARTEVENT_CUSTOM+999;
}
//--- 发送自定义事件“our”图表
EventChartCustom(0,customEventID-CHARTEVENT_CUSTOM,0,0,message);
///--- 发送信息到所有打开的图表
BroadcastEvent(ChartID(),0,"Broadcast Message");
//--- 调试信息
Print("Sent an event with ID = ",customEventID);
}
ChartRedraw();// 强制重画所有图表物件
}
//--- 检测属于用户事件的事件
if(id>CHARTEVENT_CUSTOM)
{
if(id==broadcastEventID)
{
Print("Got broadcast message from a chart with id = "+lparam);
}
else
{
//--- 阅读事件中的文本信息
string info=sparam;
Print("Handle the user event with the ID = ",id);
//--- 标签中展示信息
ObjectSetString(0,labelID,OBJPROP_TEXT,sparam);
ChartRedraw();// 强制重画所有图表物件
}
}
}
//+------------------------------------------------------------------+
//| 发送广播事件到所有打开的图表 |
//+------------------------------------------------------------------+
void BroadcastEvent(long lparam,double dparam,string sparam)
{
int eventID=broadcastEventID-CHARTEVENT_CUSTOM;
long currChart=ChartFirst();
int i=0;
while(i<CHARTS_MAX) // 打开图表不能多于CHARTS_MAX
{
EventChartCustom(currChart,eventID,lparam,dparam,sparam);
currChart=ChartNext(currChart); // 从上一个接收新图表
if(currChart==-1) break; // 达到图表列表末端
i++; // 不要忘记增加计数器
}
}
//+------------------------------------------------------------------+
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
相关参考
客户端事件 , 事件处理程序函数