| 目錄簡介盡管算法交易的發(fā)展非?;钴S,很多交易者還是傾向于人工交易。然而,很難完全避免一些重復(fù)性操作的自動化。 本文展示了一個用于人工交易的多交易品種信號 EA 交易的開發(fā),作為例子,讓我們使用來自終端標(biāo)準(zhǔn)發(fā)布的 隨機(jī)振蕩指標(biāo)(Stochastic)的信號。您可以使用這里的代碼來開發(fā)您自己的含有圖形界面(GUI)的 EA 交易:可以在其中包含任何其他指標(biāo),也可以根據(jù)某些計算結(jié)果來做交易決定。 對于執(zhí)行其它交易者訂單的人來說,本文也是有用的,可以用于向客戶演示一些技術(shù)任務(wù)的實例。這個例子可以在您準(zhǔn)備開發(fā)含有 GUI 的程序需求規(guī)格的時候節(jié)約您的時間。 這里是本文詳細(xì)討論的一些問題:  
 本文將分為兩部分發(fā)表, 在這篇文章中,我們會探討開發(fā)面板,而下一篇則描述使用功能來填補(bǔ)它。  GUI 元件我們將要開發(fā)一個含有 GUI 的 EA 交易,這可以使用戶和程序之間實現(xiàn)交互,并且可以把數(shù)據(jù)可視化??梢允褂脴?biāo)準(zhǔn)庫的功能來創(chuàng)建 GUI,但是在我的例子中,它是基于 EasyAndFast 開發(fā)庫來實現(xiàn)的。它的功能很豐富,可以集中精力于程序的功能方面,而不用被圖形部分的優(yōu)化來分神。 首先,讓我們規(guī)劃一下大致的 GUI 結(jié)構(gòu),下面的圖表顯示,GUI 窗口含有兩個頁面,下面的列表顯示了它們要有的功能。這是一個簡化過的例子,客戶和開發(fā)者可以在討論的時候更加詳細(xì)地合作。 
 圖 1. 含有注釋的 GUI 總體視圖 可能會有很多的 GUI 控件,所以,讓我們首先以分級表單方式列出它們: 
 在主程序類 (CProgram) 中, 聲明方法類以上列出的元件類的實例。用于創(chuàng)建元件的方法的代碼位于單獨(dú)的文件中,使用 MQL 程序類包含在文件中: // ------------------------------------------------------------------ 
//| 應(yīng)用程序開發(fā)類                                                      |
// ------------------------------------------------------------------ 
class CProgram : public CWndEvents
  {
private:
   //--- 窗口
   CWindow           m_window1;
   //--- 狀態(tài)條
   CStatusBar        m_status_bar;
   //--- 頁面
   CTabs             m_tabs1;
   //--- 輸入欄位
   CTextEdit         m_symb_filter;
   CTextEdit         m_lot;
   CTextEdit         m_up_level;
   CTextEdit         m_down_level;
   CTextEdit         m_chart_scale;
   //--- 按鈕
   CButton           m_request;
   CButton           m_chart_shift;
   CButton           m_buy;
   CButton           m_sell;
   CButton           m_close_all;
   //--- 組合框
   CComboBox         m_timeframes;
   //--- 復(fù)選框
   CCheckBox         m_date_scale;
   CCheckBox         m_price_scale;
   CCheckBox         m_show_indicator;
   //--- 表格
   CTable            m_table_positions;
   CTable            m_table_symb;
   //--- 標(biāo)準(zhǔn)圖表
   CStandardChart    m_sub_chart1;
   //--- 進(jìn)度條
   CProgressBar      m_progress_bar;
   //---
public:
   //--- 創(chuàng)建 GUI
   bool              CreateGUI(void);
   //---
private:
   //--- 表單
   bool              CreateWindow(const string text);
   //--- 狀態(tài)條
   bool              CreateStatusBar(const int x_gap,const int y_gap);
   //--- 頁面
   bool              CreateTabs1(const int x_gap,const int y_gap);
   //--- 輸入欄位
   bool              CreateSymbFilter(const int x_gap,const int y_gap,const string text);
   bool              CreateLot(const int x_gap,const int y_gap,const string text);
   bool              CreateUpLevel(const int x_gap,const int y_gap,const string text);
   bool              CreateDownLevel(const int x_gap,const int y_gap,const string text);
   bool              CreateChartScale(const int x_gap,const int y_gap,const string text);
   //--- 按鈕
   bool              CreateRequest(const int x_gap,const int y_gap,const string text);
   bool              CreateChartShift(const int x_gap,const int y_gap,const string text);
   bool              CreateBuy(const int x_gap,const int y_gap,const string text);
   bool              CreateSell(const int x_gap,const int y_gap,const string text);
   bool              CreateCloseAll(const int x_gap,const int y_gap,const string text);
   //--- 組合框
   bool              CreateComboBoxTF(const int x_gap,const int y_gap,const string text);
   //--- 復(fù)選框
   bool              CreateDateScale(const int x_gap,const int y_gap,const string text);
   bool              CreatePriceScale(const int x_gap,const int y_gap,const string text);
   bool              CreateShowIndicator(const int x_gap,const int y_gap,const string text);
   //--- 表格
   bool              CreatePositionsTable(const int x_gap,const int y_gap);
   bool              CreateSymbolsTable(const int x_gap,const int y_gap);
   //--- 標(biāo)準(zhǔn)圖表
   bool              CreateSubChart1(const int x_gap,const int y_gap);
   //--- 進(jìn)度條
   bool              CreateProgressBar(const int x_gap,const int y_gap,const string text);
  };
