文章 "图形界面 X: 标准图表控件 (集成编译 4)" - 页 2 123456 新评论 Anatoli Kazharski 2016.10.19 12:10 #11 Artyom Trishkin:阿纳托利,请告诉我错误的原因是什么?2016.10.19 03:09:04.993 TestTable (EURUSD,H1) invalid pointer access in 'Scrolls.mqh' (698,10)更新前一切正常。现在,在创建 CTable 表时却出现了这个错误。请告诉我哪里出错了--我已经打印了每一行--界面是建好了,但在某个地方出了问题,....。错误。档案中的文件包含一个示例。我忘了更正,因为之前在CCanvasTable 类中已经更正过了。在CTable 类中,您需要将当前版本的CreateScrollV() 和CreateScrollH() 方法替换为下表所示的方法://+------------------------------------------------------------------+//|| 创建垂直滚动条//+------------------------------------------------------------------+bool CTable::CreateScrollV(void) {//--- 保存表单指针 m_scrollv.WindowPointer(m_wnd);//--- 坐标 int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth(); int y=CElement::Y();//--- 设置尺寸 m_scrollv.Id(CElement::Id()); m_scrollv.IsDropdown(CElement::IsDropdown()); m_scrollv.XSize(m_scrollv.ScrollWidth()); m_scrollv.YSize((m_columns_total>m_visible_columns_total)? m_y_size-m_scrollv.ScrollWidth()+1 : m_y_size); m_scrollv.AnchorRightWindowSide(m_anchor_right_window_side); m_scrollv.AnchorBottomWindowSide(m_anchor_bottom_window_side);//--- 创建滚动条 if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total)) return(false);//--- 如果现在不需要,请隐藏 if(m_rows_total<=m_visible_rows_total) m_scrollv.Hide();//--- return(true); }//+------------------------------------------------------------------+//|| 创建水平滚动条//+------------------------------------------------------------------+bool CTable::CreateScrollH(void) {//--- 保存表单指针 m_scrollh.WindowPointer(m_wnd);//--- 坐标 int x=CElement::X(); int y=(m_anchor_bottom_window_side)? m_y-m_area.Y_Size()+m_scrollh.ScrollWidth() : CElement::Y2()-m_scrollh.ScrollWidth();//--- 设置尺寸 m_scrollh.Id(CElement::Id()); m_scrollh.IsDropdown(CElement::IsDropdown()); m_scrollh.XSize((m_rows_total>m_visible_rows_total)? m_area.XSize()-m_scrollh.ScrollWidth()+1 : m_area.XSize()); m_scrollh.YSize(m_scrollh.ScrollWidth()); m_scrollh.AnchorRightWindowSide(m_anchor_right_window_side); m_scrollh.AnchorBottomWindowSide(m_anchor_bottom_window_side);//--- 创建滚动条 if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total)) return(false);//--- 如果现在不需要,请隐藏 if(m_columns_total<=m_visible_columns_total) m_scrollh.Hide();//--- return(true); }//---CLabelsTable 类也需要做类似的更改。这些修正将在下一次更新中进行。 Discussion of article "Graphical 文章 "图形界面 X: 时间控件, Discussion of article "Graphical Artyom Trishkin 2016.10.19 12:15 #12 Anatoli Kazharski:之前在CCanvasTable 类中做过更正,我忘了更正。在CTable 类中,您需要将当前版本的CreateScrollV() 和CreateScrollH() 方法替换为下表所示的方法:...//---CLabelsTable 类也需要进行类似的更改。这些修正将在下一次更新中进行。 О!谢谢! Artyom Trishkin 2016.10.23 22:39 #13 Anatoli Kazharski:之前在CCanvasTable 类中做过更正,我忘了更正。在CTable 类中,您需要将当前版本的CreateScrollV() 和CreateScrollH() 方法替换为下表所示的方法://+------------------------------------------------------------------+//|| 创建垂直滚动条//+------------------------------------------------------------------+bool CTable::CreateScrollV(void) {//--- 保存表单指针 m_scrollv.WindowPointer(m_wnd);//--- 坐标 int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth(); int y=CElement::Y();//--- 设置尺寸 m_scrollv.Id(CElement::Id()); m_scrollv.IsDropdown(CElement::IsDropdown()); m_scrollv.XSize(m_scrollv.ScrollWidth()); m_scrollv.YSize((m_columns_total>m_visible_columns_total)? m_y_size-m_scrollv.ScrollWidth()+1 : m_y_size); m_scrollv.AnchorRightWindowSide(m_anchor_right_window_side); m_scrollv.AnchorBottomWindowSide(m_anchor_bottom_window_side);//--- 创建滚动条 if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total)) return(false);//--- 如果现在不需要,请隐藏 if(m_rows_total<=m_visible_rows_total) m_scrollv.Hide();//--- return(true); }//+------------------------------------------------------------------+//|| 创建水平滚动条//+------------------------------------------------------------------+bool CTable::CreateScrollH(void) {//--- 保存表单指针 m_scrollh.WindowPointer(m_wnd);//--- 坐标 int x=CElement::X(); int y=(m_anchor_bottom_window_side)? m_y-m_area.Y_Size()+m_scrollh.ScrollWidth() : CElement::Y2()-m_scrollh.ScrollWidth();//--- 设置尺寸 m_scrollh.Id(CElement::Id()); m_scrollh.IsDropdown(CElement::IsDropdown()); m_scrollh.XSize((m_rows_total>m_visible_rows_total)? m_area.XSize()-m_scrollh.ScrollWidth()+1 : m_area.XSize()); m_scrollh.YSize(m_scrollh.ScrollWidth()); m_scrollh.AnchorRightWindowSide(m_anchor_right_window_side); m_scrollh.AnchorBottomWindowSide(m_anchor_bottom_window_side);//--- 创建滚动条 if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total)) return(false);//--- 如果现在不需要,请隐藏 if(m_columns_total<=m_visible_columns_total) m_scrollh.Hide();//--- return(true); }//---CLabelsTable 类也需要做类似的更改。下一次更新中将进行修复。Anatoly,修改已经完成。以 MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5 中的表格为例,修改 Program.mqh 中的表格,使行数与可见行数一致,或列数与可见列数一致,或两者都一致。例如//+------------------------------------------------------------------+//|| 创建表格|//+------------------------------------------------------------------+bool CProgram::CreateTable(void) {#define COLUMNS1_TOTAL (6)#define ROWS1_TOTAL (15)//--- 保存指向表单的指针 m_table.WindowPointer(m_window1);//--- 坐标 int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y;//--- 可见列数和行数 int visible_columns_total =6; int visible_rows_total =15;//--- 创建前设置属性 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(ALIGN_CENTER); m_table.HeadersColor(C'255,244,213'); m_table.HeadersTextColor(clrBlack); m_table.CellColorHover(clrGold); m_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL); m_table.VisibleTableSize(visible_columns_total,visible_rows_total);//--- 创建一个控件 if(!m_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false);//--- 让我们填写表格:// 第一个单元格为空 m_table.SetValue(0,0,"-");//--- 栏目标题 for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_table.SetValue(c,r,"SYMBOL "+string(c)); }//--- 行标题,文本对齐方式 - 向右 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); } }//--- 数据和表格格式化(背景颜色和单元格颜色) 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); } }//-- 更新表格以显示变化 m_table.UpdateTable();//--- 将对象添加到对象组的通用数组中 CWndContainer::AddToElementsArray(0,m_table); return(true); }//+------------------------------------------------------------------+编译并运行示例,点击表格的最低行(一切正常),然后再次点击。第二次点击时,弹出了一个错误:2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1091,86)怎么办? Discussion of article "Graphical 文章 "图形界面 V: 组合框控件 图形界面 VII: 表格控件 (第一章) Anatoli Kazharski 2016.10.24 15:32 #14 Artyom Trishkin:阿纳托利,修改已经完成。以 MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5 中的示例为例,修改 Program.mqh 中的表格,使行数与可见行数一致,或列数与可见列数一致,或两者都一致。例如,像这样...编译并运行示例,点击表格的最低行(一切正常),然后再次点击。第二次点击时出现错误:2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1091,86)怎么办?在CScrollH 和 CScrollV 类的ScrollBarControl() 方法中,需要对元素的可见性添加额外检查,如下表所示://+------------------------------------------------------------------+//| 滚动控制|//+------------------------------------------------------------------+bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state) {//--- 如果没有表单指针,则退出 if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false);//--- 如果表单被其他元素挡住,则退出 if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false);//--- 如果项目被隐藏,则退出 if(!CElement::IsVisible()) return(false);//--- 检查滑块上的焦点 m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2());//-- 检查并记住鼠标按钮的状态 CScroll::CheckMouseButtonState(mouse_state);//--- 更改列表滚动条的颜色 CScroll::ChangeObjectsColor();//--- 如果控制传递给了滚动条,则定义滑块位置 if(CScroll::ScrollState()) { //--- 移动滑块 OnDragThumb(x); //--- 更改滑块位置编号 CalculateThumbPos(); return(true); } return(false); }//---该修复将在下一次库更新中提供。 Discussion of article "Graphical 文章 "图形界面 X: 文本编辑框, 图形界面 V: 垂直与水平滚动条 (第一章) Artyom Trishkin 2016.10.24 20:45 #15 Anatoli Kazharski:在CScrollH 和CScrollV 类的ScrollBarControl() 方法中,我们需要对元素的可见性添加额外的检查,如下表所示:...该修复将在下一次库更新中提供。谢谢。我做了这些修改:在 Scrolls.mqh 文件的CScrollH 和 CScrollV类中 添加了几行://+------------------------------------------------------------------+//| 滑块控制|//+------------------------------------------------------------------+bool CScrollV::ScrollBarControl(const int x,const int y,const bool mouse_state) {//--- 如果没有表单指针,则退出 if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false);//--- 如果表单未锁定且标识符匹配 if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false);//--- 如果项目被隐藏,则退出 if(!CElement::IsVisible()) return(false);//--- 检查滑块上的焦点 m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2());//-- 检查并记住鼠标按钮的状态 CScroll::CheckMouseButtonState(mouse_state);//--- 更改滑块的颜色 CScroll::ChangeObjectsColor();//--- 如果控制传递给了滚动条,则定义滑块位置 if(CScroll::ScrollState()) { //--- 移动滑块 OnDragThumb(y); //--- 更改滑块位置编号 CalculateThumbPos(); return(true); }//--- return(false); }//+------------------------------------------------------------------+//+------------------------------------------------------------------+//| 滚动控制|//+------------------------------------------------------------------+bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state) {//--- 如果没有表单指针,则退出 if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false); if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false);//--- 如果项目被隐藏,则退出 if(!CElement::IsVisible()) return(false);//--- 检查滑块上的焦点 m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2());//-- 检查并记住鼠标按钮的状态 CScroll::CheckMouseButtonState(mouse_state);//--- 更改列表滚动条的颜色 CScroll::ChangeObjectsColor();//--- 如果控制传递给了滚动条,则定义滑块位置 if(CScroll::ScrollState()) { //--- 移动滑块 OnDragThumb(x); //--- 更改滑块位置编号 CalculateThumbPos(); return(true); } return(false); }//+------------------------------------------------------------------+我编译并运行了来自 \MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5 的相同测试文件,其中我更改了 Program.mqh 中的建表函数,使所有列和行的数量与可见列和行的数量一致://+------------------------------------------------------------------+//|| 创建表格|//+------------------------------------------------------------------+bool CProgram::CreateTable(void) {#define COLUMNS1_TOTAL (6)#define ROWS1_TOTAL (15)//--- 保存指向表单的指针 m_table.WindowPointer(m_window1);//--- 坐标 int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y;//--- 可见列数和行数 int visible_columns_total =6; int visible_rows_total =15;//--- 创建前设置属性 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(ALIGN_CENTER); m_table.HeadersColor(C'255,244,213'); m_table.HeadersTextColor(clrBlack); m_table.CellColorHover(clrGold); m_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL); m_table.VisibleTableSize(visible_columns_total,visible_rows_total);//--- 创建一个控件 if(!m_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false);//--- 让我们填写表格:// 第一个单元格为空 m_table.SetValue(0,0,"-");//--- 栏目标题 for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_table.SetValue(c,r,"SYMBOL "+string(c)); }//--- 行标题,文本对齐方式 - 向右 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); } }//--- 数据和表格格式化(背景颜色和单元格颜色) 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); } }//-- 更新表格以显示变化 m_table.UpdateTable();//--- 将对象添加到对象组的通用数组中 CWndContainer::AddToElementsArray(0,m_table); return(true); }//+------------------------------------------------------------------+编译并运行 ChartWindow02.ex5我们点击了几次表格的最低行,得到的结果是在数组外飞行:2016.10.25 01:39:22.899 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1096,86) 看起来没有任何变化吗? Discussion of article "Graphical 文章 "图形界面 V: 组合框控件 图形界面 VII: 表格控件 (第一章) Anatoli Kazharski 2016.10.24 21:18 #16 Artyom Trishkin:... 所以什么都没变?在我做了更改之后,它就不再播放了。我可能还做了其他改动,但我不记得了。我没有小修改的历史记录。 为了以防万一,如果CScroll::Show() 和CScroll::Hide() 方法不同,请尝试用这些版本替换它们://+------------------------------------------------------------------+//| 显示菜单项|//+------------------------------------------------------------------+void CScroll::Show(void) {//--- 如果列表项的数量不大于列表可见部分的数量,则退出 if(m_items_total<=m_visible_items_total) return;//--- m_area.Timeframes(OBJ_ALL_PERIODS); m_bg.Timeframes(OBJ_ALL_PERIODS); m_inc.Timeframes(OBJ_ALL_PERIODS); m_dec.Timeframes(OBJ_ALL_PERIODS); m_thumb.Timeframes(OBJ_ALL_PERIODS);//-- 更新对象的位置 Moving(m_wnd.X(),m_wnd.Y(),true);//--- 可见性状态 CElement::IsVisible(true); }//+------------------------------------------------------------------+//| 隐藏菜单项|//+------------------------------------------------------------------+void CScroll::Hide(void) { m_area.Timeframes(OBJ_NO_PERIODS); m_bg.Timeframes(OBJ_NO_PERIODS); m_inc.Timeframes(OBJ_NO_PERIODS); m_dec.Timeframes(OBJ_NO_PERIODS); m_thumb.Timeframes(OBJ_NO_PERIODS);//--- 可见性状态 CElement::IsVisible(false); } //---如果没有帮助,你只能等待下一次更新了。 Discussion of article "Graphical 图形界面 V: 垂直与水平滚动条 (第一章) 图形界面 I: 用于表单按钮的函数与删除界面元素 (第四章) Artyom Trishkin 2016.10.24 21:36 #17 Anatoli Kazharski:但在我做了更改之后,它就不再播放了。我可能还做了其他改动,但我不记得了。我没有标记小修改的历史记录。 为了以防万一,如果CScroll::Show() 和CScroll::Hide() 方法不同,请尝试用这些版本替换它们://+------------------------------------------------------------------+//| 显示菜单项|//+------------------------------------------------------------------+void CScroll::Show(void) {//--- 如果列表项的数量不大于列表可见部分的数量,则退出 if(m_items_total<=m_visible_items_total) return;//--- m_area.Timeframes(OBJ_ALL_PERIODS); m_bg.Timeframes(OBJ_ALL_PERIODS); m_inc.Timeframes(OBJ_ALL_PERIODS); m_dec.Timeframes(OBJ_ALL_PERIODS); m_thumb.Timeframes(OBJ_ALL_PERIODS);//-- 更新对象的位置 Moving(m_wnd.X(),m_wnd.Y(),true);//--- 可见性状态 CElement::IsVisible(true); }//+------------------------------------------------------------------+//| 隐藏菜单项|//+------------------------------------------------------------------+void CScroll::Hide(void) { m_area.Timeframes(OBJ_NO_PERIODS); m_bg.Timeframes(OBJ_NO_PERIODS); m_inc.Timeframes(OBJ_NO_PERIODS); m_dec.Timeframes(OBJ_NO_PERIODS); m_thumb.Timeframes(OBJ_NO_PERIODS);//--- 可见性状态 CElement::IsVisible(false); } //---如果还没用,那就等下次更新吧。谢谢,似乎有帮助。显示()和隐藏()方法中缺少了关于可见性状态的行://--- 可见性状态 CElement::IsVisible(true);和 Hide()://--- 可见性状态 CElement::IsVisible(false); Anatoli Kazharski 2016.10.25 12:47 #18 Artyom Trishkin:谢谢,看来成功了。在 Show()://--- 可见性状态 CElement::IsVisible(true);和 Hide()://--- 可见性状态 CElement::IsVisible(false);还需要更正。应该在更新元素位置之前设置可见性。就像这样...//--- 可见性状态 CElement::IsVisible(true);//-- 更新对象的位置 Moving(m_wnd.X(),m_wnd.Y(),true);... Реter Konow 2016.10.27 09:12 #19 通过计时器实现界面元素的交互性是一种奇怪的解决方案。- 为什么要通过(或使用)计时器来实现呢?- 当然,这会消耗大量资源。控制控件的状态根本不需要计时器。1.记录数组(地图)中所有元素的当前坐标。在移动窗口时调整所有窗体对象的位置坐标。2.2. 制作一个通过坐标查找元素的函数(定位器)。该函数将循环查看记录的当前元素坐标,并找到光标下的元素。3.从 "CHARTEVENT_MOUSE_MOVE "事件(光标移动事件)中调用定位器。4.4. 将从 localiser 返回的对象名称传递给交互函数,在交互函数中,ObjectSetInteger() 函数 将应用于该对象,从而强制其改变颜色。如您所见,该方案中没有计时器,因此不会消耗不必要的资源。 Anatoli Kazharski 2016.10.27 09:30 #20 Реter Konow:通过计时器实现界面元素的交互性是一种奇怪的解决方案。- 为什么要通过(或使用)计时器来实现呢?- 当然,这会消耗大量资源。...正如您所看到的,这个方案中没有定时器,因此不存在不必要的资源消耗。你错了。我已经在上面的评论中详细回答了为什么要这样做。它现在不会消耗大量资源(现在在Windows 10 中也是如此)。你读了这篇文章(以及评论)吗?//---顺便 说一下,在同等条件下,不同终端(MT4/MT5)和不同操作系统版本(Windows)的 CPU 资源消耗是完全不同的。在Windows 7 中,MetaTrader 4 终端的性能明显优于MetaTrader 5。遗憾的是,我现在无法提供相关数据,因为我已经完全切换到Windows 10。至于优化,我还没有用尽所有选项。还有一些需要优化的地方,也需要了解如何优化。 123456 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
阿纳托利,请告诉我错误的原因是什么?
更新前一切正常。现在,在创建 CTable 表时却出现了这个错误。
请告诉我哪里出错了--我已经打印了每一行--界面是建好了,但在某个地方出了问题,....。错误。
档案中的文件包含一个示例。
我忘了更正,因为之前在CCanvasTable 类中已经更正过了。
在CTable 类中,您需要将当前版本的CreateScrollV() 和CreateScrollH() 方法替换为下表所示的方法:
//|| 创建垂直滚动条
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
{
//--- 保存表单指针
m_scrollv.WindowPointer(m_wnd);
//--- 坐标
int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
int y=CElement::Y();
//--- 设置尺寸
m_scrollv.Id(CElement::Id());
m_scrollv.IsDropdown(CElement::IsDropdown());
m_scrollv.XSize(m_scrollv.ScrollWidth());
m_scrollv.YSize((m_columns_total>m_visible_columns_total)? m_y_size-m_scrollv.ScrollWidth()+1 : m_y_size);
m_scrollv.AnchorRightWindowSide(m_anchor_right_window_side);
m_scrollv.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- 创建滚动条
if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
return(false);
//--- 如果现在不需要,请隐藏
if(m_rows_total<=m_visible_rows_total)
m_scrollv.Hide();
//---
return(true);
}
//+------------------------------------------------------------------+
//|| 创建水平滚动条
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
{
//--- 保存表单指针
m_scrollh.WindowPointer(m_wnd);
//--- 坐标
int x=CElement::X();
int y=(m_anchor_bottom_window_side)? m_y-m_area.Y_Size()+m_scrollh.ScrollWidth() : CElement::Y2()-m_scrollh.ScrollWidth();
//--- 设置尺寸
m_scrollh.Id(CElement::Id());
m_scrollh.IsDropdown(CElement::IsDropdown());
m_scrollh.XSize((m_rows_total>m_visible_rows_total)? m_area.XSize()-m_scrollh.ScrollWidth()+1 : m_area.XSize());
m_scrollh.YSize(m_scrollh.ScrollWidth());
m_scrollh.AnchorRightWindowSide(m_anchor_right_window_side);
m_scrollh.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- 创建滚动条
if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
return(false);
//--- 如果现在不需要,请隐藏
if(m_columns_total<=m_visible_columns_total)
m_scrollh.Hide();
//---
return(true);
}
//---
CLabelsTable 类也需要做类似的更改。这些修正将在下一次更新中进行。
之前在CCanvasTable 类中做过更正,我忘了更正。
在CTable 类中,您需要将当前版本的CreateScrollV() 和CreateScrollH() 方法替换为下表所示的方法:
...
//---
CLabelsTable 类也需要进行类似的更改。这些修正将在下一次更新中进行。
之前在CCanvasTable 类中做过更正,我忘了更正。
在CTable 类中,您需要将当前版本的CreateScrollV() 和CreateScrollH() 方法替换为下表所示的方法:
//|| 创建垂直滚动条
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
{
//--- 保存表单指针
m_scrollv.WindowPointer(m_wnd);
//--- 坐标
int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
int y=CElement::Y();
//--- 设置尺寸
m_scrollv.Id(CElement::Id());
m_scrollv.IsDropdown(CElement::IsDropdown());
m_scrollv.XSize(m_scrollv.ScrollWidth());
m_scrollv.YSize((m_columns_total>m_visible_columns_total)? m_y_size-m_scrollv.ScrollWidth()+1 : m_y_size);
m_scrollv.AnchorRightWindowSide(m_anchor_right_window_side);
m_scrollv.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- 创建滚动条
if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
return(false);
//--- 如果现在不需要,请隐藏
if(m_rows_total<=m_visible_rows_total)
m_scrollv.Hide();
//---
return(true);
}
//+------------------------------------------------------------------+
//|| 创建水平滚动条
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
{
//--- 保存表单指针
m_scrollh.WindowPointer(m_wnd);
//--- 坐标
int x=CElement::X();
int y=(m_anchor_bottom_window_side)? m_y-m_area.Y_Size()+m_scrollh.ScrollWidth() : CElement::Y2()-m_scrollh.ScrollWidth();
//--- 设置尺寸
m_scrollh.Id(CElement::Id());
m_scrollh.IsDropdown(CElement::IsDropdown());
m_scrollh.XSize((m_rows_total>m_visible_rows_total)? m_area.XSize()-m_scrollh.ScrollWidth()+1 : m_area.XSize());
m_scrollh.YSize(m_scrollh.ScrollWidth());
m_scrollh.AnchorRightWindowSide(m_anchor_right_window_side);
m_scrollh.AnchorBottomWindowSide(m_anchor_bottom_window_side);
//--- 创建滚动条
if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
return(false);
//--- 如果现在不需要,请隐藏
if(m_columns_total<=m_visible_columns_total)
m_scrollh.Hide();
//---
return(true);
}
//---
CLabelsTable 类也需要做类似的更改。下一次更新中将进行修复。
Anatoly,修改已经完成。以 MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5 中的表格为例,修改 Program.mqh 中的表格,使行数与可见行数一致,或列数与可见列数一致,或两者都一致。例如
//|| 创建表格|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
{
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL (15)
//--- 保存指向表单的指针
m_table.WindowPointer(m_window1);
//--- 坐标
int x=m_window1.X()+TABLE1_GAP_X;
int y=m_window1.Y()+TABLE1_GAP_Y;
//--- 可见列数和行数
int visible_columns_total =6;
int visible_rows_total =15;
//--- 创建前设置属性
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(ALIGN_CENTER);
m_table.HeadersColor(C'255,244,213');
m_table.HeadersTextColor(clrBlack);
m_table.CellColorHover(clrGold);
m_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL);
m_table.VisibleTableSize(visible_columns_total,visible_rows_total);
//--- 创建一个控件
if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
return(false);
//--- 让我们填写表格:
// 第一个单元格为空
m_table.SetValue(0,0,"-");
//--- 栏目标题
for(int c=1; c<COLUMNS1_TOTAL; c++)
{
for(int r=0; r<1; r++)
m_table.SetValue(c,r,"SYMBOL "+string(c));
}
//--- 行标题,文本对齐方式 - 向右
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);
}
}
//--- 数据和表格格式化(背景颜色和单元格颜色)
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);
}
}
//-- 更新表格以显示变化
m_table.UpdateTable();
//--- 将对象添加到对象组的通用数组中
CWndContainer::AddToElementsArray(0,m_table);
return(true);
}
//+------------------------------------------------------------------+
编译并运行示例,点击表格的最低行(一切正常),然后再次点击。第二次点击时,弹出了一个错误:
怎么办?
阿纳托利,修改已经完成。以 MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5 中的示例为例,修改 Program.mqh 中的表格,使行数与可见行数一致,或列数与可见列数一致,或两者都一致。例如,像这样
...
编译并运行示例,点击表格的最低行(一切正常),然后再次点击。第二次点击时出现错误:
怎么办?
在CScrollH 和 CScrollV 类的ScrollBarControl() 方法中,需要对元素的可见性添加额外检查,如下表所示:
//| 滚动控制|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- 如果没有表单指针,则退出
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
//--- 如果表单被其他元素挡住,则退出
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- 如果项目被隐藏,则退出
if(!CElement::IsVisible())
return(false);
//--- 检查滑块上的焦点
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//-- 检查并记住鼠标按钮的状态
CScroll::CheckMouseButtonState(mouse_state);
//--- 更改列表滚动条的颜色
CScroll::ChangeObjectsColor();
//--- 如果控制传递给了滚动条,则定义滑块位置
if(CScroll::ScrollState())
{
//--- 移动滑块
OnDragThumb(x);
//--- 更改滑块位置编号
CalculateThumbPos();
return(true);
}
return(false);
}
//---
该修复将在下一次库更新中提供。
在CScrollH 和CScrollV 类的ScrollBarControl() 方法中,我们需要对元素的可见性添加额外的检查,如下表所示:
...
该修复将在下一次库更新中提供。
谢谢。我做了这些修改:在 Scrolls.mqh 文件的CScrollH 和 CScrollV类中 添加了几行:
//| 滑块控制|
//+------------------------------------------------------------------+
bool CScrollV::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- 如果没有表单指针,则退出
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
//--- 如果表单未锁定且标识符匹配
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- 如果项目被隐藏,则退出
if(!CElement::IsVisible())
return(false);
//--- 检查滑块上的焦点
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//-- 检查并记住鼠标按钮的状态
CScroll::CheckMouseButtonState(mouse_state);
//--- 更改滑块的颜色
CScroll::ChangeObjectsColor();
//--- 如果控制传递给了滚动条,则定义滑块位置
if(CScroll::ScrollState())
{
//--- 移动滑块
OnDragThumb(y);
//--- 更改滑块位置编号
CalculateThumbPos();
return(true);
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| 滚动控制|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- 如果没有表单指针,则退出
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- 如果项目被隐藏,则退出
if(!CElement::IsVisible())
return(false);
//--- 检查滑块上的焦点
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//-- 检查并记住鼠标按钮的状态
CScroll::CheckMouseButtonState(mouse_state);
//--- 更改列表滚动条的颜色
CScroll::ChangeObjectsColor();
//--- 如果控制传递给了滚动条,则定义滑块位置
if(CScroll::ScrollState())
{
//--- 移动滑块
OnDragThumb(x);
//--- 更改滑块位置编号
CalculateThumbPos();
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
我编译并运行了来自 \MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5 的相同测试文件,其中我更改了 Program.mqh 中的建表函数,使所有列和行的数量与可见列和行的数量一致:
//|| 创建表格|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
{
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL (15)
//--- 保存指向表单的指针
m_table.WindowPointer(m_window1);
//--- 坐标
int x=m_window1.X()+TABLE1_GAP_X;
int y=m_window1.Y()+TABLE1_GAP_Y;
//--- 可见列数和行数
int visible_columns_total =6;
int visible_rows_total =15;
//--- 创建前设置属性
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(ALIGN_CENTER);
m_table.HeadersColor(C'255,244,213');
m_table.HeadersTextColor(clrBlack);
m_table.CellColorHover(clrGold);
m_table.TableSize(COLUMNS1_TOTAL,ROWS1_TOTAL);
m_table.VisibleTableSize(visible_columns_total,visible_rows_total);
//--- 创建一个控件
if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
return(false);
//--- 让我们填写表格:
// 第一个单元格为空
m_table.SetValue(0,0,"-");
//--- 栏目标题
for(int c=1; c<COLUMNS1_TOTAL; c++)
{
for(int r=0; r<1; r++)
m_table.SetValue(c,r,"SYMBOL "+string(c));
}
//--- 行标题,文本对齐方式 - 向右
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);
}
}
//--- 数据和表格格式化(背景颜色和单元格颜色)
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);
}
}
//-- 更新表格以显示变化
m_table.UpdateTable();
//--- 将对象添加到对象组的通用数组中
CWndContainer::AddToElementsArray(0,m_table);
return(true);
}
//+------------------------------------------------------------------+
编译并运行 ChartWindow02.ex5
我们点击了几次表格的最低行,得到的结果是在数组外飞行:
...
所以什么都没变?在我做了更改之后,它就不再播放了。我可能还做了其他改动,但我不记得了。我没有小修改的历史记录。
为了以防万一,如果CScroll::Show() 和CScroll::Hide() 方法不同,请尝试用这些版本替换它们:
//| 显示菜单项|
//+------------------------------------------------------------------+
void CScroll::Show(void)
{
//--- 如果列表项的数量不大于列表可见部分的数量,则退出
if(m_items_total<=m_visible_items_total)
return;
//---
m_area.Timeframes(OBJ_ALL_PERIODS);
m_bg.Timeframes(OBJ_ALL_PERIODS);
m_inc.Timeframes(OBJ_ALL_PERIODS);
m_dec.Timeframes(OBJ_ALL_PERIODS);
m_thumb.Timeframes(OBJ_ALL_PERIODS);
//-- 更新对象的位置
Moving(m_wnd.X(),m_wnd.Y(),true);
//--- 可见性状态
CElement::IsVisible(true);
}
//+------------------------------------------------------------------+
//| 隐藏菜单项|
//+------------------------------------------------------------------+
void CScroll::Hide(void)
{
m_area.Timeframes(OBJ_NO_PERIODS);
m_bg.Timeframes(OBJ_NO_PERIODS);
m_inc.Timeframes(OBJ_NO_PERIODS);
m_dec.Timeframes(OBJ_NO_PERIODS);
m_thumb.Timeframes(OBJ_NO_PERIODS);
//--- 可见性状态
CElement::IsVisible(false);
}
//---
如果没有帮助,你只能等待下一次更新了。
但在我做了更改之后,它就不再播放了。我可能还做了其他改动,但我不记得了。我没有标记小修改的历史记录。
为了以防万一,如果CScroll::Show() 和CScroll::Hide() 方法不同,请尝试用这些版本替换它们:
//| 显示菜单项|
//+------------------------------------------------------------------+
void CScroll::Show(void)
{
//--- 如果列表项的数量不大于列表可见部分的数量,则退出
if(m_items_total<=m_visible_items_total)
return;
//---
m_area.Timeframes(OBJ_ALL_PERIODS);
m_bg.Timeframes(OBJ_ALL_PERIODS);
m_inc.Timeframes(OBJ_ALL_PERIODS);
m_dec.Timeframes(OBJ_ALL_PERIODS);
m_thumb.Timeframes(OBJ_ALL_PERIODS);
//-- 更新对象的位置
Moving(m_wnd.X(),m_wnd.Y(),true);
//--- 可见性状态
CElement::IsVisible(true);
}
//+------------------------------------------------------------------+
//| 隐藏菜单项|
//+------------------------------------------------------------------+
void CScroll::Hide(void)
{
m_area.Timeframes(OBJ_NO_PERIODS);
m_bg.Timeframes(OBJ_NO_PERIODS);
m_inc.Timeframes(OBJ_NO_PERIODS);
m_dec.Timeframes(OBJ_NO_PERIODS);
m_thumb.Timeframes(OBJ_NO_PERIODS);
//--- 可见性状态
CElement::IsVisible(false);
}
//---
如果还没用,那就等下次更新吧。
谢谢,似乎有帮助。显示()和隐藏()方法中缺少了关于可见性状态的行:
CElement::IsVisible(true);
和 Hide():
CElement::IsVisible(false);
谢谢,看来成功了。在 Show():
CElement::IsVisible(true);
和 Hide():
CElement::IsVisible(false);
还需要更正。应该在更新元素位置之前设置可见性。就像这样
//--- 可见性状态
CElement::IsVisible(true);
//-- 更新对象的位置
Moving(m_wnd.X(),m_wnd.Y(),true);
...
通过计时器实现界面元素的交互性是一种奇怪的解决方案。- 为什么要通过(或使用)计时器来实现呢?- 当然,这会消耗大量资源。
控制控件的状态根本不需要计时器。
1.记录数组(地图)中所有元素的当前坐标。在移动窗口时调整所有窗体对象的位置坐标。
2.2. 制作一个通过坐标查找元素的函数(定位器)。该函数将循环查看记录的当前元素坐标,并找到光标下的元素。
3.从 "CHARTEVENT_MOUSE_MOVE "事件(光标移动事件)中调用定位器。
4.4. 将从 localiser 返回的对象名称传递给交互函数,在交互函数中,ObjectSetInteger() 函数 将应用于该对象,从而强制其改变颜色。
如您所见,该方案中没有计时器,因此不会消耗不必要的资源。
通过计时器实现界面元素的交互性是一种奇怪的解决方案。- 为什么要通过(或使用)计时器来实现呢?- 当然,这会消耗大量资源。
...
正如您所看到的,这个方案中没有定时器,因此不存在不必要的资源消耗。
你错了。我已经在上面的评论中详细回答了为什么要这样做。
它现在不会消耗大量资源(现在在Windows 10 中也是如此)。你读了这篇文章(以及评论)吗?
//---
顺便 说一下,在同等条件下,不同终端(MT4/MT5)和不同操作系统版本(Windows)的 CPU 资源消耗是完全不同的。在Windows 7 中,MetaTrader 4 终端的性能明显优于MetaTrader 5。遗憾的是,我现在无法提供相关数据,因为我已经完全切换到Windows 10。
至于优化,我还没有用尽所有选项。还有一些需要优化的地方,也需要了解如何优化。