程序库: 用于创建图形界面的 EasyAndFastGUI 开发库 - 页 11

 
Anatoli Kazharski:

最初根本没有这样的任务,即在创建图形用户界面后有必要移动元素。一切都基于这样一个想法,即每个元素都已经具备了所有必要的功能。

反问为什么需要移动元素?您想做什么?在与图形用户界面交互时,您希望得到什么行为?

要了解是否会出现故障,您需要在每次更改基类后测试所有元素。这已经很难说了。我已经有一段时间没有深入研究了。

创建一个包含库中所有元素的测试图形用户界面,并在更改后对其进行测试。

例如,可扩展列表。当你点击时,一些元素会被隐藏,而下面的所有元素都会被拉上来。反之亦然。

测试图形用户界面是个好主意,我得试着做做:)

顺便说一下,在相同的 CElement::Moving.

//--- 如果绑定在右侧
   if(m_anchor_right_window_side)
     {
      //-- 在元素字段中保存坐标
      CElementBase::X(m_main.X2()-XGap());
      //-- 在对象字段中保存坐标
      m_canvas.X(m_main.X2()-m_canvas.XGap());
     }
   else
     {
      CElementBase::X(m_main.X()+XGap());
      m_canvas.X(m_main.X()+m_canvas.XGap());
     }
//--- 如果绑定来自下面
   if(m_anchor_bottom_window_side)
     {
      CElementBase::Y(m_main.Y2()-YGap());
      m_canvas.Y(m_main.Y2()-m_canvas.YGap());
     }
   else
     {
      CElementBase::Y(m_main.Y()+YGap());
      m_canvas.Y(m_main.Y()+m_canvas.YGap());
     }

如果存在绑定,元素会与画布一起移动。所以理论上应该不会出错:)

 

是否有人尝试过使用该库创建组合框 - 更改其中的元素 ?????共享 您是如何做到的?

我创建了一个组合框,一切正常。然后,我使用以下函数在其中填充元素:

void CPresenter::setCombobox(CComboBox *cb_ptr,CArrayString &arr)
  {
   CListView *lv_ptr=cb_ptr.GetListViewPointer();
   lv_ptr.Clear(true);
   
   cb_ptr.ItemsTotal(arr.Total());
   for(int i=0;i<arr.Total();i++)
      cb_ptr.SetValue(i,arr[i]);
   lv_ptr.SelectItem(0,true);
   cb_ptr.SelectItem(0);
   cb_ptr.Update(true);
   cb_ptr.GetButtonPointer().Update(true);
  }

一切正常。我在填满的组合框中进行选择,例如选择第三个值,然后点击按钮,结果是一系列操作导致组合框溢出。然后我重新填充一个值(例如,最初有 20 个项目,点击按钮后只剩下一个项目!)。

这里出现了一个有趣的错误--在所有内容都被覆盖之后(使用上述函数)--我试图打开组合框,但无法打开,因为错误数组超出了范围!
错误发生在以下方法中:
void CListView::RedrawItemsByMode(const bool is_selected_item=false).

第 1364 行。我四处查找后发现,出现这种情况的原因是:
1) 当选择列表中的第三个项目时(在按下按钮之前)--变量
m_prev_item_index_focus 被填入一个等于 3 的索引。

然后,在第 1357 行将该索引通过 prev_item_index 变量传递给
索引

数组。其结果是,在第 1364 行,从数组
m_items 中选择了一个值

的一个值,而数组 (m_items) 在索引 #0 处只有一个值。




从逻辑上讲,它应该在CListView 类 的 Clear 方法中被清除,我用它清除了所有项目,但不幸的是,我在那里找不到这样的方法....。


关于上述所有问题:
1)这是库中的一个错误,还是我更新值的方法不正确?
2)解决这个问题的最佳方法是什么?

 
为我的问题提供最基本的可重现代码:

//+------------------------------------------------------------------+
//|TestCombobox.mq5
//| Copyright 2018, MetaQuotes Software Corp.
//|https://www.mql5.com ||
//+------------------------------------------------------------------+

#include <EasyAndFastGUI\WndEvents.mqh>
#include <Arrays/ArrayString.mqh>
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
class CWindowManager : public CWndEvents
  {
public:
   void              OnDeinitEvent(const int reason){CWndEvents::Destroy();};
   //--- 图形事件处理程序
   virtual void      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);//

   //--- 创建程序的图形界面
   bool              CreateGUI(void);