// ------------------------------------------------------------------ 
//| 用于創(chuàng)建控件的代碼                                                   |
// ------------------------------------------------------------------ 
#include 'CreateGUI.mqh'
// ------------------------------------------------------------------ 
 下一步,讓我們著重于 GUI 的組裝,用于創(chuàng)建它的元件以及屬性的方法。 組裝 GUI在程序 GUI 的開發(fā)中,我們將使用10類 GUI 元件。 
 在這個列表的一些種類中,我們會需要多個元件,所以我們每個組只會討論一個元件,讓我們使用相同的順序來探討創(chuàng)建它們的方法。 用于控件的表單下面是用于創(chuàng)建容納所有其他元件的表單的方法,首先,我們需要把表單加到程序 GUI 元件列表中,為此,調(diào)用 CWndContainer::AddWindow() 方法, 傳入 CWindow 類型的元件對象。然后,在創(chuàng)建表單之前設(shè)置它的屬性,我們要設(shè)置以下屬性 (和下面列表中順序相同): 
 在設(shè)置完屬性之后,調(diào)用創(chuàng)建表單的方法 — CWindow::CreateWindow() 并傳給它: 
 // ------------------------------------------------------------------ //| 創(chuàng)建控件表單 | // ------------------------------------------------------------------ bool CProgram::CreateWindow(const string caption_text) { //--- 把窗口指針加到窗口數(shù)組中 CWndContainer::AddWindow(m_window1); //--- 屬性 m_window1.XSize(750); m_window1.YSize(450); m_window1.FontSize(9); m_window1.IsMovable(true); m_window1.ResizeMode(true); m_window1.CloseButtonIsUsed(true); m_window1.CollapseButtonIsUsed(true); m_window1.TooltipsButtonIsUsed(true); m_window1.FullscreenButtonIsUsed(true); //--- 設(shè)置工具提示 m_window1.GetCloseButtonPointer().Tooltip('Close'); m_window1.GetTooltipButtonPointer().Tooltip('Tooltips'); m_window1.GetFullscreenButtonPointer().Tooltip('Fullscreen'); m_window1.GetCollapseButtonPointer().Tooltip('Collapse/Expand'); //--- 創(chuàng)建表單 if(!m_window1.CreateWindow(m_chart_id,m_subwin,caption_text,1,1)) return(false); //--- return(true); } 推薦每次在您加上新的 GUI 元件的時候都編譯程序并檢查結(jié)果。 
 圖 2. 用于控件的表單 所有中間過程的結(jié)果都顯示如下. 狀態(tài)條用于根據(jù)指定的主元件來創(chuàng)建狀態(tài)條的方法的代碼,也用于計算其中元件的邊界以及它們的大小,這在開發(fā)應(yīng)用程序的時候可以節(jié)約時間: 一組相關(guān)元件可以只根據(jù)主元件來改變它們的坐標(biāo)。為了綁定元件,它的指針要傳給 CElement::MainPointer() 方法。在本例中,我們把狀態(tài)條綁定到表單,所以, 要把表單對象傳給這個方法。 然后,再設(shè)置狀態(tài)條的屬性。它包含了三個部分,向用戶顯示信息。 
 在設(shè)置了屬性之后,再創(chuàng)建元件。現(xiàn)在,它已經(jīng)可以工作了,我們可以在運(yùn)行時刻改變它分段中的文字,在我們的例子中,第一個分段的文字設(shè)為 'For Help, press F1(如需取得幫助,按F1)' . 在方法的最后,要確保把所創(chuàng)建元件的指針保存到總的 GUI 元件列表中,為此,要調(diào)用 CWndContainer::AddToElementsArray() 方法,并且把表單索引和元件對象傳給它。因為我們只有一個表單,它的索引將是0。 // ------------------------------------------------------------------ 
