Inicialmente, simplesmente não havia essa tarefa de que, após a criação da GUI, era necessário mover os elementos. Tudo foi baseado na ideia de que cada elemento já tinha todo o comportamento necessário implementado.
Perguntas contrárias: Por que você precisa mover elementos? O que você quer fazer? Que comportamento você deseja obter ao interagir com a GUI?
Para saber se algo vai quebrar, você precisa testar todos os elementos após cada alteração nas classes de base. Já é difícil dizer isso imediatamente. Já faz algum tempo que não estou pesquisando a fundo.
Crie uma GUI de teste com todos os elementos da biblioteca e teste-os após as alterações.
Por exemplo, listas expansíveis. Quando você clica, alguns dos elementos ficam ocultos, e tudo o que está abaixo é puxado para cima. E vice-versa.
Testar a GUI é uma boa ideia, vou ter que tentar criá-la :)
//--- Se o vínculo estiver à direitaif(m_anchor_right_window_side)
{
//--- Salvando coordenadas em campos de elementos
CElementBase::X(m_main.X2()-XGap());
//--- Salvando coordenadas em campos de objetos
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());
}
//--- Se o vínculo for de baixo para cimaif(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());
}
Se houver um vínculo, o elemento se moverá junto com a tela. Portanto, teoricamente, nada deve quebrar :)
Tudo funciona. Depois que seleciono na combobox preenchida - por exemplo, o terceiro valor - e clico no botão, o resultado é uma série de ações que resultam no transbordamento da combobox. E eu a preencho novamente com um valor (por exemplo, inicialmente havia 20 itens nela, mas depois de clicar no botão, resta apenas um item!)
E aqui vem um erro interessante - depois que tudo é sobrescrito (usando a função acima) - tento abrir a caixa de combinação, mas não consigo, porque o erro Array out of range! O erro ocorre no método: void CListView::RedrawItemsByMode(const bool is_selected_item=false).
Na linha 1364. Como descobri pesquisando, isso ocorre porque: 1) ao selecionar o terceiro item da lista (antes de pressionar o botão) - a variável m_prev_item_index_focus é preenchida com um índice igual a 3.
Em seguida, esse índice é passado por meio da variável prev_item_index para a matriz indexes
na linha 1357. O resultado disso - na linha 1364 - é a seleção de um valor da matriz m_items
no índice #2 (índice correspondente ao último elemento selecionado), enquanto a matriz (m_items) tem apenas um valor no índice #0.
Estou pesquisando pelo segundo dia e ainda não consegui encontrar o local onde o valor da variável m_prev_item_index_focus seria redefinido para zero.
Logicamente, ele deveria ser limpo no método Clear da classe CListView, que usei para limpar todos os itens, mas infelizmente não consegui encontrar esse método....
Em relação a todas as perguntas acima: 1) É um bug na biblioteca ou estou atualizando os valores incorretamente? 2) Qual é a melhor maneira de contornar esse problema?
//+------------------------------------------------------------------+//|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(constint reason){CWndEvents::Destroy();};
//--- Manipulador de eventos do Graphvirtualvoid OnEvent(constint id,constlong &lparam,constdouble &dparam,conststring &sparam);////--- Cria a GUI do programabool CreateGUI(void);
private:
CComboBox m_cb;
CButton m_btn;
void Btn_Click(int id,long lparam);
bool CreateComboBox(conststring comboBox_name,
conststring &items_text[],
constint x_gap,
constint y_gap,
constint x_size,
constint y_size,
CComboBox &comboBox_link,
int x_ButtonSize=0);
bool CreateButton(conststring text,
constint x_gap,
constint y_gap,
constint x_size,
constint y_size,
CButton &btn_link);
bool CreateWindow(conststring text);
void setCombobox(CComboBox *cb_ptr,CArrayString &arr);
//--- Janela principal
CWindow m_window;
//--- ID e número da janela do gráficolong m_chart_id;
int m_subwin;
};
CWindowManager _window;
//+------------------------------------------------------------------+//| Função de inicialização de especialista|//+------------------------------------------------------------------+intOnInit()
{
//---if(!_window.CreateGUI())
{
Print(__FUNCTION__," > Falha ao criar uma GUI!");
return(INIT_FAILED);
}
//---return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+//| Função de desinicialização de especialista|//+------------------------------------------------------------------+voidOnDeinit(constint reason)
{
//---
_window.OnDeinitEvent(reason);
}
//+------------------------------------------------------------------+//| Função de tique de especialista|//+------------------------------------------------------------------+voidOnTick()
{
//---
}
//+------------------------------------------------------------------+//||//+------------------------------------------------------------------+voidOnChartEvent(constint id,
constlong &lparam,
constdouble &dparam,
conststring &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(conststring text)
{
//--- Adicione o ponteiro da janela à matriz de janelas
CWndContainer::AddWindow(m_window);
//--- Coordenadasint x=(m_window.X()>0) ? m_window.X() : 1;
int y=(m_window.Y()>0) ? m_window.Y() : 1;
//--- Propriedades
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);
//--- Definir dicas de ferramentas
m_window.GetCloseButtonPointer().Tooltip("Close");
m_window.GetCollapseButtonPointer().Tooltip("Collapse/Expand");
//--- Criação de formulárioif(!m_window.CreateWindow(m_chart_id,m_subwin,text,x,y))
return(false);
//---return(true);
}
//+------------------------------------------------------------------+//||//+------------------------------------------------------------------+bool CWindowManager::CreateButton(conststring text,
constint x_gap,
constint y_gap,
constint x_size,
constint y_size,
CButton &btn_link)
{
//--- Salvar o ponteiro para o elemento principal
btn_link.MainPointer(m_window);
//--- Propriedades
btn_link.XSize(x_size);
btn_link.YSize(y_size);
btn_link.IconXGap(3);
btn_link.IconYGap(3);
btn_link.IsCenterText(true);
//--- Criar um controleif(!btn_link.CreateButton(text,x_gap,y_gap))
return(false);
//--- Adicione um ponteiro ao elemento na base
CWndContainer::AddToElementsArray(0,btn_link);
return(true);
}
//+------------------------------------------------------------------+//||//+------------------------------------------------------------------+bool CWindowManager::CreateComboBox(conststring comboBox_name,
conststring &items_text[],
constint x_gap,
constint y_gap,
constint x_size,
constint y_size,
CComboBox &comboBox_link,
int x_lableXSize)
{
//--- Salvar o ponteiro para o elemento principal
comboBox_link.MainPointer(m_window);
if(x_lableXSize==0)
x_lableXSize=x_size;
int items_total=ArraySize(items_text);
//--- Definir propriedades antes da criação
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);
}
//--- Salvar os valores dos itens na lista da caixa de combinaçãofor(int i=0;i<items_total;i++)
comboBox_link.SetValue(i,items_text[i]);
//--- Obter o ponteiro da lista
CListView *lv=comboBox_link.GetListViewPointer();
//--- Definir propriedades da lista
lv.YSize((int)MathMin(items_total*y_size,150));
lv.LightsHover(true);
lv.SelectItem(lv.SelectedItemIndex()==WRONG_VALUE ? 0 : lv.SelectedItemIndex());
//--- Criar um controleif(!comboBox_link.CreateComboBox(comboBox_name,x_gap,y_gap))
returnfalse;
CWndContainer::AddToElementsArray(0,comboBox_link);
returntrue;
}
//+------------------------------------------------------------------+//||//+------------------------------------------------------------------+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))
returnfalse;
if(!CreateButton("Action",100,130,50,20,m_btn))
returnfalse;
// Mostrar janela
CWndEvents::CompletedGUI();
returntrue;
}
//+------------------------------------------------------------------+//||//+------------------------------------------------------------------+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(constint id,constlong &lparam,constdouble &dparam,conststring &sparam)
{
Btn_Click(id,lparam);
}
//+------------------------------------------------------------------+
Até agora, todas as soluções que encontrei se resumem a editar o código da biblioteca (adicionando novas 3 linhas de código) - mas não gosto da ideia de ajustar o código de outra pessoa...
Andrey Azatskiy: Código mínimo reproduzível para minha pergunta:
...
Até agora, todas as soluções que encontrei se resumem à edição do código da biblioteca (adição de novas 3 linhas de código), mas não gosto da ideia de ajustar o código de outra pessoa...
Obrigado pela mensagem.
Tente fazer uma pequena adição ao método da classeCListView. Você precisa zerar os campos auxiliares, conforme indicado abaixo:
//+------------------------------------------------------------------+//| Limpa a lista (exclui todos os itens)//+------------------------------------------------------------------+void CListView::Clear(constbool redraw=false)
{
//--- Redefinir os campos auxiliares para zero m_item_index_focus =WRONG_VALUE;
m_prev_selected_item =WRONG_VALUE;
m_prev_item_index_focus =WRONG_VALUE;//--- Definir o tamanho como zero
ListSize(0);
//--- Calcular e definir novos tamanhos de lista
RecalculateAndResizeList(redraw);
}
Você pode me dizer como lidar corretamente com o botão de fechar a janela?
O problema é o seguinte: coloco um Expert Advisor (por exemplo, ExampleEAF.ex5) e meu indicador em uma janela separada sob o gráfico (o código mínimo exibe apenas uma janela vazia). Em seguida, clico no botão fechar janela em qualquer um desses aplicativos e ambos são fechados (removidos do gráfico).
Esse comportamento não é totalmente correto. Existe alguma maneira de distinguir eventos para diferentes aplicativos que trabalham simultaneamente no mesmo gráfico? Há uma suspeita de que outros eventos também possam se sobrepor.
Você pode me dizer como lidar corretamente com o botão de fechar a janela?
O problema é o seguinte: coloco um Expert Advisor (por exemplo, ExampleEAF.ex5) e meu indicador em uma janela separada sob o gráfico (o código mínimo exibe apenas uma janela vazia). Em seguida, clico no botão fechar janela em qualquer um desses aplicativos e ambos são fechados (removidos do gráfico).
Esse não é o comportamento correto. Existe alguma maneira de distinguir eventos para diferentes aplicativos que trabalham simultaneamente no mesmo gráfico? Suspeito que outros eventos também possam se sobrepor.
Vou testá-lo quando tiver tempo e relatarei o resultado aqui.
Para login e uso do site MQL5.com, você deve ativar o uso de cookies.
Ative esta opção no seu navegador, caso contrário você não poderá fazer login.
Você entrou na conta. A autenticação de dois fatores foi desativada. Configure-a novamente e escaneie um novo código QR ou continue com a autenticação de dois fatores desativada.
Inicialmente, simplesmente não havia essa tarefa de que, após a criação da GUI, era necessário mover os elementos. Tudo foi baseado na ideia de que cada elemento já tinha todo o comportamento necessário implementado.
Perguntas contrárias: Por que você precisa mover elementos? O que você quer fazer? Que comportamento você deseja obter ao interagir com a GUI?
Para saber se algo vai quebrar, você precisa testar todos os elementos após cada alteração nas classes de base. Já é difícil dizer isso imediatamente. Já faz algum tempo que não estou pesquisando a fundo.
Crie uma GUI de teste com todos os elementos da biblioteca e teste-os após as alterações.
Por exemplo, listas expansíveis. Quando você clica, alguns dos elementos ficam ocultos, e tudo o que está abaixo é puxado para cima. E vice-versa.
Testar a GUI é uma boa ideia, vou ter que tentar criá-la :)
A propósito, no mesmo CElement::Moving.
Se houver um vínculo, o elemento se moverá junto com a tela. Portanto, teoricamente, nada deve quebrar :)
Alguém já tentou criar uma caixa de combinação usando essa biblioteca para alterar os elementos nela? ????? Share Como você faz isso?
Eu crio uma caixa de combinação e tudo funciona. Em seguida, eu a preencho com elementos usando a seguinte função:
Tudo funciona. Depois que seleciono na combobox preenchida - por exemplo, o terceiro valor - e clico no botão, o resultado é uma série de ações que resultam no transbordamento da combobox. E eu a preencho novamente com um valor (por exemplo, inicialmente havia 20 itens nela, mas depois de clicar no botão, resta apenas um item!)
E aqui vem um erro interessante - depois que tudo é sobrescrito (usando a função acima) - tento abrir a caixa de combinação, mas não consigo, porque o erro Array out of range!
O erro ocorre no método:
void CListView::RedrawItemsByMode(const bool is_selected_item=false).
Na linha 1364. Como descobri pesquisando, isso ocorre porque:
1) ao selecionar o terceiro item da lista (antes de pressionar o botão) - a variável
m_prev_item_index_focus é preenchida com um índice igual a 3.
Em seguida, esse índice é passado por meio da variável prev_item_index para a matriz
indexes
na linha 1357. O resultado disso - na linha 1364 - é a seleção de um valor da matriz
m_items
no índice #2 (índice correspondente ao último elemento selecionado), enquanto a matriz (m_items) tem apenas um valor no índice #0.
Estou pesquisando pelo segundo dia e ainda não consegui encontrar o local onde o valor da variável
m_prev_item_index_focus seria redefinido para zero.
Logicamente, ele deveria ser limpo no método Clear da classe CListView, que usei para limpar todos os itens, mas infelizmente não consegui encontrar esse método....
Em relação a todas as perguntas acima:
1) É um bug na biblioteca ou estou atualizando os valores incorretamente?
2) Qual é a melhor maneira de contornar esse problema?
Até agora, todas as soluções que encontrei se resumem a editar o código da biblioteca (adicionando novas 3 linhas de código) - mas não gosto da ideia de ajustar o código de outra pessoa...
Código mínimo reproduzível para minha pergunta:
...
Até agora, todas as soluções que encontrei se resumem à edição do código da biblioteca (adição de novas 3 linhas de código), mas não gosto da ideia de ajustar o código de outra pessoa...
Obrigado pela mensagem.
Tente fazer uma pequena adição ao método da classe CListView. Você precisa zerar os campos auxiliares, conforme indicado abaixo:
Obrigado pela mensagem.
Tente fazer uma pequena adição ao método da classe CListView. Você precisa zerar os campos auxiliares, conforme indicado abaixo:
Obrigado por sua resposta.
Que tal um repositório no bitbucket e aceitar commits de usuários ativos da biblioteca?
Juntos, terminaremos o projeto mais rápido ;)
Você pode me dizer como lidar corretamente com o botão de fechar a janela?
O problema é o seguinte: coloco um Expert Advisor (por exemplo, ExampleEAF.ex5) e meu indicador em uma janela separada sob o gráfico (o código mínimo exibe apenas uma janela vazia). Em seguida, clico no botão fechar janela em qualquer um desses aplicativos e ambos são fechados (removidos do gráfico).
Esse comportamento não é totalmente correto. Existe alguma maneira de distinguir eventos para diferentes aplicativos que trabalham simultaneamente no mesmo gráfico? Há uma suspeita de que outros eventos também possam se sobrepor.
Que tal um repositório no bitbucket e aceitar commits de usuários ativos da biblioteca?
Juntos, terminaremos o projeto mais rápido ;)
Já me deram acesso. Tenho dúvidas sobre muitas das edições.
Não há justificativa para essas ou aquelas alterações. É mais fácil discutir isso aqui no fórum.
Se alguma alteração for feita, é necessário dar exemplos e resultados de testes com a explicação de por que ela será melhor.
Você pode me dizer como lidar corretamente com o botão de fechar a janela?
O problema é o seguinte: coloco um Expert Advisor (por exemplo, ExampleEAF.ex5) e meu indicador em uma janela separada sob o gráfico (o código mínimo exibe apenas uma janela vazia). Em seguida, clico no botão fechar janela em qualquer um desses aplicativos e ambos são fechados (removidos do gráfico).
Esse não é o comportamento correto. Existe alguma maneira de distinguir eventos para diferentes aplicativos que trabalham simultaneamente no mesmo gráfico? Suspeito que outros eventos também possam se sobrepor.
Vou testá-lo quando tiver tempo e relatarei o resultado aqui.
Andrey Khatimlianskii:
Как на счет репозитория на битбакете и принятия коммитов от активных пользователей библиотеки?
Вместе быстрее допилим ;)
Anatoli Kazharski:
...
Se alguma alteração for feita, é necessário dar exemplos e resultados de testes com uma explicação de por que seria melhor.
Pelo menos de forma breve. Por exemplo:
Correções na classe CListView. No método Clear(), precisamos zerar alguns campos auxiliares para evitar que outros métodos da classe saiam da matriz.