内容
介绍
第一篇 图形界面I:准备库结构(第1章) 详细描述此库的作用。在每章的结尾,您将找到与该文章相关的链接的完整列表。在这里,您还可以根据当前的开发状态下载项目。文件必须与存储在归档文件中的文件放置在相同的目录中。
本文是关于三个类的,这些类使您可以为MQL应用程序的二维数据集编程不同的表类型:
- 文字标签表;
- 编辑框表;
- 渲染表。
每种类型的表都有其自身的特殊属性和优点,我们将在下面进行描述。
在下面的文章(第七部分,第2章)中,我们将讨论以下控件:
- 标签;
- 带有图片的标签。
文本标签表控件
表格是一个复杂的GUI控件,因为它还包含其他控件-水平和垂直滚动条。由于可能发生数据量超出控件内可用可见空间的情况,因此滚动条为您提供了沿水平和垂直方向来回移动数据的选项。
文本标签表由以下组件组成:
- 背景
- 文字标签。
- 垂直滚动条。
- 水平滚动条。
图1.文本标签表控件的组件
让我们仔细看看此控件的类。
标签表 类的开发
产生 标签表 归档并从库中获取(WndContainer.mqh ),其中包含:
//+------------------------------------------------------------------+ //| WndContainer.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| //www.mql5.com | //+------------------------------------------------------------------+ #include "标签表"
在中生成它们 标签表 备课 标签表 该库中每个控件应具有的标准方法集,以及用于保存添加了控件的表单的指针的方法。使用本文中讨论的所有控件来执行此操作。
//+------------------------------------------------------------------+ //| Class for creating a text label table | //+------------------------------------------------------------------+ class 标签表 : 上市 CElement { 私人的 : //--- Ein Pointer zu 的 Form zu welchem das Element hinzugefügt worden ist CWindow *m_wnd; //--- 上市 : 标签表 (void); ~CLabelsTable(void); //--- (1) Speichert den Pointer das Formulars, (2) Gibt den Pointer zu den Scrollbars zurück void WindowPointer(CWindow &object) { m_wnd=::GetPointer(object); } //--- 上市 : //--- Chart Eventhandler virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); //--- Timer virtual void OnEventTimer(void); //--- Bewegen des Elementes virtual void Moving(const int x,const int y); //--- (1) Anzeigen, (2) verstecken, (3) zurücksetzen, (4) löschen virtual void Show(void); virtual void Hide(void); virtual void Reset(void); virtual void Delete(void); //--- (1) Setzen, (2) Zurücksetzen 的 Prioritäten 的 linken Maustaste virtual void SetZorders(void); virtual void ResetZorders(void); //--- Zurücksetzen 的 Farbe virtual void ResetColors(void) {} }; //+------------------------------------------------------------------+ //| Konstruktor | //+------------------------------------------------------------------+ CLabelsTable::CLabelsTable(void) { } //+------------------------------------------------------------------+ //| Destruktor | //+------------------------------------------------------------------+ CLabelsTable::~CLabelsTable(void) { }
在创建表之前,让我们指定其某些属性。我们命名这些
- 线的高度
- 从控件的左边缘开始的第一列缩进
- 列之间的距离
- 背景色
- 文字颜色
- 第一行锁定模式
- 第一栏的锁定方式
- 总列数
- 总行数
- 可见列数
- 可见线数
对于这种类型的表格,文本标签的坐标是根据中心锚点(ANCHOR_CENTER)。因此,从控件的左上角开始计算文本标签第一列的缩进,并从每列的中心计算每列文本标签之间的距离。
在锁定模式下,即使用户移动了垂直和水平滚动条的滑块,第一行和/或每一行(用户在其中指定每个列和行的名称)也必须保持可见。锁定模式可以一起使用,也可以单独使用。
class 标签表 : 上市 CElement { 私人的 : //--- 线的高度 int m_row_y_size; //--- 背景色 的 Tabelle color m_area_color; //--- 的 Standardfarbe des Textes 的 Tabelle color m_text_color; //--- Der Abstand zwischen dem Ankerpunkt 的 ersten Spalte 和 的 linken Ecke des Controls int m_x_offset; //--- Der Abstand zwischen den Ankerpunkten 的 Spalten int m_column_x_offset; //--- Sperrmodus 的 ersten Zeile bool m_fix_first_row; //--- Sperrmodus 的 ersten Spalte bool m_fix_first_column; //--- Priorität für die linke Maustaste int m_zorder; int m_area_zorder; //--- 上市 : //--- (1) 背景 farbe, (2) Textfarbe void AreaColor(const color clr) { m_area_color=clr; } void TextColor(const color clr) { m_text_color=clr; } //--- (1) Höhe 的 Zeile, (2) Festlegen des Abstandes zwischen dem Ankerpunkt 的 ersten Spalte 和 的 linken Ecke 的 Tabelle, // (3) festlegen 的 Abstände zwischen den Ankerpunkten 的 Spalten void RowYSize(const int y_size) { m_row_y_size=y_size; } void XOffset(const int x_offset) { m_x_offset=x_offset; } void ColumnXOffset(const int x_offset) { m_column_x_offset=x_offset; } //--- (1) Abfrage 和 (2) des Sperrmodus für die erste Zeile bool FixFirstRow(void) const { return(m_fix_first_row); } void FixFirstRow(const bool flag) { m_fix_first_row=flag; } //--- (1) Abfrage 和 (2) des Sperrmodus für die erste Spalte bool FixFirstColumn(void) const { return(m_fix_first_column); } void FixFirstColumn(const bool flag) { m_fix_first_column=flag; } };
来做吧 标签表 :: TableSize () 和 标签表 :: VisibleTableSize () 获得方法 总 才能定义可见的列数和行数。我们还需要结构形式的二维动态数组。这些结构之一( LT标签 )为表格的可见区域创建带有文本标签的数组,而另一个( LT选项 )保存表中每个单元格的所有值和属性。在我们的实现中,这将保存显示的值(线条)和文本颜色
的 标签表 :: TableSize () 和 标签表 :: VisibleTableSize () 方法传递两个参数(列数和行数)。在方法开始时,将检查值以查看列数是否小于一以及行数是否小于两。然后定义所有arrayd的大小,并初始化数组的属性。
除了用于表大小的方法外,我们还需要用于查询具有列和行的总可见大小的方法。
class 标签表 : 上市 CElement { 私人的 : //--- Array mit Objekten für den sichtbaren Bereich 的 Tabelle struct LT标签 { CLabel m_rows[]; }; LT标签 m_columns[]; //--- Array mit den Werten 和 Eigenschaften 的 Tabelle struct LT选项 { string m_vrows[]; color m_colors[]; }; LT选项 m_vcolumns[]; //--- 上市 : //--- Gib die gesamte Anzahl von (1) Zeilen 和 (2) Spalten zurück int RowsTotal(void) const { return(m_rows_total); } int ColumnsTotal(void) const { return(m_columns_total); } //--- Gibt die Anzahl von (1) Zeilen 和 (2) Spalten des sichtbaren Bereichs 的 Tabelle zurück int VisibleRowsTotal(void) const { return(m_visible_rows_total); } int VisibleColumnsTotal(void) const { return(m_visible_columns_total); } //--- Setzen 的 (1) Größe 的 Tabelle 和 (2) Der Größe des sichtbaren Bereiches void TableSize(const int columns_total,const int rows_total); void VisibleTableSize(const int visible_columns_total,const int visible_rows_total); }; //+------------------------------------------------------------------+ //| Legt die Größe 的 Tabelle fest | //+------------------------------------------------------------------+ void 标签表 :: TableSize(const int columns_total,const int rows_total) { //--- Es muss mindestens eine Spalte geben m_columns_total=(columns_total<1) ? 1 : columns_total; //--- Es muss mindestens zwei Zeilen geben m_rows_total=(rows_total<2) ? 2 : rows_total; //--- Festlegen 的 Größe 的 Spalten-Arrays ::ArrayResize(m_vcolumns,m_columns_total); //--- Festlegen 的 Größe 的 Zeilen-Arrays for(int i=0; i<m_columns_total; i++) { ::ArrayResize(m_vcolumns[i].m_vrows,m_rows_total); ::ArrayResize(m_vcolumns[i].m_colors,m_rows_total); //--- Initialisieren des Arrays 的 Textfarben mit den Standardwerten ::ArrayInitialize(m_vcolumns[i].m_colors,m_text_color); } } //+-----------------------------------------------------------------+ //| Festlegen 的 Größe des sichtbaren Teils 的 Tabelle | //+-----------------------------------------------------------------+ void 标签表 :: VisibleTableSize(const int visible_columns_total,const int visible_rows_total) { //--- Es muss mindestens eine Spalte geben m_visible_columns_total=(visible_columns_total<1) ? 1 : visible_columns_total; //--- Es muss mindestens zwei Zeilen geben m_visible_rows_total=(visible_rows_total<2) ? 2 : visible_rows_total; //--- Festlegen 的 Größe 的 Spalten-Arrays ::ArrayResize(m_columns,m_visible_columns_total); //--- Festlegen 的 Größe 的 Zeilen-Arrays for(int i=0; i<m_visible_columns_total; i++) ::ArrayResize(m_columns[i].m_rows,m_visible_rows_total); }
在创建控件之前,应使用标准值初始化所有属性。我建议直接在类构造函数中执行此操作:
//+----------------------------------------------------------------+ //| Konstruktor | //+----------------------------------------------------------------+ CLabelsTable::CLabelsTable(void) : m_fix_first_row(false), m_fix_first_column(false), m_row_y_size(18), m_x_offset(30), m_column_x_offset(60), m_area_color(clrWhiteSmoke), m_text_color(clrBlack), m_rows_total(2), m_columns_total(1), m_visible_rows_total(2), m_visible_columns_total(1) { //--- Abspeichern des namens 的 Elementklasse in 的 Basisklasse CElement::ClassName(CLASS_NAME); //--- Setzen 的 Priorität eines Klicks mit 的 linken Maustaste m_zorder =0; m_area_zorder =1; //--- Festlegen 的 Größe 的 Tabelle 和 seines sichtbaren Bereiches TableSize(m_columns_total,m_rows_total); VisibleTableSize(m_visible_columns_total,m_visible_rows_total); }
我们四个 私人的 和一个 上市 生成用于外部调用的控件的开发方法。为了使用户能够配置表的滚动条,我们必须添加一个返回其指针的方法。
class 标签表 : 上市 CElement { 私人的 : //--- Objekte für die Erzeugung einer Tabelle CRectLabel m_area; CScrollV m_scrollv; CScrollH m_scrollh; //--- Array mit Objekten für den sichtbaren Bereich 的 Tabelle struct LT标签 { CLabel m_rows[]; }; LT标签 m_columns[]; //--- 上市 : //--- Gibt die Pointer 的 Scrollbars zurück CScrollV *GetScrollVPointer(void) const { return(::GetPointer(m_scrollv)); } CScrollH *GetScrollHPointer(void) const { return(::GetPointer(m_scrollh)); } //--- Methoden für die Erzeugung 的 Tabelle bool CreateLabelsTable(const long chart_id,const int subwin,const int x,const int y); //--- 私人的 : bool CreateArea(void); bool CreateLabels(void); bool CreateScrollV(void); bool CreateScrollH(void); };
在所有生成方法中,这里仅讨论那些方法 标签表 :: CreateLabels()显示为文本标签数组的开发。确保你有 向列和行添加索引 建立对象名称时。其他所有方法都可以在附件中找到。
//+-----------------------------------------------------------------+ //| Erzeugung eines Arrays mit Text-Labeln | //+-----------------------------------------------------------------+ bool 标签表 :: CreateLabels(void) { //--- Koordinaten 和 Offset int x =CElement::X(); int y =0; int offset =0; //--- Spalten for(int c=0; c<m_visible_columns_total; c++) { //--- Berechnung des Tabellen-Offsets offset=(c>0) ? m_column_x_offset : m_x_offset; //--- Berechnung 的 x-Koordinate x=x+offset; //--- Zeilen for(int r=0; r<m_visible_rows_total; r++) { //--- Bilden des Objektnamens string name=CElement::ProgramName()+"_labelstable_label_"+(string)c+"_"+(string)r+"__"+(string)CElement::Id(); //--- Berechne die Y Koordinate y=(r>0) ? y+m_row_y_size-1 : CElement::Y()+10; //--- Erzeugen des Objektes if(!m_columns[c].m_rows[r].Create(m_chart_id,name,m_subwin,x,y)) return(false); //--- Festlegen 的 Eigenschaften m_columns[c].m_rows[r].Description(m_vcolumns[c].m_vrows[r]); m_columns[c].m_rows[r].Font(FONT); m_columns[c].m_rows[r].FontSize(FONT_SIZE); m_columns[c].m_rows[r].Color(m_text_color); m_columns[c].m_rows[r].Corner(m_corner); m_columns[c].m_rows[r].Anchor(ANCHOR_CENTER); m_columns[c].m_rows[r].Selectable(false); m_columns[c].m_rows[r].Z_Order(m_zorder); m_columns[c].m_rows[r].Tooltip("\n"); //--- Abstände von 的 Ecke des Formulars m_columns[c].m_rows[r].XGap(x-m_wnd.X()); m_columns[c].m_rows[r].YGap(y-m_wnd.Y()); //--- Koordinaten m_columns[c].m_rows[r].X(x); m_columns[c].m_rows[r].Y(y); //--- Abspeichern des Objekt-Pointers CElement::AddToArray(m_columns[c].m_rows[r]); } } //--- return(true); }
我们仍然需要能够随时更改表中每个单元格的值和属性的方法。来做吧 标签表 :: SetValue () 和 标签表 :: GetValue () 创建用于设置和查询单元格值的方法。使用这两种方法时,必须将列和行的索引作为第一个参数传递。然后将要保存在数组中的值用作以下项的第三个参数: 标签表 :: SetValue () 通过方法。首先当然要强制检查索引值是否超过数组的限制。
class 标签表 : 上市 CElement { 上市 : //--- Festlegen eines Wertes in 的 spezifizierten Zelle einer Tabelle void SetValue(const int column_index,const int row_index,const string value); //--- 查询值 einer bestimmten Zelle einer Tabelle string GetValue(const int column_index,const int row_index); }; //+-----------------------------------------------------------------+ //| Setzen des Wertes bei den angegebenen Indizes | //+-----------------------------------------------------------------+ void 标签表 :: SetValue(const int column_index,const int row_index,const string value) { //--- Überprüfung auf Überschreitung des Indexbereiches 的 Spalten int csize=::ArraySize(m_vcolumns); if(csize<1 || column_index<0 || column_index>=csize) return; //--- Überprüfung 的 Überschreitung des Indexbereiches 的 Zeilen int rsize=::ArraySize(m_vcolumns[column_index].m_vrows); if(rsize<1 || row_index<0 || row_index>=rsize) return; //--- Setzen des Wertes m_vcolumns[column_index].m_vrows[row_index]=value; } //+-----------------------------------------------------------------+ //| Rückgabe des Wertes an den angegebenen Indizes | //+-----------------------------------------------------------------+ string 标签表 :: GetValue(const int column_index,const int row_index) { //--- Überprüfung auf Überschreitung des Indexbereiches 的 Spalten int csize=::ArraySize(m_vcolumns); if(csize<1 || column_index<0 || column_index>=csize) return(""); //--- Überprüfung 的 Überschreitung des Indexbereiches 的 Zeilen int rsize=::ArraySize(m_vcolumns[column_index].m_vrows); if(rsize<1 || row_index<0 || row_index>=rsize) return(""); //--- Rückgabe des Wertes return(m_vcolumns[column_index].m_vrows[row_index]); }
除了更改表中的值之外,库用户还可能希望更改文本的颜色。例如,正值可以用绿色显示,负值可以用红色显示。为此, 标签表 :: TextColor()创建方法。她就是那个 标签表 :: SetValue()方法非常相似,唯一的区别在于颜色是第三个参数。
class 标签表 : 上市 CElement { 上市 : //--- 文字颜色 einer bestimmten Zelle ändern void TextColor(const int column_index,const int row_index,const color clr); }; //+-----------------------------------------------------------------+ //| Ändert die Farbe einer bestimmten Zelle | //+-----------------------------------------------------------------+ void 标签表 :: TextColor(const int column_index,const int row_index,const color clr) { //--- Überprüfung auf Überschreitung des Indexbereiches 的 Spalten int csize=::ArraySize(m_vcolumns); if(csize<1 || column_index<0 || column_index>=csize) return; //--- Überprüfung 的 Überschreitung des Indexbereiches 的 Zeilen int rsize=::ArraySize(m_vcolumns[column_index].m_vrows); if(rsize<1 || row_index<0 || row_index>=rsize) return; //--- Festlegen 的 Farbe m_vcolumns[column_index].m_colors[row_index]=clr; }
仅在更新表后才接受/显示更改。为此,我们创建了一种通用方法,该方法在必须根据滑块在滚动条上的位置移动数据时也可以使用。
让我们做这个方法 标签表 :: UpdateTable()致电。如果标题已锁定,则移位将从第二个(1)数组索引开始,以确保第一行或第一列始终保持可见。的 t 和 l 变量在方法开始时声明,其值0或1根据当前使用的模式设置。
为了能够定义必须从中开始换档或更新的索引, 必须查询滚动条滑块的当前位置。左列和顶行的标题在单独的循环中移动(如果激活了此模式)。
在方法结束时,表格的主要数据和单元格的颜色以双循环方式移动。
class 标签表 : 上市 CElement { 上市 : //--- Aktualisierung 的 那里 ten 的 Tabelle unter Berücksichtigung 的 letzten Veränderungen void UpdateTable(void); }; //+-----------------------------------------------------------------------------------------+ //| Aktualisierung 的 那里 ten 的 Tabelle unter Berücksichtigung 的 letzten Veränderungen | //+-----------------------------------------------------------------------------------------+ void 标签表 :: UpdateTable(void) { //--- Verschieben um einen Index, falls 的 fixierte Kopfzeilen-Modus aktiviert ist int t=(m_fix_first_row) ? 1 : 0; int l=(m_fix_first_column) ? 1 : 0; //--- Abfrage 的 aktuellen Positionen 的 Schieberegler 的 vertikalen 和 horizontalen Scrollbars int h=m_scrollh.CurrentPos()+l; int v=m_scrollv.CurrentPos()+t; //--- Verschieben 的 Kopfzeile in 的 linken Spalte if(m_fix_first_column) { m_columns[0].m_rows[0].Description(m_vcolumns[0].m_vrows[0]); //--- Zeilen for(int r=t; r<m_visible_rows_total; r++) { if(r>=t && r<m_rows_total) m_columns[0].m_rows[r].Description(m_vcolumns[0].m_vrows[v]); //--- v++; } } //--- Verschieben 的 Kopfzeile in 的 obersten Zeile if(m_fix_first_row) { m_columns[0].m_rows[0].Description(m_vcolumns[0].m_vrows[0]); //--- Spalten for(int c=l; c<m_visible_columns_total; c++) { if(h>=l && h<m_columns_total) m_columns[c].m_rows[0].Description(m_vcolumns[h].m_vrows[0]); //--- h++; } } //--- Abfrage 的 aktuellen Position des Schiebereglers 的 Horizontalen Scrollbar h=m_scrollh.CurrentPos()+l; //--- Spalten for(int c=l; c<m_visible_columns_total; c++) { //--- Abfrage 的 aktuellen Position des Schiebereglers 的 vertikalen Scrollbar v=m_scrollv.CurrentPos()+t; //--- Zeilen for(int r=t; r<m_visible_rows_total; r++) { //--- Verschiebung 的 Tabellendaten if(v>=t && v<m_rows_total && h>=l && h<m_columns_total) { //--- Einstellung 的 Farbe m_columns[c].m_rows[r].Color(m_vcolumns[h].m_colors[v]); //--- Einstellen 的 Werte m_columns[c].m_rows[r].Description(m_vcolumns[h].m_vrows[v]); v++; } } //--- h++; } }
正如我们对输入框和列表控件所做的那样,让我们实现快速滚动,只要在滚动条按钮上方按下鼠标左键即可。无需阅读 标签表 ::快速切换()这里的方法,因为它对应于以前文章中方法的程序代码( CListView , CSpin编辑 其他 CCheckBox编辑 类)。
下面的列表中显示了用于处理控制事件的方法的程序代码:
//+-----------------------------------------------------------------+ //| Even handler | //+-----------------------------------------------------------------+ void 标签表 ::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verarbeiten 的 Events über die Bewegung des Mauszeigers if(id==CHARTEVENT_MOUSE_MOVE) { //--- Abbrechen, falls das Element versteckt ist if(!CElement::IsVisible()) return; //---Koordinaten 和 的 Status 的 linken Maustaste int x=(int)lparam; int y=(int)dparam; m_mouse_state=(bool)int(sparam); //--- Überprüfen des Fokus über 的 Tabelle CElement::MouseFocus(x>X() && x<X2() && y>Y() && y<Y2()); //--- Bewege die Liste, falls die Verwaltung des Schiebereglers aktiviert ist if(m_scrollv.ScrollBarControl(x,y,m_mouse_state) || m_scrollh.ScrollBarControl(x,y,m_mouse_state)) UpdateTable(); //--- return; } //--- Verarbeitung von Klicks auf Objekte if(id==CHARTEVENT_OBJECT_CLICK) { //--- Falls auf einen Button 的 Tabellen-Scrollbars gedrückt wurde if(m_scrollv.OnClickScrollInc(sparam) || m_scrollv.OnClickScrollDec(sparam) || m_scrollh.OnClickScrollInc(sparam) || m_scrollh.OnClickScrollDec(sparam)) //--- Verschiebe die Tabelle relativ zu 的 Scrollbar UpdateTable(); //--- return; } } //+-----------------------------------------------------------------+ //| Timer | //+-----------------------------------------------------------------+ void 标签表 ::OnEventTimer(void) { //--- Falls es sich um einen DropDown-Element handelt if(CElement::IsDropdown()) FastSwitching(); //--- Falls es sich nicht um ein Dropdown-Element handelt, berücksichtige die aktuelle Verfügbarkeit des Formulars else { //--- Verfolge den schnellen Vorlauf 的 Tabelle nur, falls das Formular nicht gesperrt ist if(!m_wnd.IsLocked()) FastSwitching(); } }
表是一个复杂的GUI控件。因此,其他控件(水平和垂直滚动条)的指针应包含在指针数据库中。我们应该为表指针创建一个独立的数组。您可以在 WndContainer.mqh 的档案 CWnd容器 大。本系列的其他文章中已经讨论了该主题。因此,我将跳过这一步并继续测试文本标签表。
测试文字标签表
为了进行测试,我们将使用上一篇文章中的EA交易,并仅保留主菜单和状态栏。为了能够将文本标签表添加到MQL应用程序, 标签表 声明了类型类实例,以及到表单最顶端的方法和距离(您可以在下面的程序代码中看到它们)。
class C程序 : 上市 CWndEvents { 私人的 : //--- Text-Label-Tabelle 标签表 m_labels_table; //--- 私人的 : //--- Text-Label-Tabelle #define LABELS_TABLE1_GAP_X (1) #define LABELS_TABLE1_GAP_Y (42) bool CreateLabelsTable(void); };
现在,让我们运行 C程序 :: CreateLabelsTable()仔细研究该方法。我们想要一个组成的桌子 21 列和 100 线条由设计组成。可见列数为 5,可见线数为 10. 我们修复了顶行和左列,以免它们移动。创建表后,它会填充随机值(来自-1000 至 1000),并且颜色仍然定义。正值显示为绿色,负值显示为红色。 您更新表格,以便可以看到最新的更改.
//+-----------------------------------------------------------------+ //| Erzeugung 的 Text Label Tabelle | //+-----------------------------------------------------------------+ bool C程序 :: CreateLabelsTable(void) { #define COLUMNS1_TOTAL (21) #define ROWS1_TOTAL (100) //--- Abspeichern des pointers zu dem Formular m_labels_table.WindowPointer(m_window1); //--- Koordinaten int x=m_window1.X()+LABELS_TABLE1_GAP_X; int y=m_window1.Y()+LABELS_TABLE1_GAP_Y; //--- 可见列数 和 Zeilen int visible_columns_total =5; int visible_rows_total =10; //--- Setzen 的 Eigenschaften m_labels_table.XSize(400); m_labels_table.XOffset(40); m_labels_table.ColumnXOffset(75); m_labels_table.FixFirstRow(true); m_labels_table.FixFirstColumn(true); m_labels_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL); m_labels_table.VisibleTableSize(visible_columns_total,visible_rows_total); //--- Erzeugen 的 Tabelle if(!m_labels_table.CreateLabelsTable(m_chart_id,m_subwin,x,y)) return(false); //--- Einfügen in die Tabelle: // Die erste Zelle ist leer m_labels_table.SetValue(0,0,"-"); //--- 的 Überschriften 的 Spalten for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_labels_table.SetValue(c,r,"SYMBOL "+string(c)); } //--- 的 Überschriften 的 Zeilen, die Ausrichtung ist Rechts for(int c=0; c<1; c++) { for(int r=1; r<ROWS1_TOTAL; r++) m_labels_table.SetValue(c,r,"PARAMETER "+string(r)); } //--- 那里 ten 和 Tabellen-Formatierung (Hintergrund 和 Farben 的 Zellen) for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=1; r<ROWS1_TOTAL; r++) m_labels_table.SetValue(c,r,string(::rand () %1000-::rand () %1000)); } //--- 文字颜色 in den Zellen setzen for(int c=1; c<m_labels_table.ColumnsTotal(); c++) for(int r=1; r<m_labels_table.RowsTotal(); r++) m_labels_table.TextColor(c,r,((double)m_labels_table.GetValue(c,r)>=0) ? clrGreen : clrRed); //--- Aktualisieren 的 Tabelle m_labels_table.UpdateTable(); //--- Hinzufügen des Pointers des Elementes zu 的 Basis CWnd容器::AddToElementsArray(0,m_labels_table); return(true); }
当程序在终端图表上运行时,我们还应该测试表值如何更改。去做这个 成为以下程序代码 的 C程序 :: OnTimerEvent()将Timer方法添加到应用程序中。看一下下面的清单:
//+----------------------------------------------------------------+ //| Timer | //+----------------------------------------------------------------+ void C程序 :: OnTimerEvent(void) { CWndEvents::OnTimerEvent(); //--- Aktualisierung des zweiten Punktes 的 Statuszeile alle 500 Millisekunden static int count=0; if(count<500) { count+=TIMER_STEP_MSC; return; } //--- Zurücksetzen des Timers count=0; //--- Veränderung des Wertes in dem zweiten Punkt 的 Statuszeile. m_status_bar.ValueToItem(1,::TimeToString(::TimeLocal () ,TIME_DATE|TIME_SECONDS)); //--- Tabelle mit 那里 ten auffüllen for(int c=1; c<m_labels_table.ColumnsTotal(); c++) for(int r=1; r<m_labels_table.RowsTotal(); r++) m_labels_table.SetValue(c,r,string(::rand () %1000-::rand () %1000)); //--- 文字颜色 in den Zellen setzen for(int c=1; c<m_labels_table.ColumnsTotal(); c++) for(int r=1; r<m_labels_table.RowsTotal(); r++) m_labels_table.TextColor(c,r,((double)m_labels_table.GetValue(c,r)>=0) ? clrGreen : clrRed); //--- Aktualisieren 的 Tabelle m_labels_table.UpdateTable(); }
创建文本标签表的方法应该在main方法中 C程序 :: CreateExpertPanel()的应用。该过程的简短版本如下所示:
//+----------------------------------------------------------------+ //| Erzeugung des Expert-Bedienfeldes | //+----------------------------------------------------------------+ bool C程序 :: CreateExpertPanel(void) { //--- Erzeugen des Formulars 1 für die Controls //--- Erzeugen 的 Controls: // Hauptmenü //--- Kontextmenüs //--- Erzeugen 的 Statuszeile //--- Text-Label-Tabelle if(!CreateLabelsTable()) return(false); //--- Neuzeichnen des 图表 m_chart.Redraw(); return(true); }
编译程序代码并将程序加载到图表上。以下屏幕截图显示了结果:
图2.文本标签表的测试
一切正常。现在,让我们继续创建第二种类型的表的类。
编辑框表控件
与文本标签表不同,editbox表具有更大的灵活性和更多的属性。除了可以更改文本颜色外,它还提供:
- 单元格内文本的对齐方式(左/中/右)
- 更改背景颜色和编辑框的框架;
- 如果激活了相应的模式,则可以在编辑框中手动更改值。
所有这些要点使此表更加用户友好,并且易于执行大量任务。文本标签表由以下组件组成:
- 背景
- 编辑框
- 垂直滚动条。
- 水平滚动条。
图3.表格控件编辑框的组件
让我们看看程序代码与上表有何不同。
表格 类的开发
让我们描述表的特征,突出显示与上一张表的区别。该表中可见图形对象的数组来自另一种类型-( 编辑 )。换句话说,它由编辑框而不是文本标签组成(请参见下面的代码)。
class 表格 : 上市 CElement { 私人的 : //--- Array mit Objekten für den sichtbaren Bereich 的 Tabelle struct TEdits { 编辑 m_rows[]; }; TEdits m_columns[]; };
由于表格允许您执行此操作,因此每个单元格都有更多独特的属性 文字对齐 和 编辑框的背景色 改变。
class 表格 : 上市 CElement { 私人的 : //--- Arrays mit den Tabellenwerten 和 Eigenschaften struct TOptions { string m_vrows[]; ENUM_ALIGN_MODE m_text_align[]; color m_text_color[]; color m_cell_color[]; }; TOptions m_vcolumns[]; };
下面是文本标签表中不可用的模式和属性的列表。
- “可编辑”表模式
- 当鼠标指针悬停在一行上时突出显示该行的模式。
- 所选行的模式
- 线的高度
- 表格网格颜色
- 标题的背景色
- 标题文字颜色
- 鼠标指针悬停在单元格上方时的颜色。
- 单元格的默认颜色
- 单元格的默认对齐方式
- 行的突出显示的背景色
- 突出显示时文本的颜色
这种类型的表还允许您固定第一行和第一列的标题。选择此模式后,当移动滑块时它们将保留在原位。以下程序代码显示了完整的编辑框和用于设置表属性的方法:
class 表格 : 上市 CElement { 私人的 : //--- Höhe 的 Zeilen 的 Tabelle int m_row_y_size; //--- (1) 的 Farbe des 背景 es 和 (2) Des Rahmens des 背景 es 的 Tabelle color m_area_color; color m_area_border_color; //--- Farbe des Gitters color m_grid_color; //--- 背景 farbe 的 Überschrift color m_headers_color; //--- Textfarbe 的 Überschrift color m_headers_text_color; //--- 的 Farben 的 Zellen in den unterschiedlichen Zuständen color m_cell_color; color m_cell_color_hover; //--- 的 Standardfarbe für den Text einer Zelle color m_cell_text_color; //--- Farbe des (1) 背景 es 和 (2) des Textes 的 selektierten Zeile color m_selected_row_color; color m_selected_row_text_color; //--- Modus für die Editierbarkeit 的 Tabelle bool m_read_only; //--- Modus für das Hervorheben von Zeilen, wenn sich 的 Mauszeiger darüber befindet bool m_lights_hover; //--- Modus für die Auswählbarkeit einer Zeile bool m_selectable_row; //--- Sperrmodus 的 ersten Zeile bool m_fix_first_row; //--- Sperrmodus 的 ersten Spalte bool m_fix_first_column; //--- 的 Standard-Textausrichtung in den Edit-Boxen ENUM_ALIGN_MODE m_align_mode; //--- 上市 : //--- Farbe des (1) 背景 es 和 (2) des Rahmens 的 Tabelle void AreaColor(const color clr) { m_area_color=clr; } void BorderColor(const color clr) { m_area_border_color=clr; } //--- (1) Abfrage 和 (2) des Sperrmodus für die erste Zeile bool FixFirstRow(void) const { return(m_fix_first_row); } void FixFirstRow(const bool flag) { m_fix_first_row=flag; } //--- (1) Abfrage 和 (2) des Sperrmodus für die erste Spalte bool FixFirstColumn(void) const { return(m_fix_first_column); } void FixFirstColumn(const bool flag) { m_fix_first_column=flag; } //--- Farbe des (1) 背景 es 的 Überschriften, (2) Text 的 Überschriften 和 (3) Dis Tabellengitters void HeadersColor(const color clr) { m_headers_color=clr; } void HeadersTextColor(const color clr) { m_headers_text_color=clr; } void GridColor(const color clr) { m_grid_color=clr; } //--- 的 Größe 的 Zeilen entlang 的 y-Achse void RowYSize(const int y_size) { m_row_y_size=y_size; } void CellColor(const color clr) { m_cell_color=clr; } void CellColorHover(const color clr) { m_cell_color_hover=clr; } //--- (1) "Nur lesen", (2) Hervorheben 的 Zeilen, wenn sich die Maus darüber befindet, (3) Modus für die Auswertbarkeit 的 Zeile void ReadOnly(const bool flag) { m_read_only=flag; } void LightsHover(const bool flag) { m_lights_hover=flag; } void SelectableRow(const bool flag) { m_selectable_row=flag; } //--- 文字对齐 in 的 Zelle void TextAlign(const ENUM_ALIGN_MODE align_mode) { m_align_mode=align_mode; } };
下面列出了用于设置或查询表值的方法的属性,具体取决于列索引和行索引。
- 表的总大小(列和行的总数)
- 表格可见区域的大小(可见列和行的数量)
- 单元格的文本对齐方式(左/右/中心)
- 文字颜色
- 背景色
- 定义/更改值
- 查询值
这里没有理由重复此方法的代码,因为我们已经在文本标签表的部分中进行了讨论。设置所有值后,必须通过调用来确保拥有该表 表格 :: UpdateTable () 更新方法,以便所有更改都可见。
class 表格 : 上市 CElement { 上市 : //--- Setzen 的 (1) Größe 的 Tabelle 和 (2) Der Größe des sichtbaren Bereiches void TableSize(const int columns_total,const int rows_total); void VisibleTableSize(const int visible_columns_total,const int visible_rows_total); //--- Setzen (1) des Ausrichtungs-Modus, (2) Textfarbe, (3) 背景 farbe 的 Zelle void TextAlign(const int column_index,const int row_index,const ENUM_ALIGN_MODE mode); void TextColor(const int column_index,const int row_index,const color clr); void CellColor(const int column_index,const int row_index,const color clr); //--- Festlegen eines Wertes in 的 spezifizierten Zelle einer Tabelle void SetValue(const int column_index,const int row_index,const string value); //--- 查询值 einer bestimmten Zelle einer Tabelle string GetValue(const int column_index,const int row_index); //--- Aktualisierung 的 那里 ten 的 Tabelle unter Berücksichtigung 的 letzten Veränderungen void UpdateTable(void); };
现在让我们讨论管理表的方法。这些是排他性的 私人的 内部使用的类方法。它们的功能范围包括:
- 单击表中一行的处理。
- 将值输入到表的单元格中。
- 从对象名称查询ID
- 从对象名称查询列的索引
- 从对象名称查询行的索引
- 突出显示所选行
- 当鼠标指针悬停在按钮上时更改线条颜色。
- 快速向后滚动表格。
让我们处理一下 表格 :: OnClickTableRow()单击表中一行的启动方法。在方法开始时,需要进行一些检查。在以下情况下,程序将退出该方法:
- 选择用于编辑表格的模式;
- 滚动条之一处于活动状态时;
- 单击事件不属于此表的单元格。这可以根据对象名称,程序名称以及单元格与表的关联来确定;
- 控件ID不适用。要从对象名称获取ID, 表格 :: IdFromObjectName () 使用的方法。我们在检查其他控件时已经描述了此过程。
现在是时候在所有单元格中搜索并查找单击的单元格,同时考虑到标题的锁定线和垂直滚动条的滑块的当前位置。如果找到了按下的单元格,则行索引和该单元格的值将保存在该类的变量中。
如果单击标题(第一行),程序将退出该方法。除此以外 生成自定义消息。它包含(1)图表ID,(2)事件ID(ON_CLICK_LIST_ITEM),(3)控件ID和(4)单击的行的索引。
class 表格 : 上市 CElement { 私人的 : //--- Verarbeiten eines Klicks auf eine Tabellenzeile bool OnClickTableRow(const string clicked_object); //--- 的 Bezeichner aus dem Objektnamen entnehmen int IdFromObjectName(const string object_name); }; //+-----------------------------------------------------------------+ //| Verarbeiten eines Klicks auf eine Tabellenzeile | //+-----------------------------------------------------------------+ bool 表格 :: OnClickTableRow(const string clicked_object) { //--- Abbrechen, falls 的 Modus für das Editieren einer Tabelle aktiv ist if(!m_read_only) return(false); //--- Abbrechen, falls die Scrollbar aktiv ist if(m_scrollv.ScrollState() || m_scrollh.ScrollState()) return(false); //--- Abbrechen, falls es sich nicht um einen Klick auf eine Zelle dieser Tabelle handelt if(::StringFind(clicked_object,CElement::ProgramName()+"_table_edit_",0)<0) return(false); //--- 的 Bezeichner aus dem Objektnamen entnehmen int id=IdFromObjectName(clicked_object); //--- Abbrechen, falls 的 Bezeichner nicht übereinstimmt if(id!=CElement::Id()) return(false); //--- Suche nach den Zeilenindex int row_index=0; //--- Verschieben um einen Index, falls 的 fixierte Kopfzeilen-Modus aktiviert ist int t=(m_fix_first_row) ? 1 : 0; //--- Spalten for(int c=0; c<m_visible_columns_total; c++) { //--- Abfrage 的 aktuellen Position des Schiebereglers 的 vertikalen Scrollbar int v=m_scrollv.CurrentPos()+t; //--- Zeilen for(int r=t; r<m_visible_rows_total; r++) { //--- Falls nicht auf diese Zelle geklickt wurde if(m_columns[c].m_rows[r].Name()==clicked_object) { //--- Speichere den Index 的 Zeile m_selected_item=row_index=v; //--- Speichere die Linie 的 Zelle m_selected_item_text=m_columns[c].m_rows[r].Description(); break; } //--- Erhöhe den Zähler für die Zeilen if(v>=t && v<m_rows_total) v++; } } //--- Abbrechen, falls auf die Überschrift geklickt wurde if(m_fix_first_row && row_index<1) return(false); //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_CLICK_LIST_ITEM,CElement::Id(),m_selected_item,""); return(true); }
来做吧 表格 :: OnEndEditCell()用于处理单元格中值输入的写方法。该方法还需要首先进行一些检查。在以下情况下退出该方法:
- 未激活可编辑模式;
- 程序名称或该单元格与表格的从属关系不匹配。
- 控件ID不匹配。
如果所有检查都成功,那么我们将使用辅助方法 表格 :: ColumnIndexFromObjectName () 和 表格 :: RowIndexFromObjectName () 可见区域的单元格列和行(图形对象数组中的索引)。现在我们必须 将滚动条的滑块的当前位置添加到对象的索引 这样我们就可以得到数据数组的正确索引。然后,如果激活了固定标题的模式并且数组的索引= 0,我们仍然必须更正行索引。然后,我们需要检查单元格的值是否已更改。如果是这样,则将新值保存在相应的数据数组中,并显示一条消息,其中包含(1)图表ID,(2)事件ID( ON_END_EDIT ),(3)从列和行的索引以及当前单元格的值生成的控件ID和(4)行。 “ _”符号用作该行内的分隔符。
class 表格 : 上市 CElement { 私人的 : //--- Verarbeiten 的 manuellen Eingabe eines Wertes in eine Zelle bool OnEndEditCell(const string edited_object); //--- Abfrage des Spaltenindex aus dem Objektnamen int ColumnIndexFromObjectName(const string object_name); //--- 从对象名称查询行的索引 int RowIndexFromObjectName(const string object_name); }; //+----------------------------------------------------------------------+ //| Event für das Abschließen einer Eingabe eines Wertes in eine Zelle | //+----------------------------------------------------------------------+ bool 表格 :: OnEndEditCell(const string edited_object) { //--- Abbrechen, falls 的 Modus für die Editierbarkeit deaktiviert ist if(m_read_only) return(false); //--- Abbrechen, falls es sich nicht um einen Klick auf eine Zelle dieser Tabelle handelt if(::StringFind(edited_object,CElement::ProgramName()+"_table_edit_",0)<0) return(false); //--- 的 Bezeichner aus dem Objektnamen entnehmen int id=IdFromObjectName(edited_object); //--- Abbrechen, falls 的 Bezeichner nicht übereinstimmt if(id!=CElement::Id()) return(false); //--- Abfrage des Spalten- 和 Zeilen- Index 的 Zelle int c =ColumnIndexFromObjectName(edited_object); int r =RowIndexFromObjectName(edited_object); //--- Abfrage des Spalten- 和 Zeilen-Index in dem 那里 ta-Array int vc =c+m_scrollh.CurrentPos(); int vr =r+m_scrollv.CurrentPos(); //--- Korrektur des Zeilenindex, falls auf eine Kopfzeile geklickt wird if(m_fix_first_row && r==0) vr=0; //--- Abfrage des eingegebenen Wertes string cell_text=m_columns[c].m_rows[r].Description(); //--- Falls sich 的 Wert 的 Zelle geändert hat if(cell_text!=m_vcolumns[vc].m_vrows[vr]) { //--- Abspeichern des Wertes in dem Array SetValue(vc,vr,cell_text); //--- Eine Nachricht darüber senden ::EventChartCustom(m_chart_id,ON_END_EDIT,CElement::Id(),0,string(vc)+"_"+string(vr)+"_"+cell_text); } //--- return(true); } //+-----------------------------------------------------------------+ //| Abfrage des Spaltenindex aus dem Objektnamen | //+-----------------------------------------------------------------+ int 表格 :: ColumnIndexFromObjectName(const string object_name) { ushort u_sep=0; string result[]; int array_size=0; //--- 的 Code des Trennzeichens erhalten u_sep=::StringGetCharacter("_",0); //--- 的 String aufteilen ::StringSplit(object_name,u_sep,result); array_size=::ArraySize(result)-1; //--- Überprüfung 的 Überschreitung des ABCs if(array_size-3<0) { ::Print(PREVENTING_OUT_OF_RANGE); return(WRONG_VALUE); } //--- Rückgabe des Index des Elementes return((int)result[array_size-3]); } //+-----------------------------------------------------------------+ //| Abfrage des Zeilenindex aus dem Objektnamen | //+-----------------------------------------------------------------+ int 表格 :: RowIndexFromObjectName(const string object_name) { ushort u_sep=0; string result[]; int array_size=0; //--- 的 Code des Trennzeichens erhalten u_sep=::StringGetCharacter("_",0); //--- 的 String aufteilen ::StringSplit(object_name,u_sep,result); array_size=::ArraySize(result)-1; //--- Überprüfung 的 Überschreitung des ABCs if(array_size-2<0) { ::Print(PREVENTING_OUT_OF_RANGE); return(WRONG_VALUE); } //--- Rückgabe des Index des Elementes return((int)result[array_size-2]); }
的 表格 :: HighlightSelectedItem()如果通过相应的模式激活了线条的高亮显示,则使用此方法。突出显示的行具有不同的背景和文本颜色。这些可编辑的属性已经过检查。
在方法开始时,将进行两次检查(请看下面的程序代码)。如果满足以下条件,程序将在此处终止:
- 如果激活了单元格的可编辑模式;
- 突出显示一行的模式被禁用。
如果这些检查成功,则如果冻结列或行的标题,则再次移动索引。现在,我们应该找到选定的行,并考虑滚动条滑块图像的当前位置,为带有两个计数器(用于列和行)的双循环中的单元格背景设置适当的颜色。对于其他线条的对象,使用数组中的颜色。
class 表格 : 上市 CElement { 私人的 : //--- 突出显示所选行 void HighlightSelectedItem(void); }; //+-----------------------------------------------------------------+ //| 突出显示所选行 | //+-----------------------------------------------------------------+ void 表格 :: HighlightSelectedItem(void) { //--- Abbrechen, falls einer 的 Modi ("Nur lesen", "Auswählbare Zeile") deaktiviert ist. if(!m_read_only || !m_selectable_row) return; //--- Verschieben um einen Index, falls 的 fixierte Kopfzeilen-Modus aktiviert ist int t=(m_fix_first_row) ? 1 : 0; int l=(m_fix_first_column) ? 1 : 0; //--- Abfrage 的 aktuellen Position des Schiebereglers 的 Horizontalen Scrollbar int h=m_scrollh.CurrentPos()+l; //--- Spalten for(int c=l; c<m_visible_columns_total; c++) { //--- Abfrage 的 aktuellen Position des Schiebereglers 的 vertikalen Scrollbar int v=m_scrollv.CurrentPos()+t; //--- Zeilen for(int r=t; r<m_visible_rows_total; r++) { //--- Verschiebung 的 Tabellendaten if(v>=t && v<m_rows_total) { //--- Einstellungen unter Berücksichtigung 的 ausgewählten Zeile color back_color=(m_selected_item==v) ? m_selected_row_color : m_vcolumns[h].m_cell_color[v]; color text_color=(m_selected_item==v) ? m_selected_row_text_color : m_vcolumns[h].m_text_color[v]; //--- Einstellung 的 Text- 和 背景 farbe 的 Zelle m_columns[c].m_rows[r].Color(text_color); m_columns[c].m_rows[r].BackColor(back_color); v++; } } //--- h++; } }
另一个有用的模式是当鼠标指针悬停在其上方时突出显示该行的模式。为此, 表格 :: RowColorByHover()使用的方法。它还包括一些检查。如果没有成功完成,程序将在此时终止该方法。在以下情况下将终止:
- 当鼠标指针悬停在突出显示行的模式时,将被禁用。
- 表格编辑模式被激活。
- 当添加了控件的表单被阻止时
- 滚动条之一处于活动状态时(滑块当前正在移动)。
如果所有检查均已成功通过,则应在所有单元格中进行双循环,并根据鼠标指针当前位于哪个单元格上来更改其颜色。唯一的例外是突出显示的行。当我们到达这样的行时,仅该行的计数器增加一个,但单元格不变。
class 表格 : 上市 CElement { 私人的 : //--- Veränderung 的 Farbe 的 Zeile, wenn sich 的 Mauszeiger darüber befindet void RowColorByHover(const int x,const int y); }; //+-------------------------------------------------------------------------+ //| Veränderung 的 Zeilenfarbe, wenn sich 的 Mauszeiger darüber befindet | //+-------------------------------------------------------------------------+ void 表格 :: RowColorByHover(const int x,const int y) { //--- Abbrechen, wenn 的 Modus für das Hervorheben 的 Zeile deaktiviert ist 要么 wenn das Formular gesperrt ist if(!m_lights_hover || !m_read_only || m_wnd.IsLocked()) return; //--- Abbrechen, falls sich 的 Schieberegler einer Scrollbar gerade bewegt if(m_scrollv.ScrollState() || m_scrollh.ScrollState()) return; //--- Verschieben um einen Index, falls 的 fixierte Kopfzeilen-Modus aktiviert ist int t=(m_fix_first_row) ? 1 : 0; int l=(m_fix_first_column) ? 1 : 0; //--- Abfrage 的 aktuellen Position des Schiebereglers 的 Horizontalen Scrollbar int h=m_scrollh.CurrentPos()+l; //--- Spalten for(int c=l; c<m_visible_columns_total; c++) { //--- Abfrage 的 aktuellen Position des Schiebereglers 的 vertikalen Scrollbar int v=m_scrollv.CurrentPos()+t; //--- Zeilen for(int r=t; r<m_visible_rows_total; r++) { //--- Überprüfen, ob die Bandbreite des Arrays überschritten wird if(v>=t && v<m_rows_total) { //--- Überspringen, falls wir uns in dem "nur lesen"-Modus befinden, das Selektieren einer Zeile aktiviert ist 和 wir das selektierte Element erreicht haben if(m_selected_item==v && m_read_only && m_selectable_row) { v++; continue; } //--- Hervorheben 的 Zeile, falls sich 的 Mauszeiger darüber befindet if(x>m_columns[0].m_rows[r].X() && x<m_columns[m_visible_columns_total-1].m_rows[r].X2() && y>m_columns[c].m_rows[r].Y() && y<m_columns[c].m_rows[r].Y2()) { m_columns[c].m_rows[r].BackColor(m_cell_color_hover); } //--- Wiederherstellen 的 Standard Farbe, falls sich 的 Mauszeiger außerhalb des Bereiches dieser Zeile befindet else { if(v>=t && v<m_rows_total) m_columns[c].m_rows[r].BackColor(m_vcolumns[h].m_cell_color[v]); } //--- v++; } } //--- h++; } }
现在,我们已经检查了表的所有管理方法。您可以查看 表格 :: OnEvent()在以下程序代码中查看事件处理程序。请注意方法 表格 :: HighlightSelectedItem()之后 处理垂直滚动条滑块的运动称为.
//+-----------------------------------------------------------------+ //| Event handler | //+-----------------------------------------------------------------+ void 表格 :: OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Verarbeiten des Mauszeiger Bewegungs Events if(id==CHARTEVENT_MOUSE_MOVE) { //--- Abbrechen, falls das Element versteckt ist if(!CElement::IsVisible()) return; //---Koordinaten 和 的 Status 的 linken Maustaste int x=(int)lparam; int y=(int)dparam; m_mouse_state=(bool)int(sparam); CElement::MouseFocus(x>X() && x<X2() && y>Y() && y<Y2()); //--- Falls die Scrollbar aktiv ist if(m_scrollv.ScrollBarControl(x,y,m_mouse_state) || m_scrollh.ScrollBarControl(x,y,m_mouse_state)) //--- Verschieben 的 Tabelle UpdateTable(); //--- 突出显示所选行 HighlightSelectedItem(); //--- Veränderung 的 Farbe 的 Zeile, wenn sich 的 Mauszeiger darüber befindet RowColorByHover(x,y); return; } //--- Verarbeitung von Klicks auf Objekte if(id==CHARTEVENT_OBJECT_CLICK) { //--- Falls eine Zeile 的 Tabelle geklickt wurde if(OnClickTableRow(sparam)) { //--- 突出显示所选行 HighlightSelectedItem(); return; } //--- Falls ein Scrollbar-Button geklickt wurde if(m_scrollv.OnClickScrollInc(sparam) || m_scrollv.OnClickScrollDec(sparam) || m_scrollh.OnClickScrollInc(sparam) || m_scrollh.OnClickScrollDec(sparam)) { //--- Aktualisierung 的 那里 ten 的 Tabelle unter Berücksichtigung 的 letzten Veränderungen UpdateTable(); //--- 突出显示所选行 HighlightSelectedItem(); return; } return; } //--- Verarbeiten des Events über die Veränderung des Wertes in dem Eingabefeld if(id==CHARTEVENT_OBJECT_ENDEDIT) { OnEndEditCell(sparam); //--- Zurücksetzen 的 Farben 的 Tabelle ResetColors(); return; } }
测试编辑框表
现在一切准备就绪,可以测试editbox表了,复制上一个示例中的EA交易,并删除与文本标签表相关的所有元素。现在在自定义中创建 C程序 类的实例 表格 类并声明用于创建表的方法:
class C程序 : 上市 CWndEvents { 私人的 : //--- 的 Editbox-Tabelle 表格 m_table; //--- 私人的 : //--- 的 Editbox-Tabelle #define TABLE1_GAP_X (1) #define TABLE1_GAP_Y (42) bool CreateTable(void); };
让我们创建一个包含以下内容的表 100 列和 1000 行组成。可见列数为 6,可见线数为 15。让我们修复标题(第一行和第一列),以便在滚动滚动条的滑块时它们不会移动。鼠标指针悬停在上方时,我们将激活选择线和突出显示线的模式。
创建控件后,表数组将填充数据并进行格式化。我们以身作则 ALIGN_RIGHT 第一列的对齐方法。让我们以“斑马”样式绘制行的单元格,并且列文本的颜色以红色和蓝色完成。确保你有更新表使更改可见。
//+-----------------------------------------------------------------+ //| Erzeugung 的 Tabelle | //+-----------------------------------------------------------------+ bool C程序 :: CreateTable(void) { #define COLUMNS1_TOTAL (100) #define ROWS1_TOTAL (1000) //--- Abspeichern des Pointers des Formulars m_table.WindowPointer(m_window1); //--- Koordinaten int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y; //--- 可见列数 和 Zeilen int visible_columns_total =6; int visible_rows_total =15; //--- Vor 的 Erzeugung die Eigenschaften festlegen m_table.XSize(600); m_table.RowYSize(20); m_table.FixFirstRow(true); m_table.FixFirstColumn(true); m_table.LightsHover(true); m_table.SelectableRow(true); m_table.TextAlign( 居中对齐 ); m_table.HeadersColor(C'255,244,213'); m_table.HeadersTextColor(clrBlack); m_table.GridColor(clrLightGray); m_table.CellColorHover(clrGold); m_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL); m_table.VisibleTableSize(visible_columns_total,visible_rows_total); //--- Erzeugung des Control-Elementes if(!m_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false); //--- Einfügen in die Tabelle: // Die erste Zelle ist leer m_table.SetValue(0,0,"-"); //--- 的 Überschriften 的 Spalten for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_table.SetValue(c,r,"SYMBOL "+string(c)); } //--- 的 Überschriften 的 Zeilen, die Ausrichtung ist Rechts for(int c=0; c<1; c++) { for(int r=1; r<ROWS1_TOTAL; r++) { m_table.SetValue(c,r,"PARAMETER "+string(r)); m_table.TextAlign(c,r, ALIGN_RIGHT ); } } //--- 那里 ten- 和 Tabellen-Formatierung (Hintergrund 和 Zellenfarben) for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=1; r<ROWS1_TOTAL; r++) { m_table.SetValue(c,r,string(c)+":"+string(r)); m_table.TextColor(c,r,(c%2==0)? clrRed : clrRoyalBlue); m_table.CellColor(c,r,(r%2==0)? clrWhiteSmoke : clrWhite); } } //--- Aktualisierung 的 Tabelle um die Änderungen sichtbar zu machen m_table.UpdateTable(); //--- Hinzufügen des Objektes zu dem Array aller Objektgruppen CWnd容器::AddToElementsArray(0,m_table); return(true); }
的 C程序 :: CreateTable()方法应在应用程序的主方法中调用。 (请看下面的程序代码的缩写版):
//+----------------------------------------------------------------+ //| Erzeugung des Expert-Bedienfeldes | //+----------------------------------------------------------------+ bool C程序 :: CreateExpertPanel(void) { //--- Erzeugen des Formulars 1 für die Controls //--- Erzeugen 的 Controls: // Hauptmenü //--- Kontextmenüs //--- Erzeugen 的 Statuszeile //--- Editbox-Tabelle if(!CreateTable()) return(false); //--- Neuzeichnen des 图表 m_chart.Redraw(); return(true); }
编译程序并在图表上运行。如果正确填写了所有内容,我们将获得类似于以下屏幕截图所示的结果:
图4.测试editbox表
一切正常。但是,如果您的文字超过 63 字符长,如果在单个单元格中输入,则文本不会完全显示。终端中可以显示文本的所有图形对象的限制为 63 符号。我们用那个 C画布 非常适合解决这个问题。此类包含用于显示文本的方法,没有任何限制。我们已经将该类用于某些控件(“ Trendy me”和“上下文”菜单)。项目:
那里 63 字符经常不足,第三个表是使用 C画布 类绘制。
渲染表控件
呈现的表对每个单元格的字符数没有限制。此外,无需更改表格的可见区域即可配置每列的宽度。对于我们前面讨论的其他类型的表,这非常困难。这样我们就可以显示呈现表的一些优点:
- 每个单元的符号数没有限制;
- 每个列的宽度可以分别指定。
- 只会有一个物体(OBJ_BITMAP_LABEL)用来生成表格,而不是生成各种对象,就像文本标签( OBJ_LABEL )或编辑框( OBJ_EDIT )的情况是。
文本标签表由以下组件组成:
- 背景
- 渲染表
- 垂直滚动条。
- 水平滚动条。
图5.呈现表的组件
让我们检查用于创建此类表的类的代码。
C画布 Table 类的开发
来做吧 CT选项 创建一个结构以保存表的值和属性:
//+-----------------------------------------------------------------+ //| Klasse für die Erzeugung einer gerenderten Tabelle | //+-----------------------------------------------------------------+ class C画布 Table : 上市 CElement { 私人的 : //--- Array für die Werte 和 Eigenschaften 的 Tabelle struct CT选项 { string m_vrows[]; int m_width; ENUM_ALIGN_MODE m_text_align; }; CT选项 m_vcolumns[]; };
的 CT选项 设置表的基本大小(列和行的总数)时,用标准值初始化结构的变量。我们把所有列的宽度 100 像素固定,并且单元格中的对齐方式为 居中对齐 .
class C画布 Table : 上市 CElement { 上市 : //--- Festlegen 的 Größe 的 Tabelle void TableSize(const int columns_total,const int rows_total); }; //+-----------------------------------------------------------------+ //| Legt die Größe 的 Tabelle fest | //+-----------------------------------------------------------------+ void C画布 Table ::TableSize(const int columns_total,const int rows_total) { //--- Es muss mindestens eine Spalte geben m_columns_total=(columns_total<1) ? 1 : columns_total; //--- Es muss mindestens zwei Zeilen geben m_rows_total=(rows_total<2) ? 2 : rows_total; //--- Festlegen 的 Größe 的 Spalten-Arrays ::ArrayResize(m_vcolumns,m_columns_total); //--- Festlegen 的 Größe 的 Zeilen-Arrays for(int i=0; i<m_columns_total; i++) { ::ArrayResize(m_vcolumns[i].m_vrows,m_rows_total); //--- Initialisierung 的 Spalteneigenschaften mit den Standardwerten m_vcolumns[i].m_width =100; m_vcolumns[i].m_text_align = 居中对齐 ; } }
让我们只使用允许我们的方法 宽度 要么 文字对齐 设置表的大小后,对某些列(如有必要)进行设置。为此,您要做的就是初始化数组并将其传递给适当的方法。一个例子如下所示:
class C画布 Table : 上市 CElement { 上市 : //--- Festlegen 的 (1) 文字对齐 和 (2) 的 Breite für jede Spalte void TextAlign(const ENUM_ALIGN_MODE &array[]); void ColumnsWidth(const int &array[]); }; //+----------------------------------------------------------------+ //| Füllt das array mit den Textausrichtungs-Modi | //+----------------------------------------------------------------+ void C画布 Table ::TextAlign(const ENUM_ALIGN_MODE &array[]) { int total=0; int array_size=::ArraySize(array); //--- Abbrechen, falls ein Array 的 Größe 0 übergeben wurde if(array_size<1) return; //--- Einstellen des Wertes, um ein Überschreiten 的 Bandbreite des Arrays zu verhindern total=(array_size<m_columns_total)? array_size : m_columns_total; //--- Abspeichern 的 Werte in 的 Struktur for(int c=0; c<total; c++) m_vcolumns[c].m_text_align=array[c]; } //+----------------------------------------------------------------+ //| Sylt das Array mit den Spaltenbreiten | //+----------------------------------------------------------------+ void C画布 Table ::ColumnsWidth(const int &array[]) { int total=0; int array_size=::ArraySize(array); //--- Abbrechen, falls ein Array 的 Größe 0 übergeben wurde if(array_size<1) return; //--- Einstellen des Wertes, um ein Überschreiten 的 Bandbreite des Arrays zu verhindern total=(array_size<m_columns_total)? array_size : m_columns_total; //--- Abspeichern 的 Werte in 的 Struktur for(int c=0; c<total; c++) m_vcolumns[c].m_width=array[c]; }
在继续创建表之前,必须指定相对于指定参数(所有列的宽度,所有行的高度和滚动条的存在)的总大小以及可见区域的大小。为此,我们编写如下所示的方法 C画布 Table :: CalculateTableSize ():
class C画布 Table : 上市 CElement { 私人的 : //--- Gesamtgröße 和 die Größe des sichtbaren Bereiches 的 Tabelle int m_table_x_size; int m_table_y_size; int m_table_visible_x_size; int m_table_visible_y_size; //--- 私人的 : //--- Berechnung 的 Größe 的 Tabelle void CalculateTableSize(void); }; //+-----------------------------------------------------------------+ //| Berechnung 的 Größe 的 Tabelle | //+-----------------------------------------------------------------+ void C画布 Table :: CalculateTableSize(void) { //--- Berechnung 的 Gesamtbreite 的 Tabelle m_table_x_size=0; for(int c=0; c<m_columns_total; c++) m_table_x_size=m_table_x_size+m_vcolumns[c].m_width; //--- Breite 的 Tabelle mit einer vertikalen Scrollbar int x_size=(m_rows_total>m_visible_rows_total) ? m_x_size-m_scrollh.ScrollWidth() : m_x_size-2; //--- Falls 宽度 aller Spalten kleiner ist als 宽度 的 Tabelle, dann wird 宽度 的 Tabelle verwendet if(m_table_x_size<m_x_size) m_table_x_size=x_size; //--- Berechnung 的 Gesamthöhe 的 Tabelle m_table_y_size=m_cell_y_size*m_rows_total-(m_rows_total-1); //--- Festlegen 的 Rahmengröße, um einen Teil des Bildes anzuzeigen (sichtbarer Bereich 的 Tabelle) m_table_visible_x_size=x_size; m_table_visible_y_size=m_cell_y_size*m_visible_rows_total-(m_visible_rows_total-1); //--- Falls es eine horizontale Scrollbar gibt, dann wird die Größe des Controls entlang 的 y-Achse angepasst int y_size=m_cell_y_size*m_visible_rows_total+2-(m_visible_rows_total-1); m_y_size=(m_table_x_size>m_table_visible_x_size) ? y_size+m_scrollh.ScrollWidth()-1 : y_size; }
在计算了表格的大小并创建了画布之后,我们需要开发一种绘制表格网格和单元格文本的方法。为了绘制网格,我们将其写为 C画布 Table :: DrawGrid() 方法。首先在第一个循环中绘制水平网格线,然后在第二个循环中绘制垂直网格线。
class C画布 Table : 上市 CElement { 私人的 : //--- Farbe des Gitters color m_grid_color; //--- 的 Größe (Höhe) 的 Zellen int m_cell_y_size; //--- 上市 : //--- Farbe des Gitters void GridColor(const color clr) { m_grid_color=clr; } //--- 私人的 : //--- Zeichnen des Gitters void DrawGrid(void); }; //+-----------------------------------------------------------------+ //| Zeichnen des Gitters | //+-----------------------------------------------------------------+ void C画布 Table :: DrawGrid(void) { //--- Farbe des Gitters uint clr=::ColorToARGB(m_grid_color,255); //--- 的 Größe des Canvas für das Zeichnen int x_size =m_canvas.XSize()-1; int y_size =m_canvas.YSize()-1; //--- Koordinaten int x1=0,x2=0,y1=0,y2=0; //--- Horizontale Linien x1=0; y1=0; x2=x_size; y2=0; for(int i=0; i<=m_rows_total; i++) { m_canvas.Line(x1,y1,x2,y2,clr); y2=y1+=m_cell_y_size-1; } //--- Vertikale Linien x1=0; y1=0; x2=0; y2=y_size; for(int i=0; i<m_columns_total; i++) { m_canvas.Line(x1,y1,x2,y2,clr); x2=x1+=m_vcolumns[i].m_width; } //--- Rechts x1=x_size; y1=0; x2=x_size; y2=y_size; m_canvas.Line(x1,y1,x2,y2,clr); }
的 C画布 Table :: DrawText()绘制文本的方法比绘制网格的方法稍微复杂一些。我们不仅应考虑当前列中文本的对齐方式,而且还应考虑前一列中文本的对齐方式,以便能够正确计算缩进量。我们从 10 像素 从单元格的角处进行左右对齐。单元格顶部的缩进是 3 像素点 。下面是此方法的详细程序代码:
class C画布 Table : 上市 CElement { 私人的 : //--- 文字颜色 color m_cell_text_color; //--- 上市 : //--- Textfarbe 的 Tabelle void TextColor(const color clr) { m_cell_text_color=clr; } //--- 私人的 : //--- Zeichnen des Textes void DrawText(void); }; //+-----------------------------------------------------------------+ //| Zeichnen des Textes | //+-----------------------------------------------------------------+ void C画布 Table :: DrawText(void) { //--- Für die Berechnung 的 Koordinaten 和 des Offsets int x =0; int y =0; uint text_align =0; int column_offset =0; int cell_x_offset =10; int cell_y_offset =3; //--- 文字颜色 uint clr=::ColorToARGB(m_cell_text_color,255); //--- Eigenschaften 的 Schrift m_canvas.FontSet(FONT,-80,FW_NORMAL); //--- Spalten for(int c=0; c<m_columns_total; c++) { //--- Berechnung des Offsets für die erste Spalte if(c==0) { //--- 的 Ausrichtung 内容 einer Zelle basiert auf dem Modus 的 für die Spalte gesetzt ist switch(m_vcolumns[0].m_text_align) { //--- Mittig case 居中对齐 : column_offset=column_offset+m_vcolumns[0].m_width/2; x=column_offset; break; //--- Rechts case ALIGN_RIGHT : column_offset=column_offset+m_vcolumns[0].m_width; x=column_offset-cell_x_offset; break; //--- 链接 s case ALIGN_LEFT : x=column_offset+cell_x_offset; break; } } //--- 的 Berechnung 的 Offset für alle Spalten mit Ausnahme 的 ersten else { //--- 的 Ausrichtung 内容 einer Zelle basiert auf dem Modus 的 für die Spalte gesetzt ist switch(m_vcolumns[c].m_text_align) { //--- Mittig case 居中对齐 : //--- 的 Berechnung des Offset relativ zu 的 Ausrichtung in 的 vorherigen Spalte switch(m_vcolumns[c-1].m_text_align) { case 居中对齐 : column_offset=column_offset+(m_vcolumns[c-1].m_width/2)+(m_vcolumns[c].m_width/2); break; case ALIGN_RIGHT : column_offset=column_offset+(m_vcolumns[c].m_width/2); break; case ALIGN_LEFT : column_offset=column_offset+m_vcolumns[c-1].m_width+(m_vcolumns[c].m_width/2); break; } //--- x=column_offset; break; //--- Rechts case ALIGN_RIGHT : //--- 的 Berechnung des Offset relativ zu 的 Ausrichtung in 的 vorherigen Spalte switch(m_vcolumns[c-1].m_text_align) { case 居中对齐 : column_offset=column_offset+(m_vcolumns[c-1].m_width/2)+m_vcolumns[c].m_width; x=column_offset-cell_x_offset; break; case ALIGN_RIGHT : column_offset=column_offset+m_vcolumns[c].m_width; x=column_offset-cell_x_offset; break; case ALIGN_LEFT : column_offset=column_offset+m_vcolumns[c-1].m_width+m_vcolumns[c].m_width; x=column_offset-cell_x_offset; break; } //--- break; //--- 链接 s case ALIGN_LEFT : //--- 的 Berechnung des Offset relativ zu 的 Ausrichtung in 的 vorherigen Spalte switch(m_vcolumns[c-1].m_text_align) { case 居中对齐 : column_offset=column_offset+(m_vcolumns[c-1].m_width/2); x=column_offset+cell_x_offset; break; case ALIGN_RIGHT : x=column_offset+cell_x_offset; break; case ALIGN_LEFT : column_offset=column_offset+m_vcolumns[c-1].m_width; x=column_offset+cell_x_offset; break; } //--- break; } } //--- Zeilen for(int r=0; r<m_rows_total; r++) { //--- y+=(r>0) ? m_cell_y_size-1 : cell_y_offset; //--- switch(m_vcolumns[c].m_text_align) { case 居中对齐 : text_align=TA_CENTER|TA_TOP; break; case ALIGN_RIGHT : text_align=TA_RIGHT|TA_TOP; break; case ALIGN_LEFT : text_align=TA_LEFT|TA_TOP; break; } //--- Zeichnen des Textes m_canvas.TextOut(x,y,m_vcolumns[c].m_vrows[r],clr,text_align); } //--- Zurücksetzen 的 y-Koordinate für den nächsten Durchlauf y=0; } }
在前两种表格类型中,我们研究了使用滚动条通过更改表格可见区域中的对象(文本标签和编辑框)的值来完成移动。在这里,我们移动矩形框以获得图像的可见性。换句话说,表(图像)的大小最初等于所有列的总和和所有行的高度。这是原始图像的大小,可以在其中移动框以提高可见度。可见性框架的大小可以随时更改,但在此处创建控件后将直接更改。 C画布 Table :: CreateCells()方法已建立。
框架的大小可以通过属性进行调整 OBJPROP_XSIZE 和 OBJPROP_YSIZE 可以通过属性设置框架的位移(在图像内) OBJPROP_XOFFSET 和 OBJPROP_YOFFSET 被控制。 (请参见下面的示例):
//--- Festlegen 的 Größe des sichtbaren Bereiches ::ObjectSetInteger(m_chart_id,name,OBJPROP_XSIZE,m_table_visible_x_size); ::ObjectSetInteger(m_chart_id,name,OBJPROP_YSIZE,m_table_visible_y_size); //--- Festlegen des Offsets für den Rahmen innerhalb des Bildes entlang 的 X 和 Y-Achse ::ObjectSetInteger(m_chart_id,name,OBJPROP_XOFFSET,0); ::ObjectSetInteger(m_chart_id,name,OBJPROP_YOFFSET,0);
让我们做个简单的方法 C画布 Table :: ShiftTable()相对于滚动条滑块的当前位置移动框架。垂直移位等于线的高度,但是水平移位以像素为单位(请参见以下程序示例):
class C画布 Table : 上市 CElement { 上市 : //--- Verschiebung 的 Tabelle, relativ zu den Positionen 的 Scrollbars void ShiftTable(void); }; //+-----------------------------------------------------------------+ //| Verschiebung 的 Tabelle relativ zu den Scrollbars | //+-----------------------------------------------------------------+ void C画布 Table :: ShiftTable(void) { //--- Abfrage 的 aktuellen Positionen 的 Schieberegler 的 vertikalen 和 horizontalen Scrollbars int h=m_scrollh.CurrentPos(); int v=m_scrollv.CurrentPos(); //--- Berechnung 的 Position 的 Tabelle in Relation zu den Schiebereglern 的 Scrollbars long c=h; long r=v*(m_cell_y_size-1); //--- Verschieben 的 Tabelle ::ObjectSetInteger(m_chart_id,m_canvas.Name(),OBJPROP_XOFFSET,c); ::ObjectSetInteger(m_chart_id,m_canvas.Name(),OBJPROP_YOFFSET,r); }
一般 C画布 Table :: DrawTable()绘制表格的方法如下:
class C画布 Table : 上市 CElement { 上市 : //--- Zeichne die Tabelle unter Berücksichtigung 的 letzten Änderungen void DrawTable(void); }; //+-----------------------------------------------------------------+ //| Zeichnen 的 Tabelle | //+-----------------------------------------------------------------+ void C画布 Table :: DrawTable(void) { //--- 的 背景 transparent machen m_canvas.Erase(::ColorToARGB(clrNONE,0)); //--- Zeichnen des Gitters DrawGrid(); //--- Zeichnen des Textes DrawText(); //--- 那里 rstellen 的 zuletzt gezeichneten Veränderungen m_canvas.Update(); //--- Verschiebung 的 Tabelle in Relation zu den Scrollbars ShiftTable(); }
现在一切就绪,可以测试该表了。
测试渲染的表
复制以前的EA,并删除与 表格 餐桌架。现在在自定义中创建 C程序 类的实例 C画布 Table 类并声明(1) C程序 :: CreateCanvasTable()创建表的方法以及(2)缩进,如以下示例所示:
class C程序 : 上市 CWndEvents { 私人的 : //--- 渲染表 C画布 Table m_canvas_table; //--- 私人的 : //--- 渲染表 #define TABLE1_GAP_X (1) #define TABLE1_GAP_Y (42) bool CreateCanvasTable(void); };
我们用一张桌子 15 列和 1000 生成线。可见线数为 16。我们不需要设置可见列的数量,因为水平移动以像素为单位。在这种情况下,应明确指定表格可见区域的宽度。让他们上 601 设置像素。
例如,让我们设置所有列的宽度(前两列除外) 70 设置像素。第一和第二列的宽度等于 100 和 90 像素集。在所有列中(前三列除外),文本均显示在中间。在第一和第三列中,对齐方式是正确的,而在第二列中,对齐方式则是左侧。完整的程序代码 C程序 :: CreateCanvasTable()方法显示在以下程序代码中:
//+-----------------------------------------------------------------+ //| Erzeugung 的 gerenderten Tabelle | //+-----------------------------------------------------------------+ bool C程序 :: CreateCanvasTable(void) { #define COLUMNS1_TOTAL 15 #define ROWS1_TOTAL 1000 //--- Abspeichern des Pointers des Formulars m_canvas_table.WindowPointer(m_window1); //--- Koordinaten int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y; //--- Anzahl 的 sichtbaren Zeilen int visible_rows_total=16; //--- Array mit Spaltenbreiten int width[COLUMNS1_TOTAL]; ::ArrayInitialize(width,70); width[0]=100; width[1]=90; //--- Array für die Textausrichtung in den Spalten ENUM_ALIGN_MODE align[COLUMNS1_TOTAL]; ::ArrayInitialize(align, 居中对齐 ); align[0]= ALIGN_RIGHT ; align[1]=ALIGN_LEFT; align[2]= ALIGN_RIGHT ; //--- Vor 的 Erzeugung die Eigenschaften festlegen m_canvas_table.XSize(601); m_canvas_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL); m_canvas_table.VisibleTableSize(0,visible_rows_total); m_canvas_table.TextAlign(align); m_canvas_table.ColumnsWidth(width); m_canvas_table.GridColor(clrLightGray); //--- Tabelle mit 那里 ten auffüllen for(int c=0; c<COLUMNS1_TOTAL; c++) for(int r=0; r<ROWS1_TOTAL; r++) m_canvas_table.SetValue(c,r,string(c)+":"+string(r)); //--- Erzeugen des Controls if(!m_canvas_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false); //--- Hinzufügen des Objektes zu dem Array aller Objektgruppen CWnd容器::AddToElementsArray(0,m_canvas_table); return(true); }
该方法必须在用于生成图形界面的main方法中调用。
//+-----------------------------------------------------------------+ //| Erzeugung des Trading-Panels | //+-----------------------------------------------------------------+ bool C程序 :: CreateExpertPanel(void) { //--- Erzeugen des Formulars 1 für die Controls //--- Erzeugen 的 Controls: // Hauptmenü //--- Kontextmenüs //--- Erzeugen 的 Statuszeile //--- Erzeugung 的 gerenderten Tabelle if(!CreateCanvasTable()) return(false); //--- Neuzeichnen des 图表 m_chart.Redraw(); return(true); }
编译程序并在图表上运行。以下屏幕截图显示了结果:
图6.在EA中测试呈现的表
在本系列第一部分的第五章中,我们测试了脚本中表单的使用。没有滚动条的表可以在这种类型的MQL应用程序中使用。例如,您可以将呈现的表添加到表单的脚本中,并将数据全部 250 更新毫秒。将前面显示的表添加到自定义类。此外,程序代码必须与 C程序 :: OnEvent()脚本事件处理程序,如下所示, 要添加。现在,第二列中的数据以指定的时间间隔更改。
//+-----------------------------------------------------------------+ //| Events | //+-----------------------------------------------------------------+ void C程序 :: OnEvent(const int milliseconds) { static int count =0; // Counter string str =""; // Header row //--- 的 Kopfzeile zeigt den Prozess switch(count) { case 0 : str="SCRIPT PANEL"; break; case 1 : str="SCRIPT PANEL ."; break; case 2 : str="SCRIPT PANEL .."; break; case 3 : str="SCRIPT PANEL ... "; break; } //--- Aktualisierung 的 Kopfzeile m_window.CaptionText(str); //--- Änderung 的 那里 ten 的 ersten Spalte for(int r=0; r<13; r++) m_canvas_table.SetValue(1,r,string(::rand () )); //--- Anzeigen 的 neuen Tabellendaten m_canvas_table.DrawTable(); //--- Neuzeichnen des 图表 m_chart.Redraw(); //--- Erhöhung des Zählers count++; //--- Zurücksetzen auf Null, falls 3 überschritten wird if(count>3) count=0; //--- Pause ::Sleep(milliseconds); }
编译程序并在图表上运行此脚本现在,您应该看到以下内容:
图7.在脚本中测试呈现的表
我们一直在开发 C画布 Table 用于创建渲染表的完整类。现在该是一些初步结果的时候了。
结论
在本文中,我们讨论了用于创建重要接口元素(表)的三个类。这些类别中的每一个都有自己的特定特征,最适合特定情况。例如,CTable类提供了开发带有可编辑框的表的可能性,从而可以对这些框进行格式化,从而使它们看起来非常用户友好。另一方面,CCanvasTable类使您可以绕过单元格中字符数的限制,并提供为每列指定单独宽度的选项。这些不是表的最终版本。如有必要,可以在以后进行扩展。
在下一篇文章中,我们将讨论用于开发选项卡控件的类,这些类在图形界面中通常使用。
您可以下载并测试第七部分的所有材料。如果您对本材料的使用有任何疑问,可以先参考该库中文章的详细说明,或者在本文的评论中提出您的问题。
第七部分文章(章节)清单:
由MetaQuotes Software Corp.从俄语翻译而来。
来源文章: //www.tbxfkj.com/ru/articles/2500
附加的文件 |
easyandfastgui_mql4.zip
(313.25 KB)
easyandfastgui_mql5.zip
(313.88 KB)