//| 創(chuàng)建狀態(tài)條                                                         |
// ------------------------------------------------------------------ 
bool CProgram::CreateStatusBar(const int x_gap,const int y_gap)
  {
#define STATUS_LABELS_TOTAL 3
//--- 保存窗口指針
   m_status_bar.MainPointer(m_window1);
//--- 屬性
   m_status_bar.AutoXResizeMode(true);
   m_status_bar.AutoXResizeRightOffset(1);
   m_status_bar.AnchorBottomWindowSide(true);
//--- 設(shè)置分段的數(shù)量以及它們的屬性
   int width[STATUS_LABELS_TOTAL]={0,200,110};
   for(int i=0; i<STATUS_LABELS_TOTAL; i  )
      m_status_bar.AddItem(width[i]);
//--- 創(chuàng)建控件
   if(!m_status_bar.CreateStatusBar(x_gap,y_gap))
      return(false);
//--- 在狀態(tài)條分段中設(shè)置文字
   m_status_bar.SetValue(0,'For Help, press F1');
//--- 把對象加到總的對象組數(shù)組中
   CWndContainer::AddToElementsArray(0,m_status_bar);
   return(true);
  }
 EasyAndFast 開發(fā)庫中其余元件的創(chuàng)建也是基于相同的原則,所以,我們只會討論我們 EA 中需要使用的可自定義的屬性。 
 圖 3. 加上狀態(tài)條 頁面組讓我們在創(chuàng)建頁面組的方法中設(shè)置以下的元件屬性: 
 下面是方法的代碼: // ------------------------------------------------------------------ //| 創(chuàng)建頁面組 1 | // ------------------------------------------------------------------ bool CProgram::CreateTabs1(const int x_gap,const int y_gap) { #define TABS1_TOTAL 2 //--- 保存指向主元件的指針 m_tabs1.MainPointer(m_window1); //--- 屬性 m_tabs1.IsCenterText(true); m_tabs1.PositionMode(TABS_TOP); m_tabs1.AutoXResizeMode(true); m_tabs1.AutoYResizeMode(true); m_tabs1.AutoXResizeRightOffset(3); m_tabs1.AutoYResizeBottomOffset(25); //--- 使用指定的屬性增加頁面 string tabs_names[TABS1_TOTAL]={'Trade','Positions'}; for(int i=0; i<TABS1_TOTAL; i ) m_tabs1.AddTab(tabs_names[i],100); //--- 創(chuàng)建控件 if(!m_tabs1.CreateTabs(x_gap,y_gap)) return(false); //--- 把對象加到總的對象組數(shù)組中 CWndContainer::AddToElementsArray(0,m_tabs1); return(true); } 
 圖 4. 加上頁面組 輸入欄位例如,讓我們探討一個輸入欄位,用戶可以從一個表格中的交易品種列表中指定貨幣和/或貨幣對。它的主元件是一個頁面組,我們在此需要指定輸入欄位應(yīng)該顯示的頁面,為此, 要調(diào)用 CTabs::AddToElementsArray() 方法,并向它傳遞頁面的索引和附加的元件對象。 現(xiàn)在,讓我們探討這個輸入欄位的屬性。 
 CTextEdit 類型的元件包含了幾種其他元件,所以,如果您需要改變它的屬性,您可以得到它們的指針,我們必須修改一些文本輸入欄位 (CTextBox)的一些屬性。讓我們按照下面代碼列表中實現(xiàn)的相同順序來討論它們: 
 輸入欄位的復(fù)選框默認(rèn)是啟用的. 為此,要在創(chuàng)建元件時立即激活它. // ------------------------------------------------------------------ 
