資源
在MQL4程序中使用圖形和聲音
MQL4中的程序允許處理聲音和圖形文件:
PlaySound() // 播放聲音文件;
ObjectCreate() // 允許使用圖形對(duì)象OBJ_BITMAP和OBJ_BITMAP_LABEL創(chuàng)建用戶界面蛋叼。
PlaySound()
調(diào)用示例:
//+-------------調(diào)用標(biāo)準(zhǔn)OrderSend()并播放聲音 -----------------+
void OrderSendWithAudio()
{
double 用價(jià)= Ask;
//--- 下1手買單
int ticket= OrderSend(Symbol(),OP_BUY,1,price,3,0,0,"My order",16384,0,clrGreen);
if(ticket<0)
{
Print("發(fā)送買單出現(xiàn)錯(cuò)誤失敗 ,錯(cuò)碼號(hào) #",GetLastError());
//---如果錯(cuò)誤, 從timeout.wav中播放聲音
PlaySound("timeout.wav");
}
else {
Print("訂單安置成功");
//--- 如果成功, 從Ok.wavL中播放聲音
PlaySound("Ok.wav");
}
}
這個(gè)例子展示了如何播放來自文件“Ok”wav”和“timeout妇押。wav’的聲音灿椅,包含在標(biāo)準(zhǔn)終端包中。這些文件位于文件夾terminal_directory\ sound中池充。這里的terminal_directory是一個(gè)文件夾哄辣,MetaTrader 4客戶端就是從這個(gè)文件夾開始啟動(dòng)的睬关。通過mql4程序可以找到終端目錄的位置逮矛,方法如下:
//--- -文件夾矮燎,其中存儲(chǔ)終端數(shù)據(jù)
string terminal_path = TerminalInfoString(terminal_path);
您不僅可以使用文件夾terminal_directory\ sound中的聲音文件,還可以使用位于terminal_data_directory\MQL4中的任何子文件夾中的聲音文件椿疗。您可以通過終端菜單“File”->“Open Data Folder”或使用程序方法找到終端數(shù)據(jù)目錄的位置:
//---文件夾漏峰,其中存儲(chǔ)終端數(shù)據(jù)
string 電腦端路徑= TerminalInfoString(TERMINAL_PATH);
例如,如果演示届榄。wav聲音文件位于terminal_data_directory\MQL4\Files中浅乔,然后調(diào)用PlaySound()應(yīng)該是這樣寫的:
/ / ---播放演示。wav來自文件夾terminal_directory_data\MQL4\Files
PlaySound("\Files\Demo.wav");
請(qǐng)注意铝条,在注釋中靖苇,文件的路徑是使用反斜杠“\”編寫的,在函數(shù)中使用雙反斜杠“\”班缰。
在指定路徑時(shí)贤壁,始終只使用雙反斜杠作為分隔符,因?yàn)樵谔幚沓绦蛟创a中的常量字符串和字符常量時(shí)埠忘,單個(gè)反斜杠是編譯器的控制符號(hào)脾拆。
調(diào)用PlaySound()函數(shù),參數(shù)為空:
//---調(diào)用PlaySound()的空參數(shù)會(huì)停止播放
PlaySound(NULL);
ObjectCreate()
在這個(gè)個(gè)EA的示例莹妒,使用了ObjectCreate()函數(shù)創(chuàng)建一個(gè)圖形標(biāo)簽(OBJ_BITMAP_LABEL)名船。
string 標(biāo)簽名= "currency_label"; // OBJ_BITMAP_LABEL 物件的標(biāo)簽名
string 歐元= "\Images\euro.bmp"; // erminal_data_directory\MQL4\Images\euro.bmp 的所在路徑
string 美元= "\Images\dollar.bmp"; // terminal_data_directory\MQL4\Images\dollar.bmp的所在路徑
//+---------------------------初始化-------------------------+
int OnInit()
{
//--- 創(chuàng)建一個(gè)OBJ_BITMAP_LABEL按鈕,(如果它還沒有被創(chuàng)建)
if(ObjectFind(0,標(biāo)簽名)<0)
{
//--- 嘗試創(chuàng)建OBJ_BITMAP_LABEL物件
bool 己創(chuàng)建= ObjectCreate(0,標(biāo)簽名,OBJ_BITMAP_LABEL,0,0,0);
if(created)
{
//--- 連接按鈕在圖表左上角
ObjectSetInteger(0,l標(biāo)簽名,OBJPROP_CORNER,CORNER_RIGHT_UPPER);
//--- now set up the object properties
ObjectSetInteger(0,標(biāo)簽名,OBJPROP_XDISTANCE,100);
ObjectSetInteger(0,l標(biāo)簽名,OBJPROP_YDISTANCE,50);
//---刷新最后錯(cuò)碼為0 (0表示無錯(cuò))
ResetLastError();
//---下載一個(gè)圖片以提示按鈕現(xiàn)在狀況為"已通過"
bool 設(shè)置成功= ObjectSetString(0,標(biāo)簽名,OBJPROP_BMPFILE,0,euro);
//--- 測(cè)試結(jié)果
if(!設(shè)置成功) {
PrintFormat("從%s下載圖片失敗. 錯(cuò)碼 %d",euro,GetLastError());
}
ResetLastError();
//---下載一個(gè)圖片以提示按鈕現(xiàn)在狀況為"未通過"
設(shè)置成功= ObjectSetString(0,標(biāo)簽名,OBJPROP_BMPFILE,1,dollar);
if(!設(shè)置成功) {
PrintFormat("從%s下載圖片失敗. 錯(cuò)碼 %d",dollar,GetLastError());
}
//--- 發(fā)送一個(gè)命令給圖表 刷新出一個(gè)按鈕,使其在一個(gè)tick上
ChartRedraw(0);
}
else{
//---物件未成功創(chuàng)建的通知
PrintFormat("創(chuàng)建 OBJ_BITMAP_LABEL.物件出錯(cuò),錯(cuò)碼 %d",GetLastError());
}
}
//--- 初始化成功
return(INIT_SUCCEEDED);
}
//+---------------------卸載函數(shù)--------------------------------+
void OnDeinit(const int reason)
{
//--- 從圖表卸載物件
ObjectDelete(0,標(biāo)簽名);
}
本例中:
在OnInit()函數(shù)中,創(chuàng)建和設(shè)置名為currency_label的圖形對(duì)象旨怠。圖形文件的路徑設(shè)置在全局變量歐元和美元中渠驼,分隔符使用了雙重反作用力:
string euro ="\Images\euro.bmp"; // 文件路徑為 terminal_dara_directory\MQL4\Images\euro.bmp
string dollar ="\Images\dollar.bmp"; // 文件路徑為 terminal_dara_directory\MQL4\Images\dollar.bmp
帶有圖形界面的按鈕的大小會(huì)自動(dòng)調(diào)整為圖片的大小。通過鼠標(biāo)左鍵單擊OBJ_BITMAP_LABEL物件 (必須在屬性中選中“禁用選擇”"Disable selection"選項(xiàng))來更改圖像鉴腻。OBJ_BITMAP物件是用同樣的方式創(chuàng)建的——它用于創(chuàng)建具必要的圖像背景迷扇。
OBJPROP_BMPFILE屬性值可以動(dòng)態(tài)更改,該屬性負(fù)責(zé)物件OBJ_BITMAP和OBJ_BITMAP_LABEL的外觀爽哎。這允許為mql4程序創(chuàng)建各種交互式用戶界面蜓席。
在編譯mql4程序時(shí),將資源包含到可執(zhí)行文件中
mql4程序可能需要以圖像和聲音文件的形式提供大量不同的可下載資源课锌。為了避免在MQL4中移動(dòng)可執(zhí)行文件時(shí)需要傳輸所有這些文件瓮床,應(yīng)該使用編譯器的指令:
.#resource path_to_resource_file
.#resource告訴電腦資源在指定的路徑 path_to_resource_file 應(yīng)該包含在可執(zhí)行EX5文件中. 因此,所有必需的圖像和聲音都可以直接定位在EX4文件中, 這樣如果你想在不同的終端上運(yùn)行程序 , 就不需要分別傳輸其中使用的文件 产镐。任何EX4文件都可以包含資源,任何EX4程序都可以使用其他EX4程序的資源踢步。
格式為BMP和WAV的文件在包含到EX4文件之前會(huì)自動(dòng)壓縮癣亚。這表示除了在MQL4中創(chuàng)建完整的程序之外,使用資源還可以在使用圖形和聲音時(shí)減少所需文件的總大小获印,這與MQL4程序編寫的通常方式不同述雾。
資源文件大小不能超過16 Mb。
由編譯器搜索指定的資源
使用命令#resource“,如:
.#resource "<path_to_resource_file>"
常量字符串的長度不能超過63個(gè)字符。
作為資源包含的文件和文件夾名稱 必須是英文的玻孟。
編譯器按以下順序在指定的路徑上搜索資源
如果反斜杠“\”分隔符(寫為“\”)放在路徑的開頭唆缴,它會(huì)搜索相對(duì)于目錄terminal_data_directory\MQL4\的資源,如果沒有反斜杠黍翎,它會(huì)搜索相對(duì)于源文件的位置的資源面徽,在源文件中,資源被寫入匣掸。
資源路徑不能包含子字符串趟紊。\ \ "和":\ \”。
資源包含的例子:
//---正確的資源規(guī)范
.#resource "\Images\euro.bmp" // euro.bmp位于terminal_data_directory\MQL4\Images
.#resource "picture.bmp" // picture.bmp 位于與源文件相同的目錄中
.#resource "Resource\map.bmp" // resource 位于source_file_directory\Resource\map.bmp
//--- 規(guī)格不正確的資源
.#resource ":picture_2.bmp" // 必須不能包含 ":"
.#resource "..\picture_3.bmp" // 必須不能包含 ".."
.#resource "\Files\Images\Folder_First\My_panel\Labels\too_long_path.bmp" // 超過63個(gè)符號(hào)
利用資源
資源名稱
在使用#resource指令聲明資源之后碰酝,它可以用于程序的任何部分霎匈。資源的名稱是其在行首沒有反斜杠的路徑,這將設(shè)置到資源的路徑送爸。要在代碼中使用您自己的資源铛嘱,應(yīng)該在資源名之前添加特殊的“::”符號(hào)。
例子:
//---資源規(guī)范示例及其注釋中的名稱
.#resource "\Images\euro.bmp" // 資源名 - Images\euro.bmp
.#resource "picture.bmp" // 資源名- picture.bmp
.#resource "Resource\map.bmp" // 資源名 - Resource\map.bmp
.#resource "\Files\Pictures\good.bmp" // 資源名 - Files\Pictures\good.bmp
.#resource "\Files\Demo.wav"; // 資源名 - Files\Demo.wav"
.#resource "\Sounds\thrill.wav"; // 資源名 - Sounds\thrill.wav"
...
//---資源的利用
ObjectSetString(0,bitmap_name,OBJPROP_BMPFILE,0,"::Images\euro.bmp");
...
ObjectSetString(0,my_bitmap,OBJPROP_BMPFILE,0,"::picture.bmp");
...
set=ObjectSetString(0,bitmap_label,OBJPROP_BMPFILE,1,"::Files\Pictures\good.bmp");
...
PlaySound("::Files\Demo.wav");
...
PlaySound("::Sounds\thrill.wav");
應(yīng)該注意的是袭厂,當(dāng)將圖像從資源設(shè)置為OBJ_BITMAP和OBJ_BITMAP_LABEL物件時(shí)墨吓,OBJPROP_BMPFILE屬性的值不能手動(dòng)修改。例如嵌器,為了創(chuàng)建OBJ_BITMAP_LABEL肛真,我們使用資源euro。bmp和dollar.bmp爽航。
.#resource "\Images\euro.bmp"; // euro.bmp 位于 terminal_data_directory\MQL4\Images
.#resource "\Images\dollar.bmp"; // dollar.bmp 位于terminal_data_directory\MQL4\Images
當(dāng)查看這個(gè)物件的屬性時(shí)蚓让,我們會(huì)看到屬性位圖文件(On)和位圖文件(Off)都變暗了,無法手動(dòng)更改:
使用其他mql4程序的資源
使用資源還有另一個(gè)好處——在任何MQL4程序中讥珍,都可以使用另一個(gè)EX4文件的資源历极。因此,一個(gè)EX4文件中的資源可以在許多其他mql4程序中使用衷佃。
為了使用來自另一個(gè)文件的資源名趟卸,應(yīng)該將其指定為::。例如氏义,假設(shè)Draw_Triangles_Script锄列。mq5腳本包含一個(gè)資源到一個(gè)圖像在the file triangle.bmp:
.#resource "\Files\triangle.bmp"
然后它的名字(用于腳本本身)看起來就像 "Files\triangle.bmp"。為了使用它惯悠,“::”應(yīng)該添加到資源名中
//--- 使用腳本中的資源
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,"::Files\triangle.bmp");
為了從另一個(gè)程序中使用相同的資源邻邮,例如從專家顧問中,我們需要向資源名添加到EX4文件的路徑(相對(duì)于terminal_data_directory\MQL4\以及腳本的EX4文件的名稱——Draw_Triangles_Script.ex4)克婶。假設(shè)腳本位于標(biāo)準(zhǔn)文件夾terminal_data_directory\MQL4\Scripts\ Scripts中筒严,那么調(diào)用應(yīng)該這樣寫:
//---使用EA中腳本中的資源
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,"\Scripts\Draw_Triangles_Script.ex4::Files\triangle.bmp");
如果從另一個(gè)EX4調(diào)用資源時(shí)沒有指定到可執(zhí)行文件的路徑丹泉,則在包含調(diào)用資源的程序的同一個(gè)文件夾中搜索可執(zhí)行文件。這意味著如果一個(gè)EA從Draw_Triangles_Script調(diào)用一個(gè)資源鸭蛙。ex4沒有指定路徑摹恨,如下:
//---在EA中調(diào)用腳本資源,而不指定路徑
ObjectSetString(0,my_bitmap_name,OBJPROP_BMPFILE,0,"Draw_Triangles_Script.ex4::Files\triangle.bmp");
然后在文件夾terminal_data_directory\MQL4\Experts\ \專家\ \中搜索文件娶视,如果Expert Advisor位于terminal_data_directory\MQL4\Experts\ \上晒哄。
使用作為資源包含的自定義指標(biāo)
MQL4應(yīng)用程序的操作可能需要一個(gè)或多個(gè)自定義指標(biāo)。所有這些都可以包含在可執(zhí)行的MQL5程序的代碼中歇万。將指標(biāo)包含在資源中可以簡(jiǎn)化應(yīng)用程序的分布揩晴。
下面是包含和使用SampleIndicator的例子。ex4自定義指標(biāo)位于terminal_data_folder\MQL4\指標(biāo)中
//+------------------------------------------------------------------+
//| SampleEA.mq4 |
//| Copyright 2013, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
.#resource "\Indicators\SampleIndicator.ex4"
.#property strict
//+----------------------初始化-----------------------------+
int OnInit()
{
//--- 獲取自定義指標(biāo)值
double value= iCustom(_Symbol,_Period,"::Indicators\SampleIndicator.ex4",0,0);
PrintFormat("Indicator: iCustom value=%f",value);
//--- ...
return(INIT_SUCCEEDED);
}
當(dāng)OnInit()函數(shù)中的自定義指示器創(chuàng)建一個(gè)或多個(gè)自身副本時(shí)贪磺,需要特別考慮這種情況硫兰。請(qǐng)記住,資源應(yīng)該按照以下方式指定:< path_EX4_file_name>::寒锚。
例如劫映,if SampleIndicator。樣品包括ex4指示劑刹前。ex4 Expert Advisor作為資源泳赋,在自定義指示器的初始化函數(shù)中調(diào)用iCustom()時(shí)指定的路徑如下所示:“\Expert \SampleEA.ex4::Indicators\SampleIndicator.ex4”。顯式設(shè)置此路徑時(shí)喇喉,SampleIndicator祖今。ex4定制指示器嚴(yán)格連接到SampleEA。喪失獨(dú)立工作的能力拣技。
可以使用GetRelativeProgramPath()函數(shù)接收到自己的路徑千诬。其用法示例如下:
//+------------------------------------------------------------------+
//| SampleIndicator.mq4 |
//| Copyright 2013, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
.#property indicator_separate_window
//+--------------------------初始化-----------------------+
int OnInit()
{
//---提供鏈接到自身的錯(cuò)誤方式
//--- string path= "\Experts\SampleEA.ex4::Indicators\SampleIndicator.ex4";
//---接收鏈接的正確方式
string path= GetRelativeProgramPath();
//--- 獲得指標(biāo)值
double value= iCustom(_Symbol,_Period,path,0,0);
PrintFormat("Path=%s, iCustom value=%f",path,value);
//---
return(INIT_SUCCEEDED);
}
///....
//+--------------------獲得相關(guān)程序路徑------------------------+
string GetRelativeProgramPath()
{
int pos2;
//--- 獲得應(yīng)用程序的完全路徑
string path=MQLInfoString(MQL_PROGRAM_PATH);
//---查找“\MQL4\”子字符串的位置
int pos =StringFind(path,"\MQL4\");
//---子字符串未找到-錯(cuò)誤
if(pos<0)
return(NULL);
//---跳過“\ MQL4”目錄
pos+=5;
//---跳過額外的“\”符號(hào)
while(StringGetCharacter(path,pos+1)=='\')
pos++;
//---如果這是一個(gè)資源,則返回相對(duì)于MQL5目錄的路徑
if(StringFind(path,"::",pos)>=0)
return(StringSubstr(path,pos));
//---為第一個(gè)MQL4子目錄查找分隔符(例如膏斤,MQL4\指標(biāo))
//---如果沒有找到徐绑,返回相對(duì)于MQL4目錄的路徑
if((pos2=StringFind(path,"\",pos+1))<0)
return(StringSubstr(path,pos));
//---返回相對(duì)于子目錄的路徑(例如,MQL4\指標(biāo))
return(StringSubstr(path,pos2+1));
}
//+------------------自定義指標(biāo)迭代函數(shù)----------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double& price[])
{
//---為下一次調(diào)用返回prev_computed值
return(rates_total);
}