量化交易軟件:圖形界面 XI渲染控件 (統(tǒng)合構(gòu)建14.2)
首篇文章 圖形界面 I: 函數(shù)庫結(jié)構(gòu)的準(zhǔn)備 (第 1 章) 詳細(xì)研究了這個(gè)函數(shù)庫。本系列每篇文章的最后, 提供了當(dāng)前開發(fā)階段的完整版函數(shù)庫。文件必須放置于存檔中所在的相同目錄下。
在更新版的函數(shù)庫中, 所有控件將在 OBJ_BITMAP_LABEL 類型的單獨(dú)圖形對(duì)象上繪制。此外, 赫茲量化將繼續(xù)描述函數(shù)庫代碼的全局優(yōu)化。此描述已在 以前的文章 中開始?,F(xiàn)在赫茲量化來研究函數(shù)庫中核心類的變化。新版本的函數(shù)庫已經(jīng)變得更加面向?qū)ο?。代碼變得更加簡(jiǎn)明易懂。這有助于用戶根據(jù)自己的任務(wù)獨(dú)立開發(fā)函數(shù)庫。

編輯切換為居中
繪制控件的方法
已在 CElement 類已聲明了一個(gè) 畫布類的實(shí)例。其方法允許創(chuàng)建一個(gè)對(duì)象來繪制和刪除它。若有必要, 可以獲得它的指針。
class CElement : public CElementBase ?{ protected: ? //--- 繪制控件的畫布 ? CRectCanvas ? ? ? m_canvas; ? //--- public: ? //--- 返回指向控件畫布的指針 ? CRectCanvas ? ? ?*CanvasPointer(void) { return(::GetPointer(m_canvas)); } ?};
現(xiàn)在有一個(gè)通用的方法來創(chuàng)建一個(gè)用于繪制控件外觀的對(duì)象 (畫布)。它位于 CElement 基類中, 可以從函數(shù)庫的所有控件類訪問。CElement::CreateCanvas() 方法用于創(chuàng)建此類型的圖形對(duì)象。作為參數(shù), 必須傳遞 (1) 名稱, (2) 坐標(biāo), (3) 維度和 (4) 顏色格式。省缺格式為 COLOR_FORMAT_ARGB_NORMALIZE, 這可令控件變得透明。如果傳遞了無效維度, 它們將在方法的開頭被修正。一旦在運(yùn)行 MQL 應(yīng)用程序的圖表上對(duì)象了創(chuàng)建并加載, 將會(huì)為其設(shè)置基本屬性, 這在以前的所有控件類中不斷重復(fù)。
class CElement : public CElementBase ?{ public: ? //--- 創(chuàng)建畫布 ? bool ? ? ? ? ? ? ?CreateCanvas(const string name,const int x,const int y, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const int x_size,const int y_size,ENUM_COLOR_FORMAT clr_format=COLOR_FORMAT_ARGB_NORMALIZE); ?}; //+------------------------------------------------------------------+ //| 創(chuàng)建繪制控件的畫布 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| //+------------------------------------------------------------------+ bool CElement::CreateCanvas(const string name,const int x,const int y, ? ? ? ? ? ? ? ? ? ? ? ? ? ?const int x_size,const int y_size,ENUM_COLOR_FORMAT clr_format=COLOR_FORMAT_ARGB_NORMALIZE) ?{ //--- 調(diào)整尺寸 ? int xsize =(x_size<1)? 50 : x_size; ? int ysize =(y_size<1)? 20 : y_size; //--- 重置最后的錯(cuò)誤 ? ::ResetLastError(); //--- 創(chuàng)建對(duì)象 ? if(!m_canvas.CreateBitmapLabel(m_chart_id,m_subwin,name,x,y,xsize,ysize,clr_format)) ? ? { ? ? ?::Print(__FUNCTION__," > 創(chuàng)建繪制控件的畫布失敗 ("+m_class_name+"): ",::GetLastError()); ? ? ?return(false); ? ? } //--- 重置最后的錯(cuò)誤 ? ::ResetLastError(); //--- 獲取指向基類的指針 ? CChartObject *chart=::GetPointer(m_canvas); //--- 掛載到圖表 ? if(!chart.Attach(m_chart_id,name,(int)m_subwin,(int)1)) ? ? { ? ? ?::Print(__FUNCTION__," > 將繪圖畫布掛載到圖表失敗: ",::GetLastError()); ? ? ?return(false); ? ? } //--- 屬性 ? m_canvas.Tooltip("\n"); ? m_canvas.Corner(m_corner); ? m_canvas.Selectable(false); //--- 除窗體外, 所有控件的優(yōu)先級(jí)高于主控件 ? Z_Order((dynamic_cast<CWindow*>(&this)!=NULL)? 0 : m_main.Z_Order()+1); //--- 坐標(biāo) ? m_canvas.X(x); ? m_canvas.Y(y); //--- 大小 ? m_canvas.XSize(x_size); ? m_canvas.YSize(y_size); //--- 距極點(diǎn)的偏移 ? m_canvas.XGap(CalculateXGap(x)); ? m_canvas.YGap(CalculateYGap(y)); ? return(true); ?}
赫茲量化來轉(zhuǎn)進(jìn)到繪制控件的基本方法。它們都位于 CElement 類中, 并聲明為 virtual。
首先來繪制背景。在基本版中, 它只是簡(jiǎn)單地使用 CElement::DrawBackground() 方法填充顏色。如有必要, 可以啟用透明度。為此, 請(qǐng)使用 CElement::Alpha() 方法, Alpha 通道值從 0 到 255 作為參數(shù)傳遞。零值意味著完全透明。在當(dāng)前版本中, 透明度僅適用于背景填充和邊框。文字和圖像將保持完全不透明, 并清除所有 alpha 通道值。
class CElement : public CElementBase ?{ protected: ? //--- alpha 通道值 (控件的透明度) ? uchar ? ? ? ? ? ? m_alpha; ? //--- public: ? //--- alpha 通道值 (控件的透明度) ? void ? ? ? ? ? ? ?Alpha(const uchar value) ? ? ? ? ? ? ? ? ? ? ? ?{ m_alpha=value; ? ? ? ? ? ? ? ? ? } ? uchar ? ? ? ? ? ? Alpha(void) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const { return(m_alpha); ? ? ? ? ? ? ? ? } ? //--- protected: ? //--- 繪制背景 ? virtual void ? ? ?DrawBackground(void); ?}; //+------------------------------------------------------------------+ //| 繪制背景 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | //+------------------------------------------------------------------+ void CElement::DrawBackground(void) ?{ ? m_canvas.Erase(::ColorToARGB(m_back_color,m_alpha)); ?}
通常需要為特定的控件畫一個(gè)邊框。CElement::DrawBorder() 方法在畫布對(duì)象的邊緣周圍繪制一個(gè)邊框。Rectangle() 方法也可以用于此目的。它繪制一個(gè)未經(jīng)填充的矩形。
class CElement : public CElementBase ?{ protected: ? //--- 繪制邊框 ? virtual void ? ? ?DrawBorder(void); ?}; //+------------------------------------------------------------------+ //| 繪制邊框 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | //+------------------------------------------------------------------+ void CElement::DrawBorder(void) ?{ //--- 坐標(biāo) ? int x1=0,y1=0; ? int x2=m_canvas.X_Size()-1; ? int y2=m_canvas.Y_Size()-1; //--- 繪制一個(gè)未經(jīng)填充的矩形 ? m_canvas.Rectangle(x1,y1,x2,y2,::ColorToARGB(m_border_color,m_alpha)); ?}
上一篇文章中已經(jīng)提到可以將任意數(shù)量的圖片組分配給任何控件。所以, 繪制控件的方法必須能夠輸出用戶設(shè)置的所有圖像。CElement::DrawImage() 方法即用于此目的。程序按順序 遍歷所有的組 和 其中的圖片, 將它們逐像素輸出到畫布。在輸出圖像的循環(huán)開始之前, 檢測(cè)組中當(dāng)前所選的圖片。參見此方法的代碼:
class CElement : public CElementBase ?{ protected: ? //--- 繪制圖片 ? virtual void ? ? ?DrawImage(void); ?}; //+------------------------------------------------------------------+ //| 繪制圖片 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| //+------------------------------------------------------------------+ void CElement::DrawImage(void) ?{ //--- 組的數(shù)量 ? uint group_total=ImagesGroupTotal(); //--- 繪制圖片 ? for(uint g=0; g<group_total; g++) ? ? { ? ? ?//--- 所選圖片的索引 ? ? ?int i=SelectedImage(g); ? ? ?//--- 如果沒有圖片 ? ? ?if(i==WRONG_VALUE) ? ? ? ? continue; ? ? ?//--- 坐標(biāo) ? ? ?int x =m_images_group[g].m_x_gap; ? ? ?int y =m_images_group[g].m_y_gap; ? ? ?//--- 大小 ? ? ?uint height =m_images_group[g].m_image[i].Height(); ? ? ?uint width ?=m_images_group[g].m_image[i].Width(); ? ? ?//--- 繪制 ? ? ?for(uint ly=0,p=0; ly<height; ly++) ? ? ? ?{ ? ? ? ? for(uint lx=0; lx<width; lx++,p++) ? ? ? ? ? { ? ? ? ? ? ?//--- 如果沒有顏色, 轉(zhuǎn)至下一像素 ? ? ? ? ? ?if(m_images_group[g].m_image[i].Data(p)<1) ? ? ? ? ? ? ? continue; ? ? ? ? ? ?//--- 獲取下層 (單元格背景) 的顏色, 和圖標(biāo)指定像素的顏色 ? ? ? ? ? ?uint background ?=::ColorToARGB(m_canvas.PixelGet(x+lx,y+ly)); ? ? ? ? ? ?uint pixel_color =m_images_group[g].m_image[i].Data(p); ? ? ? ? ? ?//--- 混合顏色 ? ? ? ? ? ?uint foreground=::ColorToARGB(m_clr.BlendColors(background,pixel_color)); ? ? ? ? ? ?//--- 繪制疊加圖標(biāo)的像素 ? ? ? ? ? ?m_canvas.PixelSet(x+lx,y+ly,foreground); ? ? ? ? ? } ? ? ? ?} ? ? } ?}
許多控件都有一個(gè)文本描述??梢允褂?CElement::DrawText() 方法顯示它。此方法中的若干字段允許根據(jù)控件的狀態(tài)自定義文本的顯示。控件有三個(gè)狀態(tài)可用:
鎖定;
按下;
聚焦 (鼠標(biāo)懸停)。