//| 創(chuàng)建一個復(fù)選框,帶有 'Symbols filter' 輸入欄位                         |
// ------------------------------------------------------------------ 
bool CProgram::CreateSymbolsFilter(const int x_gap,const int y_gap,const string text)
  {
//--- 保存指向主元件的指針
   m_symb_filter.MainPointer(m_tabs1);
//---為頁面做保留
   m_tabs1.AddToElementsArray(0,m_symb_filter);
//--- 屬性
   m_symb_filter.SetValue('USD'); // 'EUR,USD' 'EURUSD,GBPUSD' 'EURUSD,GBPUSD,AUDUSD,NZDUSD,USDCHF'
   m_symb_filter.CheckBoxMode(true);
   m_symb_filter.AutoXResizeMode(true);
   m_symb_filter.AutoXResizeRightOffset(90);
   m_symb_filter.GetTextBoxPointer().XGap(100);
   m_symb_filter.GetTextBoxPointer().AutoXResizeMode(true);
   m_symb_filter.GetTextBoxPointer().AutoSelectionMode(true);
   m_symb_filter.GetTextBoxPointer().DefaultText('Example: EURUSD,GBP,NOK');
//--- 創(chuàng)建控件
   if(!m_symb_filter.CreateTextEdit(text,x_gap,y_gap))
      return(false);
//--- 啟用復(fù)選框
   m_symb_filter.IsPressed(true);
//--- 把對象加到對象組的統(tǒng)一數(shù)組中
   CWndContainer::AddToElementsArray(0,m_symb_filter);
   return(true);
  }
 除了文本輸入欄位,在 GUI 中還有數(shù)字式輸入的。例如, Lot 輸入欄位 (用于建立倉位的交易量). 這種類型的其他元件應(yīng)當(dāng)是輸入欄位.  
 這里是方法的代碼: // ------------------------------------------------------------------ //| 創(chuàng)建 'Lot' 輸入欄位 | // ------------------------------------------------------------------ bool CProgram::CreateLot(const int x_gap,const int y_gap,const string text) { //--- 保存指向主元件的指針 m_lot.MainPointer(m_tabs1); //---為頁面做保留 m_tabs1.AddToElementsArray(0,m_lot); //--- 屬性 m_lot.XSize(80); m_lot.MaxValue(1000); m_lot.MinValue(0.01); m_lot.StepValue(0.01); m_lot.SetDigits(2); m_lot.SpinEditMode(true); m_lot.SetValue((string)0.1); m_lot.GetTextBoxPointer().XSize(50); m_lot.GetTextBoxPointer().AutoSelectionMode(true); m_lot.GetTextBoxPointer().AnchorRightWindowSide(true); //--- 創(chuàng)建控件 if(!m_lot.CreateTextEdit(text,x_gap,y_gap)) return(false); //--- 把對象加到對象組的統(tǒng)一數(shù)組中 CWndContainer::AddToElementsArray(0,m_lot); return(true); } 
 圖 5. 增加輸入欄位 圖片看起來不是很有邏輯,但是當(dāng)您加上其它元件的時候,一切就變得合理了。 按鈕讓我們在 EA 的 GUI 上加上幾個按鈕,我們將通過一個按鈕探討主要的屬性:用于開啟賣出倉位的按鈕。 
 對于買入按鈕,屬性的變化是相同的,除了指定的背景顏色。 // ------------------------------------------------------------------ 
