2016.10.19 03:09:04.993 TestTable (EURUSD,H1) invalid pointer access in 'Scrolls.mqh' (698,10)
Tudo funcionava bem antes dessa atualização. Agora, ao criar a tabela CTable, esse erro aparece.
Por favor, diga-me onde está o erro - já imprimi todas as linhas - a interface é criada, mas depois de algum tempo ela tropeça e .... erro.
Arquivo com um exemplo no arquivo.
Esqueci de fazer uma correção, pois ela foi feita anteriormente na classe CCanvasTable.
Na classe CTable, você precisa substituir as versões atuais dos métodos CreateScrollV() e CreateScrollH() pelos métodos mostrados na listagem abaixo:
//+------------------------------------------------------------------+ //|| Cria uma barra de rolagem vertical //+------------------------------------------------------------------+ bool CTable::CreateScrollV(void) { //--- Salvar o ponteiro do formulário m_scrollv.WindowPointer(m_wnd); //--- Coordenadas int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth(); int y=CElement::Y(); //--- Definir dimensões 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); //--- Criando uma barra de rolagem if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total)) return(false); //--- Ocultar se não for necessário agora if(m_rows_total<=m_visible_rows_total) m_scrollv.Hide(); //--- return(true); } //+------------------------------------------------------------------+ //|| Cria uma barra de rolagem horizontal //+------------------------------------------------------------------+ bool CTable::CreateScrollH(void) { //--- Salvar o ponteiro do formulário m_scrollh.WindowPointer(m_wnd); //--- Coordenadas 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(); //--- Definir dimensões 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); //--- Criando uma barra de rolagem if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total)) return(false); //--- Ocultar se não for necessário agora if(m_columns_total<=m_visible_columns_total) m_scrollh.Hide(); //--- return(true); }
//---
Mudanças semelhantes precisam ser feitas na classe CLabelsTable. As correções estarão na próxima atualização.
Esqueci de fazer uma correção, pois ela foi feita anteriormente na classe CCanvasTable.
Na classe CTable, você precisa substituir as versões atuais dos métodos CreateScrollV() e CreateScrollH() pelos métodos mostrados na listagem abaixo:
//+------------------------------------------------------------------+ //|| Cria uma barra de rolagem vertical //+------------------------------------------------------------------+ bool CTable::CreateScrollV(void) { //--- Salvar o ponteiro do formulário m_scrollv.WindowPointer(m_wnd); //--- Coordenadas int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth(); int y=CElement::Y(); //--- Definir dimensões 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); //--- Criando uma barra de rolagem if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total)) return(false); //--- Ocultar se não for necessário agora if(m_rows_total<=m_visible_rows_total) m_scrollv.Hide(); //--- return(true); } //+------------------------------------------------------------------+ //|| Cria uma barra de rolagem horizontal //+------------------------------------------------------------------+ bool CTable::CreateScrollH(void) { //--- Salvar o ponteiro do formulário m_scrollh.WindowPointer(m_wnd); //--- Coordenadas 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(); //--- Definir dimensões 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); //--- Criando uma barra de rolagem if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total)) return(false); //--- Ocultar se não for necessário agora if(m_columns_total<=m_visible_columns_total) m_scrollh.Hide(); //--- return(true); }
//---
Mudanças semelhantes precisam ser feitas na classe CLabelsTable. As correções estarão na próxima atualização.
Anatoly, as alterações foram feitas. Pegue o exemplo de MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, corrija a tabela em Program.mqh para que o número de linhas coincida com o número visível de linhas, ou o número de colunas coincida com o número visível de colunas, ou ambos. Por exemplo:
//+------------------------------------------------------------------+ //|| Cria uma tabela| //+------------------------------------------------------------------+ bool CProgram::CreateTable(void) { #define COLUMNS1_TOTAL (6) #define ROWS1_TOTAL (15) //--- Salvar o ponteiro no formulário m_table.WindowPointer(m_window1); //--- Coordenadas int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y; //--- Número de colunas e linhas visíveis intvisible_columns_total =6; intvisible_rows_total =15; //--- Definir propriedades antes da criação 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); //--- Criar um controle if(!m_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false); //--- Vamos preencher a tabela: // A primeira célula está vazia m_table.SetValue(0,0,"-"); //--- Títulos para colunas for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_table.SetValue(c,r,"SYMBOL "+string(c)); } //--- Cabeçalhos para linhas, método de alinhamento de texto - à direita 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); } } //--- Formatação de dados e tabelas (cor de fundo e cor da célula) 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); } } //--- Atualize a tabela para mostrar as alterações m_table.UpdateTable(); //--- Adicione o objeto à matriz comum de grupos de objetos CWndContainer::AddToElementsArray(0,m_table); return(true); } //+------------------------------------------------------------------+
Compile, execute o exemplo, clique na linha mais baixa da tabela (tudo está bem) e, em seguida, clique nela novamente. No segundo clique, aparece um erro:
2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1091,86)
Anatoly, as alterações foram feitas. Pegue o exemplo de MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, corrija a tabela em Program.mqh para que o número de linhas coincida com o número visível de linhas, ou o número de colunas coincida com o número visível de colunas, ou ambos. Por exemplo, assim:
...
Compile, execute o exemplo, clique na linha mais baixa da tabela (tudo está bem) e, em seguida, clique nela novamente. Um erro aparece no segundo clique:
2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1091,86)
O que fazer e o que fazer?
Nas classes CScrollH e CScrollV , nos métodos ScrollBarControl(), você precisa adicionar uma verificação adicional da visibilidade do elemento, conforme mostrado na listagem abaixo:
//+------------------------------------------------------------------+ //| Controle de rolagem| //+------------------------------------------------------------------+ bool CScrollH::ScrollBarControl(constint x,constint y,constbool mouse_state) { //--- Sair se não houver ponteiro para o formulário if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false); //--- Sair se o formulário estiver bloqueado por outro elemento if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false); //--- Sair se o item estiver oculto if(!CElement::IsVisible()) return(false); //--- Verificando o foco sobre o controle deslizante m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2()); //--- Verificar e lembrar o estado do botão do mouse CScroll::CheckMouseButtonState(mouse_state); //--- Alterar a cor da barra de rolagem da lista CScroll::ChangeObjectsColor(); //--- Se o controle for passado para a barra de rolagem, defina a posição do controle deslizante if(CScroll::ScrollState()) { //--- Movendo o controle deslizante OnDragThumb(x); //--- Altera o número da posição do controle deslizante CalculateThumbPos(); return(true); } return(false); }
//---
A correção estará disponível na próxima atualização da biblioteca.
Nas classes CScrollH e CScrollV , nos métodos ScrollBarControl(), precisamos adicionar uma verificação adicional da visibilidade do elemento, conforme mostrado na listagem abaixo:
...
A correção estará disponível na próxima atualização da biblioteca.
Obrigado. Fiz as seguintes alterações: no arquivo Scrolls.mqh, nas classes CScrollH e CScrollV, adicionei linhas:
//+------------------------------------------------------------------+ //| Controle deslizante| //+------------------------------------------------------------------+ bool CScrollV::ScrollBarControl(constint x,constint y,constbool mouse_state) { //--- Sair se não houver ponteiro para o formulário if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false); //--- Se o formulário não estiver bloqueado e os identificadores corresponderem if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false); //--- Sair se o item estiver oculto if(!CElement::IsVisible()) return(false); //--- Verificando o foco sobre o controle deslizante m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2()); //--- Verificar e lembrar o estado do botão do mouse CScroll::CheckMouseButtonState(mouse_state); //--- Alterar a cor do controle deslizante CScroll::ChangeObjectsColor(); //--- Se o controle for passado para a barra de rolagem, defina a posição do controle deslizante if(CScroll::ScrollState()) { //--- Movendo o controle deslizante OnDragThumb(y); //--- Altera o número da posição do controle deslizante CalculateThumbPos(); return(true); } //--- return(false); } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| Controle de rolagem| //+------------------------------------------------------------------+ bool CScrollH::ScrollBarControl(constint x,constint y,constbool mouse_state) { //--- Sair se não houver ponteiro para o formulário if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false); if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false); //--- Sair se o item estiver oculto if(!CElement::IsVisible()) return(false); //--- Verificando o foco sobre o controle deslizante m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2()); //--- Verificar e lembrar o estado do botão do mouse CScroll::CheckMouseButtonState(mouse_state); //--- Alterar a cor da barra de rolagem da lista CScroll::ChangeObjectsColor(); //--- Se o controle for passado para a barra de rolagem, defina a posição do controle deslizante if(CScroll::ScrollState()) { //--- Movendo o controle deslizante OnDragThumb(x); //--- Altera o número da posição do controle deslizante CalculateThumbPos(); return(true); } return(false); } //+------------------------------------------------------------------+
Compilei e executei o mesmo arquivo de teste de \MQL5\Indicators\Article07\ChartWindow02\ChartWindow02 .mq5, no qual alterei a função de criação de tabela em Program.mqh para que o número de todas as colunas e linhas coincidisse com o número de colunas e linhas visíveis:
//+------------------------------------------------------------------+ //|| Cria uma tabela| //+------------------------------------------------------------------+ bool CProgram::CreateTable(void) { #define COLUMNS1_TOTAL (6) #define ROWS1_TOTAL (15) //--- Salvar o ponteiro no formulário m_table.WindowPointer(m_window1); //--- Coordenadas int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y; //--- Número de colunas e linhas visíveis int visible_columns_total =6; int visible_rows_total =15; //--- Definir propriedades antes da criação 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); //--- Criar um controle if(!m_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false); //--- Vamos preencher a tabela: // A primeira célula está vazia m_table.SetValue(0,0,"-"); //--- Títulos para colunas for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_table.SetValue(c,r,"SYMBOL "+string(c)); } //--- Cabeçalhos para linhas, o método de alinhamento de texto é alinhado à direita 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); } } //--- Formatação de dados e tabelas (cor de fundo e cor da célula) 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); } } //--- Atualize a tabela para mostrar as alterações m_table.UpdateTable(); //--- Adicione o objeto à matriz comum de grupos de objetos CWndContainer::AddToElementsArray(0,m_table); return(true); } //+------------------------------------------------------------------+
Compilar e executar o ChartWindow02.ex5
Várias vezes clicamos na linha mais baixa da tabela e obtemos um voo fora da matriz:
2016.10.25 01:39:22.899 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1096,86)
Depois das alterações que fiz, ele não funciona mais. Talvez eu tenha feito outras alterações, mas não me lembro. Não tenho um histórico de pequenas edições.
Por via das dúvidas, tente substituir os métodos CScroll::Show() e CScroll::Hide() por estas versões, se forem diferentes:
//+------------------------------------------------------------------+ //| Mostra o item de menu| //+------------------------------------------------------------------+ void CScroll::Show(void) { //--- Sair se o número de itens da lista não for maior que o número da parte visível da lista 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); //--- Atualizar a posição dos objetos Moving(m_wnd.X(),m_wnd.Y(),true); //--- Status de visibilidade CElement::IsVisible(true); } //+------------------------------------------------------------------+ //| Oculta o item de menu| //+------------------------------------------------------------------+ 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); //--- Status de visibilidade CElement::IsVisible(false); }
//---
Se isso não ajudar, você terá que aguardar a próxima atualização.
Mas depois das alterações que fiz, ele não é mais reproduzido. Talvez eu tenha feito outras alterações, mas não me lembro. Não marco o histórico de pequenas edições.
Por via das dúvidas, tente substituir os métodos CScroll::Show() e CScroll::Hide() por estas versões, se forem diferentes:
//+------------------------------------------------------------------+ //| Mostra o item de menu| //+------------------------------------------------------------------+ void CScroll::Show(void) { //--- Sair se o número de itens da lista não for maior que o número da parte visível da lista 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); //--- Atualizar a posição dos objetos Moving(m_wnd.X(),m_wnd.Y(),true); //--- Status de visibilidade CElement::IsVisible(true); } //+------------------------------------------------------------------+ //| Oculta o item de menu| //+------------------------------------------------------------------+ 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); //--- Status de visibilidade CElement::IsVisible(false); }
//---
Se isso não ajudar, você terá que aguardar a próxima atualização.
Obrigado, parece ter ajudado. Estavam faltando linhas sobre o status de visibilidade em Show():
//--- Status de visibilidade CElement::IsVisible(true);
: e Hide():
//--- Status de visibilidade CElement::IsVisible(false);
A interatividade dos elementos da interface implementada por meio de um cronômetro é uma solução estranha. - Por que ela deveria ser implementada por meio de (ou com) um cronômetro? - É claro que isso consumirá muitos recursos.
Você não precisa de um timer para controlar os estados dos controles.
1. Registre as coordenadas atuais de todos os elementos na matriz (mapa). Faça ajustes nas coordenadas de localização de todos os objetos do formulário à medida que você move a janela.
2. Crie uma função para localizar elementos por coordenadas (localizador). A função percorrerá as coordenadas do elemento atual registrado e encontrará o elemento que está agora sob o cursor.
3. Chame o localizador a partir do evento "CHARTEVENT_MOUSE_MOVE" (no evento de movimento do cursor).
4. Passe o nome do objeto retornado pelo localizador para a função de interatividade, onde a função ObjectSetInteger() será aplicada ao objeto, o que o forçará a mudar de cor.
Como você pode ver, não há cronômetro nesse esquema, portanto, não há consumo desnecessário de recursos.
A interatividade dos elementos da interface implementada por meio de um cronômetro é uma solução estranha. - Por que ela deveria ser implementada por meio de (ou com) um cronômetro? - É claro que isso consumirá muitos recursos.
...
Como você pode ver, não há nenhum timer nesse esquema, portanto, não há consumo desnecessário de recursos.
Você está errado. Já respondi com detalhes suficientes nos comentários acima por que foi feito dessa forma.
Ele não consome muitos recursos agora (agora também no Windows 10 ). Você leu o artigo (e os comentários também)?
//---
P.S. A propósito, o consumo de recursos da CPU em diferentes terminais (MT4/MT5) e versões do sistema operacional (Windows) é muito diferente em condições iguais. No Windows 7, o terminal MetaTrader 4 se mostrou significativamente melhor do que o MetaTrader 5. Infelizmente, não posso lhe dar os números agora, pois já mudei completamente para o Windows 10.
Quanto à otimização, ainda não esgotei todas as opções. Ainda há algo a ser otimizado e um entendimento de como.
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.
Anatoly, diga-me qual é a causa do erro
Tudo funcionava bem antes dessa atualização. Agora, ao criar a tabela CTable, esse erro aparece.
Por favor, diga-me onde está o erro - já imprimi todas as linhas - a interface é criada, mas depois de algum tempo ela tropeça e .... erro.
Arquivo com um exemplo no arquivo.
Esqueci de fazer uma correção, pois ela foi feita anteriormente na classe CCanvasTable.
Na classe CTable, você precisa substituir as versões atuais dos métodos CreateScrollV() e CreateScrollH() pelos métodos mostrados na listagem abaixo:
//|| Cria uma barra de rolagem vertical
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
{
//--- Salvar o ponteiro do formulário
m_scrollv.WindowPointer(m_wnd);
//--- Coordenadas
int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
int y=CElement::Y();
//--- Definir dimensões
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);
//--- Criando uma barra de rolagem
if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
return(false);
//--- Ocultar se não for necessário agora
if(m_rows_total<=m_visible_rows_total)
m_scrollv.Hide();
//---
return(true);
}
//+------------------------------------------------------------------+
//|| Cria uma barra de rolagem horizontal
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
{
//--- Salvar o ponteiro do formulário
m_scrollh.WindowPointer(m_wnd);
//--- Coordenadas
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();
//--- Definir dimensões
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);
//--- Criando uma barra de rolagem
if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
return(false);
//--- Ocultar se não for necessário agora
if(m_columns_total<=m_visible_columns_total)
m_scrollh.Hide();
//---
return(true);
}
//---
Mudanças semelhantes precisam ser feitas na classe CLabelsTable. As correções estarão na próxima atualização.
Esqueci de fazer uma correção, pois ela foi feita anteriormente na classe CCanvasTable.
Na classe CTable, você precisa substituir as versões atuais dos métodos CreateScrollV() e CreateScrollH() pelos métodos mostrados na listagem abaixo:
...
//---
Mudanças semelhantes precisam ser feitas na classe CLabelsTable. As correções estarão na próxima atualização.
Esqueci de fazer uma correção, pois ela foi feita anteriormente na classe CCanvasTable.
Na classe CTable, você precisa substituir as versões atuais dos métodos CreateScrollV() e CreateScrollH() pelos métodos mostrados na listagem abaixo:
//|| Cria uma barra de rolagem vertical
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
{
//--- Salvar o ponteiro do formulário
m_scrollv.WindowPointer(m_wnd);
//--- Coordenadas
int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
int y=CElement::Y();
//--- Definir dimensões
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);
//--- Criando uma barra de rolagem
if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
return(false);
//--- Ocultar se não for necessário agora
if(m_rows_total<=m_visible_rows_total)
m_scrollv.Hide();
//---
return(true);
}
//+------------------------------------------------------------------+
//|| Cria uma barra de rolagem horizontal
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
{
//--- Salvar o ponteiro do formulário
m_scrollh.WindowPointer(m_wnd);
//--- Coordenadas
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();
//--- Definir dimensões
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);
//--- Criando uma barra de rolagem
if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
return(false);
//--- Ocultar se não for necessário agora
if(m_columns_total<=m_visible_columns_total)
m_scrollh.Hide();
//---
return(true);
}
//---
Mudanças semelhantes precisam ser feitas na classe CLabelsTable. As correções estarão na próxima atualização.
Anatoly, as alterações foram feitas. Pegue o exemplo de MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, corrija a tabela em Program.mqh para que o número de linhas coincida com o número visível de linhas, ou o número de colunas coincida com o número visível de colunas, ou ambos. Por exemplo:
//|| Cria uma tabela|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
{
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL (15)
//--- Salvar o ponteiro no formulário
m_table.WindowPointer(m_window1);
//--- Coordenadas
int x=m_window1.X()+TABLE1_GAP_X;
int y=m_window1.Y()+TABLE1_GAP_Y;
//--- Número de colunas e linhas visíveis
int visible_columns_total =6;
int visible_rows_total =15;
//--- Definir propriedades antes da criação
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);
//--- Criar um controle
if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
return(false);
//--- Vamos preencher a tabela:
// A primeira célula está vazia
m_table.SetValue(0,0,"-");
//--- Títulos para colunas
for(int c=1; c<COLUMNS1_TOTAL; c++)
{
for(int r=0; r<1; r++)
m_table.SetValue(c,r,"SYMBOL "+string(c));
}
//--- Cabeçalhos para linhas, método de alinhamento de texto - à direita
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);
}
}
//--- Formatação de dados e tabelas (cor de fundo e cor da célula)
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);
}
}
//--- Atualize a tabela para mostrar as alterações
m_table.UpdateTable();
//--- Adicione o objeto à matriz comum de grupos de objetos
CWndContainer::AddToElementsArray(0,m_table);
return(true);
}
//+------------------------------------------------------------------+
Compile, execute o exemplo, clique na linha mais baixa da tabela (tudo está bem) e, em seguida, clique nela novamente. No segundo clique, aparece um erro:
O que fazer e o que fazer?
Anatoly, as alterações foram feitas. Pegue o exemplo de MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, corrija a tabela em Program.mqh para que o número de linhas coincida com o número visível de linhas, ou o número de colunas coincida com o número visível de colunas, ou ambos. Por exemplo, assim:
...
Compile, execute o exemplo, clique na linha mais baixa da tabela (tudo está bem) e, em seguida, clique nela novamente. Um erro aparece no segundo clique:
O que fazer e o que fazer?
Nas classes CScrollH e CScrollV , nos métodos ScrollBarControl(), você precisa adicionar uma verificação adicional da visibilidade do elemento, conforme mostrado na listagem abaixo:
//| Controle de rolagem|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- Sair se não houver ponteiro para o formulário
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
//--- Sair se o formulário estiver bloqueado por outro elemento
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- Sair se o item estiver oculto
if(!CElement::IsVisible())
return(false);
//--- Verificando o foco sobre o controle deslizante
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//--- Verificar e lembrar o estado do botão do mouse
CScroll::CheckMouseButtonState(mouse_state);
//--- Alterar a cor da barra de rolagem da lista
CScroll::ChangeObjectsColor();
//--- Se o controle for passado para a barra de rolagem, defina a posição do controle deslizante
if(CScroll::ScrollState())
{
//--- Movendo o controle deslizante
OnDragThumb(x);
//--- Altera o número da posição do controle deslizante
CalculateThumbPos();
return(true);
}
return(false);
}
//---
A correção estará disponível na próxima atualização da biblioteca.
Nas classes CScrollH e CScrollV , nos métodos ScrollBarControl(), precisamos adicionar uma verificação adicional da visibilidade do elemento, conforme mostrado na listagem abaixo:
...
A correção estará disponível na próxima atualização da biblioteca.
Obrigado. Fiz as seguintes alterações: no arquivo Scrolls.mqh, nas classes CScrollH e CScrollV, adicionei linhas:
//| Controle deslizante|
//+------------------------------------------------------------------+
bool CScrollV::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- Sair se não houver ponteiro para o formulário
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
//--- Se o formulário não estiver bloqueado e os identificadores corresponderem
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- Sair se o item estiver oculto
if(!CElement::IsVisible())
return(false);
//--- Verificando o foco sobre o controle deslizante
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//--- Verificar e lembrar o estado do botão do mouse
CScroll::CheckMouseButtonState(mouse_state);
//--- Alterar a cor do controle deslizante
CScroll::ChangeObjectsColor();
//--- Se o controle for passado para a barra de rolagem, defina a posição do controle deslizante
if(CScroll::ScrollState())
{
//--- Movendo o controle deslizante
OnDragThumb(y);
//--- Altera o número da posição do controle deslizante
CalculateThumbPos();
return(true);
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| Controle de rolagem|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- Sair se não houver ponteiro para o formulário
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- Sair se o item estiver oculto
if(!CElement::IsVisible())
return(false);
//--- Verificando o foco sobre o controle deslizante
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//--- Verificar e lembrar o estado do botão do mouse
CScroll::CheckMouseButtonState(mouse_state);
//--- Alterar a cor da barra de rolagem da lista
CScroll::ChangeObjectsColor();
//--- Se o controle for passado para a barra de rolagem, defina a posição do controle deslizante
if(CScroll::ScrollState())
{
//--- Movendo o controle deslizante
OnDragThumb(x);
//--- Altera o número da posição do controle deslizante
CalculateThumbPos();
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
Compilei e executei o mesmo arquivo de teste de \MQL5\Indicators\Article07\ChartWindow02\ChartWindow02 .mq5, no qual alterei a função de criação de tabela em Program.mqh para que o número de todas as colunas e linhas coincidisse com o número de colunas e linhas visíveis:
//|| Cria uma tabela|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
{
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL (15)
//--- Salvar o ponteiro no formulário
m_table.WindowPointer(m_window1);
//--- Coordenadas
int x=m_window1.X()+TABLE1_GAP_X;
int y=m_window1.Y()+TABLE1_GAP_Y;
//--- Número de colunas e linhas visíveis
int visible_columns_total =6;
int visible_rows_total =15;
//--- Definir propriedades antes da criação
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);
//--- Criar um controle
if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
return(false);
//--- Vamos preencher a tabela:
// A primeira célula está vazia
m_table.SetValue(0,0,"-");
//--- Títulos para colunas
for(int c=1; c<COLUMNS1_TOTAL; c++)
{
for(int r=0; r<1; r++)
m_table.SetValue(c,r,"SYMBOL "+string(c));
}
//--- Cabeçalhos para linhas, o método de alinhamento de texto é alinhado à direita
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);
}
}
//--- Formatação de dados e tabelas (cor de fundo e cor da célula)
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);
}
}
//--- Atualize a tabela para mostrar as alterações
m_table.UpdateTable();
//--- Adicione o objeto à matriz comum de grupos de objetos
CWndContainer::AddToElementsArray(0,m_table);
return(true);
}
//+------------------------------------------------------------------+
Compilar e executar o ChartWindow02.ex5
Várias vezes clicamos na linha mais baixa da tabela e obtemos um voo fora da matriz:
...
Então nada mudou?Depois das alterações que fiz, ele não funciona mais. Talvez eu tenha feito outras alterações, mas não me lembro. Não tenho um histórico de pequenas edições.
Por via das dúvidas, tente substituir os métodos CScroll::Show() e CScroll::Hide() por estas versões, se forem diferentes:
//| Mostra o item de menu|
//+------------------------------------------------------------------+
void CScroll::Show(void)
{
//--- Sair se o número de itens da lista não for maior que o número da parte visível da lista
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);
//--- Atualizar a posição dos objetos
Moving(m_wnd.X(),m_wnd.Y(),true);
//--- Status de visibilidade
CElement::IsVisible(true);
}
//+------------------------------------------------------------------+
//| Oculta o item de menu|
//+------------------------------------------------------------------+
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);
//--- Status de visibilidade
CElement::IsVisible(false);
}
//---
Se isso não ajudar, você terá que aguardar a próxima atualização.
Mas depois das alterações que fiz, ele não é mais reproduzido. Talvez eu tenha feito outras alterações, mas não me lembro. Não marco o histórico de pequenas edições.
Por via das dúvidas, tente substituir os métodos CScroll::Show() e CScroll::Hide() por estas versões, se forem diferentes:
//| Mostra o item de menu|
//+------------------------------------------------------------------+
void CScroll::Show(void)
{
//--- Sair se o número de itens da lista não for maior que o número da parte visível da lista
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);
//--- Atualizar a posição dos objetos
Moving(m_wnd.X(),m_wnd.Y(),true);
//--- Status de visibilidade
CElement::IsVisible(true);
}
//+------------------------------------------------------------------+
//| Oculta o item de menu|
//+------------------------------------------------------------------+
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);
//--- Status de visibilidade
CElement::IsVisible(false);
}
//---
Se isso não ajudar, você terá que aguardar a próxima atualização.
Obrigado, parece ter ajudado. Estavam faltando linhas sobre o status de visibilidade em Show():
CElement::IsVisible(true);
: e Hide():
CElement::IsVisible(false);
Obrigado, parece que funcionou. Estavam faltando linhas sobre o status de visibilidade em Show():
CElement::IsVisible(true);
e Hide():
CElement::IsVisible(false);
É necessária mais uma correção. A visibilidade deve ser definida antes de atualizar a posição do elemento. Assim:
//--- Status de visibilidade
CElement::IsVisible(true);
//--- Atualizar a posição dos objetos
Moving(m_wnd.X(),m_wnd.Y(),true);
...
A interatividade dos elementos da interface implementada por meio de um cronômetro é uma solução estranha. - Por que ela deveria ser implementada por meio de (ou com) um cronômetro? - É claro que isso consumirá muitos recursos.
Você não precisa de um timer para controlar os estados dos controles.
1. Registre as coordenadas atuais de todos os elementos na matriz (mapa). Faça ajustes nas coordenadas de localização de todos os objetos do formulário à medida que você move a janela.
2. Crie uma função para localizar elementos por coordenadas (localizador). A função percorrerá as coordenadas do elemento atual registrado e encontrará o elemento que está agora sob o cursor.
3. Chame o localizador a partir do evento "CHARTEVENT_MOUSE_MOVE" (no evento de movimento do cursor).
4. Passe o nome do objeto retornado pelo localizador para a função de interatividade, onde a função ObjectSetInteger() será aplicada ao objeto, o que o forçará a mudar de cor.
Como você pode ver, não há cronômetro nesse esquema, portanto, não há consumo desnecessário de recursos.
A interatividade dos elementos da interface implementada por meio de um cronômetro é uma solução estranha. - Por que ela deveria ser implementada por meio de (ou com) um cronômetro? - É claro que isso consumirá muitos recursos.
...
Como você pode ver, não há nenhum timer nesse esquema, portanto, não há consumo desnecessário de recursos.
Você está errado. Já respondi com detalhes suficientes nos comentários acima por que foi feito dessa forma.
Ele não consome muitos recursos agora (agora também no Windows 10 ). Você leu o artigo (e os comentários também)?
//---
P.S. A propósito, o consumo de recursos da CPU em diferentes terminais (MT4/MT5) e versões do sistema operacional (Windows) é muito diferente em condições iguais. No Windows 7, o terminal MetaTrader 4 se mostrou significativamente melhor do que o MetaTrader 5. Infelizmente, não posso lhe dar os números agora, pois já mudei completamente para o Windows 10.
Quanto à otimização, ainda não esgotei todas as opções. Ainda há algo a ser otimizado e um entendimento de como.