private:
   CComboBox         m_cb;
   CButton           m_btn;

   void              Btn_Click(int id,long lparam);

   bool              CreateComboBox(const string comboBox_name,
                                    const string &items_text[],
                                    const int x_gap,
                                    const int y_gap,
                                    const int x_size,
                                    const int y_size,
                                    CComboBox &comboBox_link,
                                    int x_ButtonSize=0);
   bool              CreateButton(const string text,
                                  const int x_gap,
                                  const int y_gap,
                                  const int x_size,
                                  const int y_size,
                                  CButton &btn_link);
   bool              CreateWindow(const string text);

   void              setCombobox(CComboBox *cb_ptr,CArrayString &arr);
   //--- 主窗口
   CWindow           m_window;
   //-- 图表窗口 ID 和编号
   long              m_chart_id;
   int               m_subwin;
  };

CWindowManager _window;
//+------------------------------------------------------------------+
//| 专家初始化函数|
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   if(!_window.CreateGUI())
     {
      Print(__FUNCTION__," > 创建图形用户界面失败!");
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 专家去初始化函数|
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   _window.OnDeinitEvent(reason);
  }
//+------------------------------------------------------------------+
//| 专家勾选功能|
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void OnChartEvent(const int    id,
                  const long   &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   _window.ChartEvent(id,lparam,dparam,sparam);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void CWindowManager::setCombobox(CComboBox *cb_ptr,CArrayString &arr)
  {
   CListView *lv_ptr=cb_ptr.GetListViewPointer();

   lv_ptr.Clear(true);
   cb_ptr.ItemsTotal(arr.Total());
   for(int i=0;i<arr.Total();i++)
      cb_ptr.SetValue(i,arr[i]);
   lv_ptr.SelectItem(0,true);
   cb_ptr.SelectItem(0);
   cb_ptr.Update(true);
   cb_ptr.GetButtonPointer().Update(true);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool CWindowManager::CreateWindow(const string text)
  {
//--- 将窗口指针添加到窗口数组中
   CWndContainer::AddWindow(m_window);
//--- 坐标
   int x=(m_window.X()>0) ? m_window.X() : 1;
   int y=(m_window.Y()>0) ? m_window.Y() : 1;
//--- 属性
   m_window.XSize(300);
   m_window.YSize(300);
   m_window.Alpha(200);
   m_window.IconXGap(3);
   m_window.IconYGap(2);
   m_window.IsMovable(true);
   m_window.ResizeMode(false);
   m_window.CloseButtonIsUsed(true);
   m_window.FullscreenButtonIsUsed(false);
   m_window.CollapseButtonIsUsed(true);
   m_window.TooltipsButtonIsUsed(false);
   m_window.RollUpSubwindowMode(true,true);
   m_window.TransparentOnlyCaption(true);

//--- 设置工具提示
   m_window.GetCloseButtonPointer().Tooltip("Close");
   m_window.GetCollapseButtonPointer().Tooltip("Collapse/Expand");
//--- 创建表格
   if(!m_window.CreateWindow(m_chart_id,m_subwin,text,x,y))
      return(false);
//---
   return(true);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool CWindowManager::CreateButton(const string text,
                                  const int x_gap,
                                  const int y_gap,
                                  const int x_size,
                                  const int y_size,
                                  CButton &btn_link)
  {
//--- 保存指向主元素的指针
   btn_link.MainPointer(m_window);
//--- 属性
   btn_link.XSize(x_size);
   btn_link.YSize(y_size);
   btn_link.IconXGap(3);
   btn_link.IconYGap(3);
   btn_link.IsCenterText(true);
//--- 创建一个控件
   if(!btn_link.CreateButton(text,x_gap,y_gap))
      return(false);
//--- 添加指向基本元素的指针
   CWndContainer::AddToElementsArray(0,btn_link);
   return(true);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool CWindowManager::CreateComboBox(const string comboBox_name,
                                    const string &items_text[],
                                    const int x_gap,
                                    const int y_gap,
                                    const int x_size,
                                    const int y_size,
                                    CComboBox &comboBox_link,
                                    int x_lableXSize)
  {
//--- 保存指向主元素的指针
   comboBox_link.MainPointer(m_window);

   if(x_lableXSize==0)
      x_lableXSize=x_size;

   int items_total=ArraySize(items_text);

//--- 创建前设置属性
   comboBox_link.XSize(x_size);
   comboBox_link.YSize(y_size);
   comboBox_link.ItemsTotal(items_total);
   comboBox_link.AnchorRightWindowSide(false);
   comboBox_link.GetButtonPointer().YSize(y_size);

   if(StringCompare(comboBox_name,"")==0)
     {
      comboBox_link.GetButtonPointer().XSize(x_size);
      comboBox_link.GetButtonPointer().AnchorRightWindowSide(true);
     }
   else
     {
      comboBox_link.GetButtonPointer().XSize(x_lableXSize);
      comboBox_link.GetButtonPointer().AnchorRightWindowSide(false);
     }

//--- 将项目值保存到组合框列表中
   for(int i=0;i<items_total;i++)
      comboBox_link.SetValue(i,items_text[i]);

//--- 获取列表指针
   CListView *lv=comboBox_link.GetListViewPointer();

//--- 设置列表属性
   lv.YSize((int)MathMin(items_total*y_size,150));
   lv.LightsHover(true);
   lv.SelectItem(lv.SelectedItemIndex()==WRONG_VALUE ? 0 : lv.SelectedItemIndex());

//--- 创建一个控件
   if(!comboBox_link.CreateComboBox(comboBox_name,x_gap,y_gap))
      return false;

   CWndContainer::AddToElementsArray(0,comboBox_link);
   return true;
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool CWindowManager::CreateGUI(void)
  {
   if(!CreateWindow("Combobox Bug ???? "))
      return(false);
   string cb_arr[20];
   for(int i=0;i<20;i++)
      cb_arr[i]=IntegerToString(i+1);
   if(!CreateComboBox("",cb_arr,100,100,100,20,m_cb))
      return false;
   if(!CreateButton("Action",100,130,50,20,m_btn))
      return false;

// 显示窗口
   CWndEvents::CompletedGUI();
   return true;
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void CWindowManager::Btn_Click(int id,long lparam)
  {
   if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON && lparam==m_btn.Id())
     {
      CArrayString s;
      s.Add("new value");
      setCombobox(&m_cb,s);
     }
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void CWindowManager::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   Btn_Click(id,lparam);
  }
//+------------------------------------------------------------------+



到目前为止,我找到的所有解决方案都是编辑库代码(添加新的 3 行代码),但我不喜欢修改别人的代码...

 
Andrey Azatskiy:
为我的问题提供最少的可重现代码:

...

到目前为止,我找到的所有解决方案都是编辑库代码(添加新的 3 行代码),但我不喜欢修改别人的代码...

感谢您的留言。

请尝试在CListView 类方法 中添加一小部分内容。如下所示,您需要将辅助字段清零:

//+------------------------------------------------------------------+
//| 清除列表(删除所有项目) | //| 删除所有项目
//+------------------------------------------------------------------+
void CListView::Clear(const bool redraw=false)
  {
//-- 将辅助字段重置为零
   m_item_index_focus      =WRONG_VALUE;
   m_prev_selected_item    =WRONG_VALUE;
   m_prev_item_index_focus =WRONG_VALUE;
//--- 将大小设置为零
   ListSize(0);
//-- 计算并设置新的列表大小
   RecalculateAndResizeList(redraw);
  }
 
Anatoli Kazharski:

感谢您的留言。

请尝试对CListView 类方法 做一个小的补充。如下所示,您需要将辅助字段清零:

感谢您的回复。

 
Anatoli Kazharski:

在 bitbucket 上建立一个版本库,接受图书馆活跃用户的提交如何?

我们会一起更快地完成它;)

 

您能告诉我如何正确处理窗口关闭按钮吗?

问题如下:我将智能交易系统(例如 ExampleEAF.ex5)和我的指标放在图表下的一个单独窗口中(最小代码只显示一个空窗口)。然后,我点击其中任何一个应用程序上的关闭窗口按钮,两个窗口都会关闭(从图表中移除)。

这种行为不太正确。有没有办法区分在同一图表上同时运行的不同应用程序的事件?我怀疑其他事件也可能重叠。

 
Andrey Khatimlianskii:

在 bitbucket 上建立一个版本库,接受图书馆活跃用户的提交如何?

我们会一起更快地完成它;)

我已经获得了访问权限。我对其中的许多编辑内容表示怀疑。

这些或那些改动没有任何正当理由。在这里的论坛上讨论会更容易些。

如果要做任何改动,有必要举例说明和测试结果,并解释为什么这样做会更好。

 
dmyger:

您能告诉我如何正确处理窗口关闭按钮吗?

问题如下:我将智能交易系统(例如 ExampleEAF.ex5)和我的指标放在图表下的一个单独窗口中(最小代码只显示一个空窗口)。然后,我单击其中任何一个应用程序上的关闭窗口按钮,两个窗口都会关闭(从图表中移除)。

这种行为不太正确。有没有办法区分在同一图表上同时运行的不同应用程序的事件?我怀疑其他事件也可能重叠。

我将在有时间时进行测试,并在此报告结果。

 

Andrey Khatimlianskii:

Как на счет репозитория на битбакете и принятия коммитов от активных пользователей библиотеки?

Вместе быстрее допилим ;)

阿纳托利-卡扎尔斯基

...

如果要做任何改动,有必要给出示例和测试结果,并解释为什么这样做会更好。

至少要简明扼要。例如

CListView 类中的更正。在Clear() 方法中,我们需要将一些辅助字段清零,以防止该类的其他方法超出数组 范围。