//| 創(chuàng)建 '賣出' 按鈕                                         |
// ------------------------------------------------------------------ 
bool CProgram::CreateSell(const int x_gap,const int y_gap,const string text)
  {
//--- 保存指向主元件的指針
   m_sell.MainPointer(m_tabs1);
//---為頁面做保留
   m_tabs1.AddToElementsArray(0,m_sell);
//--- 屬性
   m_sell.XSize(80);
   m_sell.IsCenterText(true);
   m_sell.BackColor(C'255,51,51');
   m_sell.BackColorHover(C'255,100,100');
   m_sell.BackColorPressed(C'195,0,0');
   m_sell.LabelColor(clrWhite);
   m_sell.LabelColorHover(clrWhite);
   m_sell.LabelColorPressed(clrWhite);
   m_sell.BorderColor(clrBlack);
   m_sell.BorderColorHover(clrBlack);
   m_sell.BorderColorPressed(clrBlack);
//--- 創(chuàng)建控件
   if(!m_sell.CreateButton(text,x_gap,y_gap))
      return(false);
//--- 把元件指針加到數(shù)據(jù)庫中
   CWndContainer::AddToElementsArray(0,m_sell);
   return(true);
  }
 
 圖 6. 增加按鈕 帶有下拉列表的組合框為了改變時段,讓我們制作一個含有下拉列表的組合框。定義它的配置的屬性. 
 給每個列表項目賦值,有些屬性是通過指針隨后賦值的. 
 下面是用于創(chuàng)建組合框方法的代碼: // ------------------------------------------------------------------ //| 創(chuàng)建用于生成時段的組合框 | // ------------------------------------------------------------------ bool CProgram::CreateComboBoxTF(const int x_gap,const int y_gap,const string text) { //--- 列表項目總數(shù) #define ITEMS_TOTAL2 21 //--- 傳遞面板對象 m_timeframes.MainPointer(m_tabs1); //--- 錨點設(shè)向頁面 m_tabs1.AddToElementsArray(0,m_timeframes); //--- 屬性 m_timeframes.XSize(115); m_timeframes.ItemsTotal(ITEMS_TOTAL2); m_timeframes.AnchorRightWindowSide(true); m_timeframes.GetButtonPointer().XSize(50); m_timeframes.GetButtonPointer().AnchorRightWindowSide(true); //--- 把項目值保存到組合框列表 string items_text[ITEMS_TOTAL2]={'M1','M2','M3','M4','M5','M6','M10','M12','M15','M20','M30','H1','H2','H3','H4','H6','H8','H12','D1','W1','MN'}; for(int i=0; i<ITEMS_TOTAL2; i ) m_timeframes.SetValue(i,items_text[i]); //--- 取得列表指針 CListView *lv=m_timeframes.GetListViewPointer(); //--- 設(shè)置列表屬性 lv.LightsHover(true); lv.SelectItem(18); //--- 創(chuàng)建控件 if(!m_timeframes.CreateComboBox(text,x_gap,y_gap)) return(false); //--- 把元件指針加到數(shù)據(jù)庫中 CWndContainer::AddToElementsArray(0,m_timeframes); return(true); } 
 圖 7. 加上組合框 復(fù)選框復(fù)選框是最簡單的元件,只需要為它指定兩個屬性。 
 在創(chuàng)建元件之后,我們可以編程啟用復(fù)選框。 // ------------------------------------------------------------------ 
//| 創(chuàng)建 'Date scale' 復(fù)選框                                           |
// ------------------------------------------------------------------ 
bool CProgram::CreateDateScale(const int x_gap,const int y_gap,const string text)
  {
//--- 保存窗口指針
   m_date_scale.MainPointer(m_tabs1);
//---為頁面做保留
   m_tabs1.AddToElementsArray(0,m_date_scale);
//--- 屬性
   m_date_scale.XSize(70);
   m_date_scale.AnchorRightWindowSide(true);
//--- 創(chuàng)建控件
   if(!m_date_scale.CreateCheckBox(text,x_gap,y_gap))
      return(false);
//--- 啟用復(fù)選框
   m_date_scale.IsPressed(true);
//--- 把對象加到對象組的統(tǒng)一數(shù)組中
   CWndContainer::AddToElementsArray(0,m_date_scale);
   return(true);
  }
 
 圖 8. 加上復(fù)選框 表格GUI 含有兩個表格,讓我們探討可視化交易品種列表和開啟倉位信號的那個表格,它位于第一個頁面。首先,聲明和初始化用于設(shè)置表格屬性的數(shù)組,設(shè)置以下屬性.  
 創(chuàng)建表格后需要設(shè)置的表頭文字: // ------------------------------------------------------------------ //| 創(chuàng)建交易品種表格 | // ------------------------------------------------------------------ bool CProgram::CreateSymbolsTable(const int x_gap,const int y_gap) { #define COLUMNS1_TOTAL 2 #define ROWS1_TOTAL 1 //--- 保存指向主元件的指針 m_table_symb.MainPointer(m_tabs1); //---為頁面做保留 m_tabs1.AddToElementsArray(0,m_table_symb); //--- 列的寬度數(shù)組 int width[COLUMNS1_TOTAL]={95,58}; //--- 列中文字對齊方式的數(shù)組 ENUM_ALIGN_MODE align[COLUMNS1_TOTAL]={ALIGN_LEFT,ALIGN_RIGHT}; //--- X軸方向上文字縮進(jìn)數(shù)組 int text_x_offset[COLUMNS1_TOTAL]={5,5}; //--- 屬性 m_table_symb.XSize(168); m_table_symb.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL); m_table_symb.ColumnsWidth(width); m_table_symb.TextAlign(align); m_table_symb.TextXOffset(text_x_offset); m_table_symb.ShowHeaders(true); m_table_symb.SelectableRow(true); m_table_symb.ColumnResizeMode(true); m_table_symb.IsZebraFormatRows(clrWhiteSmoke); m_table_symb.AutoYResizeMode(true); m_table_symb.AutoYResizeBottomOffset(2); //--- 創(chuàng)建控件 if(!m_table_symb.CreateTable(x_gap,y_gap)) return(false); //--- 設(shè)置表頭名稱 m_table_symb.SetHeaderText(0,'Symbol'); m_table_symb.SetHeaderText(1,'Values'); //--- 把對象加到對象組的統(tǒng)一數(shù)組中 CWndContainer::AddToElementsArray(0,m_table_symb); return(true); } 第二個表格顯示了開啟倉位的一些屬性,有10列顯示下面的數(shù)據(jù)。 
 下面這些屬性在第二個表格中應(yīng)當(dāng)另外配置. 
 第一列中圖片單元將作為按鈕,通過點擊您可以關(guān)閉一個倉位,或者指定交易品種是對沖狀況可以關(guān)閉所有這些倉位。 // ------------------------------------------------------------------ 
//| 創(chuàng)建倉位表格                                                       |
// ------------------------------------------------------------------ 
bool CProgram::CreatePositionsTable(const int x_gap,const int y_gap)
  {
...
//--- 屬性
   m_table_positions.TableSize(COLUMNS2_TOTAL,ROWS2_TOTAL);
   m_table_positions.ColumnsWidth(width);
   m_table_positions.TextAlign(align);
   m_table_positions.TextXOffset(text_x_offset);
   m_table_positions.ImageXOffset(image_x_offset);
   m_table_positions.ImageYOffset(image_y_offset);
   m_table_positions.ShowHeaders(true);
   m_table_positions.IsSortMode(true);
   m_table_positions.SelectableRow(true);
   m_table_positions.ColumnResizeMode(true);
   m_table_positions.IsZebraFormatRows(clrWhiteSmoke);
   m_table_positions.AutoXResizeMode(true);
   m_table_positions.AutoYResizeMode(true);
   m_table_positions.AutoXResizeRightOffset(2);
   m_table_positions.AutoYResizeBottomOffset(2);
...
   return(true);
  }
 
 圖 9. 在第一個頁面上加上表格 
 圖 10. 在第二個頁面上加上表格 操作表格的詳細(xì)內(nèi)容在主程序文件 (CProgram) 中,會在下面文章部分中討論。 標(biāo)準(zhǔn)圖表CStandardChart 類型的元件是用于根據(jù)交易品種可視化數(shù)據(jù)的。默認(rèn)顯示 EURUSD D1它含有下面的特性: 
 如有必要,可以創(chuàng)建一個水平方向上的圖表數(shù)組,為此, 要使用 CStandardChart::AddSubChart() 方法,并且傳遞交易品種和時段作為參數(shù)。但是,在本例中,我們只需要一個圖表,而交易品種和時段的切換是使用其它控件切換的。 // ------------------------------------------------------------------ //| 創(chuàng)建標(biāo)準(zhǔn)圖表 1 | // ------------------------------------------------------------------ bool CProgram::CreateSubChart1(const int x_gap,const int y_gap) { //--- 保存窗口指針 m_sub_chart1.MainPointer(m_tabs1); //--- 為第一個頁面保留 m_tabs1.AddToElementsArray(0,m_sub_chart1); //--- 屬性 m_sub_chart1.XScrollMode(true); m_sub_chart1.AutoXResizeMode(true); m_sub_chart1.AutoYResizeMode(true); m_sub_chart1.AutoXResizeRightOffset(125); m_sub_chart1.AutoYResizeBottomOffset(2); //--- 加上圖表 m_sub_chart1.AddSubChart('EURUSD',PERIOD_D1); //--- 創(chuàng)建控件 if(!m_sub_chart1.CreateStandardChart(x_gap,y_gap)) return(false); //--- 把對象加到對象組的通用數(shù)組中 CWndContainer::AddToElementsArray(0,m_sub_chart1); return(true); } 
 圖 11. 加上圖表 進(jìn)度條進(jìn)度條可以使用戶了解到程序現(xiàn)在正在做什么,所以讓我們把它加到 GUI 上。下面是我們例子中的屬性 (與代碼中的順序相同).  
 使用進(jìn)度條的實例在下面顯示. // ------------------------------------------------------------------ 
//| 創(chuàng)建進(jìn)度條                                                         |
// ------------------------------------------------------------------ 
bool CProgram::CreateProgressBar(const int x_gap,const int y_gap,const string text)
  {
//--- 保存指向主元件的指針
   m_progress_bar.MainPointer(m_status_bar);
//--- 屬性
   m_progress_bar.YSize(17);
   m_progress_bar.BarYSize(14);
   m_progress_bar.BarXGap(0);
   m_progress_bar.BarYGap(1);
   m_progress_bar.LabelXGap(5);
   m_progress_bar.LabelYGap(2);
   m_progress_bar.PercentXGap(5);
   m_progress_bar.PercentYGap(2);
   m_progress_bar.IsDropdown(true);
   m_progress_bar.Font('Consolas');
   m_progress_bar.BorderColor(clrSilver);
   m_progress_bar.IndicatorBackColor(clrWhiteSmoke);
   m_progress_bar.IndicatorColor(clrLightGreen);
   m_progress_bar.AutoXResizeMode(true);
   m_progress_bar.AutoXResizeRightOffset(2);
//--- 創(chuàng)建元件
   if(!m_progress_bar.CreateProgressBar(text,x_gap,y_gap))
      return(false);
//--- 把元件指針加到數(shù)據(jù)庫中
   CWndContainer::AddToElementsArray(0,m_progress_bar);
   return(true);
  }
 我們已經(jīng)描述了在我們 EA 的 GUI 中所有的控件,現(xiàn)在,這只是一個圖形化的外殼,下一步,我們將會開發(fā)所有所需的方法,來使得一切都按照最初的想法來工作。 EasyAndFast 開發(fā)庫的更新在 EasyAndFast 開發(fā)庫中, CTable::SortData() 公有方法已經(jīng)在 CTable 類中修改過了,現(xiàn)在,對第二個參數(shù),您可以指定 表格的排序方向 (可選參數(shù))。之前, CTable::SortData() 方法會開始根據(jù)當(dāng)前方向相反的方向開始排序。另外,還加上了用于取得 當(dāng)前排序方向和排序列的索引的方法。如果表格已經(jīng)由用戶手動排序過 (通過點擊一個表頭), 而表格中的數(shù)據(jù)沒有使用相同順序更新,可以在得到當(dāng)前排序方向后恢復(fù)它。 // ------------------------------------------------------------------ //| 用于創(chuàng)建繪制表格的類 | // ------------------------------------------------------------------ class CTable : public CElement { public: ... //--- 根據(jù)指定列排序數(shù)據(jù) void SortData(const uint column_index=0,const int direction=WRONG_VALUE); //--- (1) 當(dāng)前排序方向, (2) 排序數(shù)組索引 int IsSortDirection(void) const { return(m_last_sort_direction); } int IsSortedColumnIndex(void) const { return(m_is_sorted_column_index); } ... }; // ------------------------------------------------------------------ //| 根據(jù)指定列排序數(shù)據(jù) | // ------------------------------------------------------------------ void CTable::SortData(const uint column_index=0,const int direction=WRONG_VALUE) { //--- 如果超出表格邊界就退出 if(column_index>=m_columns_total) return; //--- 開始排序的索引 uint first_index=0; //--- 最后的索引 uint last_index=m_rows_total-1; //--- 方向不是由用戶管理的 if(direction==WRONG_VALUE) { //--- 第一次,根據(jù)升序排序,隨后每次按照相反方向排序 if(m_is_sorted_column_index==WRONG_VALUE || column_index!=m_is_sorted_column_index || m_last_sort_direction==SORT_DESCEND) m_last_sort_direction=SORT_ASCEND; else m_last_sort_direction=SORT_DESCEND; } else { m_last_sort_direction=(ENUM_SORT_MODE)direction; } //--- 記住最后一次排序的列的索引 m_is_sorted_column_index=(int)column_index; //--- Sorting QuickSort(first_index,last_index,column_index,m_last_sort_direction); } 另外,還在 CKeys 類的 CKeys::KeySymbol() 方法中加入了一點小的改進(jìn),數(shù)字鍵盤 (鍵盤右側(cè)部分中單獨(dú)的一個按鍵塊) 之前沒有做處理,現(xiàn)在您也可以從鍵盤的這個部分輸入數(shù)字和字符了。 // ------------------------------------------------------------------ 
//| 返回按下的按鈕字符                                                  |
// ------------------------------------------------------------------ 
string CKeys::KeySymbol(const long key_code)
  {
   string key_symbol='';
//--- 如果需要空格 (空格鍵)
   if(key_code==KEY_SPACE)
     {
      key_symbol=' ';
     }
//--- 如果需要 (1)一個字母字符或者 (2) 數(shù)字字符 或者 (3) 特殊字符
   else if((key_code>=KEY_A && key_code<=KEY_Z) ||
           (key_code>=KEY_0 && key_code<=KEY_9) ||
           (key_code>=KEY_NUMLOCK_0 && key_code<=KEY_NUMLOCK_SLASH) ||
           (key_code>=KEY_SEMICOLON && key_code<=KEY_SINGLE_QUOTE))
     {
      key_symbol=::ShortToString(::TranslateKey((int)key_code));
     }
//--- 返回字符
   return(key_symbol);
  }
 新版本的 CTable 和 CKeys 類可以在文章末尾下載。 結(jié)論這是文章的第一部分,我們已經(jīng)討論了如何不花費(fèi)額外經(jīng)歷為任何復(fù)雜程序開發(fā) GUI,您可以繼續(xù)開發(fā)這個程序,為您自己的目標(biāo)使用它。在文章的第二部分,我將會向您展示如何操作 GUI,其中最重要的是 - 怎樣填補(bǔ)功能。 在下面,您可以下載文件來測試和仔細(xì)學(xué)習(xí)本文提供的代碼。 
 | 
|  |