2016.10.19 03:09:04.993 TestTable (EURUSD,H1) invalid pointer access in 'Scrolls.mqh' (698,10)
Everything worked fine before this update. Now when building the CTable table this error pops up.
Please tell me where it is wrong - I have already printed every line - the interface is built, but after somewhere stumbles, and .... error.
File with an example in the archive.
I forgot to make a correction, as it was done earlier in the CCanvasTable class.
In the CTable class, you need to replace the current versions of the CreateScrollV() and CreateScrollH() methods with the ones shown in the listing below:
//+------------------------------------------------------------------+ //|| Creates a vertical scroll bar || //+------------------------------------------------------------------+ bool CTable::CreateScrollV(void) { //--- Save the form pointer m_scrollv.WindowPointer(m_wnd); //--- Coordinates int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth(); int y=CElement::Y(); //--- Set dimensions 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); //--- Creating a scroll bar if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total)) return(false); //--- Hide if not needed now if(m_rows_total<=m_visible_rows_total) m_scrollv.Hide(); //--- return(true); } //+------------------------------------------------------------------+ //|| Creates a horizontal scroll bar || //+------------------------------------------------------------------+ bool CTable::CreateScrollH(void) { //--- Save the form pointer m_scrollh.WindowPointer(m_wnd); //--- Coordinates 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(); //--- Set dimensions 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); //--- Creating a scroll bar if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total)) return(false); //--- Hide if not needed now if(m_columns_total<=m_visible_columns_total) m_scrollh.Hide(); //--- return(true); }
//---
Similar changes need to be made in the CLabelsTable class. The fixes will be in the next update.
I forgot to make a correction as it was done earlier in the CCanvasTable class.
In the CTable class, you need to replace the current versions of the CreateScrollV() and CreateScrollH() methods with the ones shown in the listing below:
... //---
Similar changes need to be made in the CLabelsTable class. The fixes will be in the next update.
I forgot to make a correction as it was done earlier in the CCanvasTable class.
In the CTable class, you need to replace the current versions of the CreateScrollV() and CreateScrollH() methods with the ones shown in the listing below:
//+------------------------------------------------------------------+ //|| Creates a vertical scroll bar || //+------------------------------------------------------------------+ bool CTable::CreateScrollV(void) { //--- Save the form pointer m_scrollv.WindowPointer(m_wnd); //--- Coordinates int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth(); int y=CElement::Y(); //--- Set dimensions 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); //--- Creating a scroll bar if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total)) return(false); //--- Hide if not needed now if(m_rows_total<=m_visible_rows_total) m_scrollv.Hide(); //--- return(true); } //+------------------------------------------------------------------+ //|| Creates a horizontal scroll bar || //+------------------------------------------------------------------+ bool CTable::CreateScrollH(void) { //--- Save the form pointer m_scrollh.WindowPointer(m_wnd); //--- Coordinates 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(); //--- Set dimensions 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); //--- Creating a scroll bar if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total)) return(false); //--- Hide if not needed now if(m_columns_total<=m_visible_columns_total) m_scrollh.Hide(); //--- return(true); }
//---
Similar changes need to be made in the CLabelsTable class. The fixes will be in the next update.
Anatoly, the changes have been made. Take the example from MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, correct the table in Program.mqh so that the number of rows coincides with the visible number of rows, or the number of columns coincides with the visible number of columns, or both. For example:
//+------------------------------------------------------------------+ //|| Creates a table| //+------------------------------------------------------------------+ bool CProgram::CreateTable(void) { #define COLUMNS1_TOTAL (6) #define ROWS1_TOTAL (15) //--- Save the pointer to the form m_table.WindowPointer(m_window1); //--- Coordinates int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y; //--- Number of visible columns and rows intvisible_columns_total =6; intvisible_rows_total =15; //--- Set properties before creation 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); //--- Create a control if(!m_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false); //--- Let's fill in the table: // The first cell is empty m_table.SetValue(0,0,"-"); //--- Headings for columns for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_table.SetValue(c,r,"SYMBOL "+string(c)); } //--- Headings for rows, text alignment method - to the right 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); } } //--- Data and table formatting (background colour and cell colour) 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); } } //--- Update the table to show changes m_table.UpdateTable(); //--- Add the object to the common array of object groups CWndContainer::AddToElementsArray(0,m_table); return(true); } //+------------------------------------------------------------------+
Compile, run the example, click on the lowest row of the table (everything is fine), and then click on it again. On the second click an error pops up:
2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1091,86)
Anatoly, the changes have been made. Take the example from MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, correct the table in Program.mqh so that the number of rows coincides with the visible number of rows, or the number of columns coincides with the visible number of columns, or both. For example, like this:
...
Compile, run the example, click on the lowest row of the table (everything is fine), and then click on it again. An error appears on the second click:
2016.10.24 03:37:16.407 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1091,86)
What to do, and what to do?
In the CScrollH and CScrollV classes in the ScrollBarControl() methods, you need to add an additional check on the visibility of the element as shown in the listing below:
//+------------------------------------------------------------------+ //| Scroll control| //+------------------------------------------------------------------+ bool CScrollH::ScrollBarControl(constint x,constint y,constbool mouse_state) { //--- Exit if there is no pointer to the form if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false); //--- Exit if the form is blocked by another element if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false); //--- Exit if the item is hidden if(!CElement::IsVisible()) return(false); //--- Checking the focus over the slider m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2()); //--- Check and remember the state of the mouse button CScroll::CheckMouseButtonState(mouse_state); //--- Change the colour of the list scroll bar CScroll::ChangeObjectsColor(); //--- If control is passed to the scroll bar, define the slider position if(CScroll::ScrollState()) { //--- Moving the slider OnDragThumb(x); //--- Changes the slider position number CalculateThumbPos(); return(true); } return(false); }
//---
The fix will be available in the next library update.
In the CScrollH and CScrollV classes in the ScrollBarControl() methods, we need to add an additional check for the visibility of the element as shown in the listing below:
...
The fix will be available in the next library update.
Thanks. I made these changes: in the Scrolls.mqh file in the CScrollH and CScrollV classes I added lines:
//+------------------------------------------------------------------+ //| Slider control| //+------------------------------------------------------------------+ bool CScrollV::ScrollBarControl(constint x,constint y,constbool mouse_state) { //--- Exit if there is no pointer to the form if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false); //--- If the form is not locked and the identifiers match if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false); //--- Exit if the item is hidden if(!CElement::IsVisible()) return(false); //--- Checking the focus over the slider m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2()); //--- Check and remember the state of the mouse button CScroll::CheckMouseButtonState(mouse_state); //--- Change the colour of the slider CScroll::ChangeObjectsColor(); //--- If control is passed to the scroll bar, define the slider position if(CScroll::ScrollState()) { //--- Moving the slider OnDragThumb(y); //--- Changes the slider position number CalculateThumbPos(); return(true); } //--- return(false); } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| Scroll control| //+------------------------------------------------------------------+ bool CScrollH::ScrollBarControl(constint x,constint y,constbool mouse_state) { //--- Exit if there is no pointer to the form if(::CheckPointer(m_wnd)==POINTER_INVALID) return(false); if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id()) return(false); //--- Exit if the item is hidden if(!CElement::IsVisible()) return(false); //--- Checking the focus over the slider m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() && y>m_thumb.Y() && y<m_thumb.Y2()); //--- Check and remember the state of the mouse button CScroll::CheckMouseButtonState(mouse_state); //--- Change the colour of the list scroll bar CScroll::ChangeObjectsColor(); //--- If control is passed to the scroll bar, define the slider position if(CScroll::ScrollState()) { //--- Moving the slider OnDragThumb(x); //--- Changes the slider position number CalculateThumbPos(); return(true); } return(false); } //+------------------------------------------------------------------+
I compile and run the same test file from \MQL5\Indicators\Article07\ChartWindow02\ChartWindow02 .mq5, in which I changed the table building function in Program.mqh so that the number of all columns and rows coincides with the number of visible columns and rows:
//+------------------------------------------------------------------+ //|| Creates a table| //+------------------------------------------------------------------+ bool CProgram::CreateTable(void) { #define COLUMNS1_TOTAL (6) #define ROWS1_TOTAL (15) //--- Save the pointer to the form m_table.WindowPointer(m_window1); //--- Coordinates int x=m_window1.X()+TABLE1_GAP_X; int y=m_window1.Y()+TABLE1_GAP_Y; //--- Number of visible columns and rows int visible_columns_total =6; int visible_rows_total =15; //--- Set properties before creation 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); //--- Create a control if(!m_table.CreateTable(m_chart_id,m_subwin,x,y)) return(false); //--- Let's fill in the table: // The first cell is empty m_table.SetValue(0,0,"-"); //--- Headings for columns for(int c=1; c<COLUMNS1_TOTAL; c++) { for(int r=0; r<1; r++) m_table.SetValue(c,r,"SYMBOL "+string(c)); } //--- Headings for rows, text alignment method is right aligned 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); } } //--- Data and table formatting (background colour and cell colour) 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); } } //--- Update the table to show changes m_table.UpdateTable(); //--- Add the object to the common array of object groups CWndContainer::AddToElementsArray(0,m_table); return(true); } //+------------------------------------------------------------------+
Compile and run ChartWindow02.ex5
Several times we click on the lowest row of the table and get a flight outside the array:
2016.10.25 01:39:22.899 ChartWindow02 (USDCHF,H1) array out of range in 'Table.mqh' (1096,86)
After the changes I made, it doesn't play anymore. I may have made some other changes, but I don't remember. I don't have a history of minor edits.
Just in case, try replacing CScroll::Show() and CScroll::Hide() methods with these versions, if they are different:
//+------------------------------------------------------------------+ //| Shows the menu item| //+------------------------------------------------------------------+ void CScroll::Show(void) { //--- Exit if the number of list items is not greater than the number of the visible part of the list 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); //--- Update the position of objects Moving(m_wnd.X(),m_wnd.Y(),true); //--- Visibility status CElement::IsVisible(true); } //+------------------------------------------------------------------+ //| Hides the menu item| //+------------------------------------------------------------------+ 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); //--- Visibility status CElement::IsVisible(false); }
//---
If it doesn't help, you'll have to wait for the next update.
But after the changes I made, it doesn't play anymore. I may have made some other changes, but I don't remember. I don't mark the history of minor edits.
Just in case, try replacing CScroll::Show() and CScroll::Hide() methods with these versions, if they are different:
//+------------------------------------------------------------------+ //| Shows the menu item| //+------------------------------------------------------------------+ void CScroll::Show(void) { //--- Exit if the number of list items is not greater than the number of the visible part of the list 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); //--- Update the position of objects Moving(m_wnd.X(),m_wnd.Y(),true); //--- Visibility status CElement::IsVisible(true); } //+------------------------------------------------------------------+ //| Hides the menu item| //+------------------------------------------------------------------+ 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); //--- Visibility status CElement::IsVisible(false); }
//---
If it doesn't help, you'll have to wait for the next update.
Thanks, it seems to help. There were missing lines about visibility status in Show():
//--- Visibility status CElement::IsVisible(true);
: and Hide():
//--- Visibility status CElement::IsVisible(false);
Interactivity of interface elements implemented via timer is a strange solution. - Why should it be implemented through (or with) a timer? - Of course, it will consume a lot of resources.
You don't need a timer at all to control the states of controls.
1. Record the current coordinates of all elements in the array (map). Make adjustments to the location coordinates of all form objects as you move the window.
2. Make a function to find elements by coordinates (localiser). The function will loop through the recorded current element coordinates and find the element that is now under the cursor.
3. Call the localiser from the "CHARTEVENT_MOUSE_MOVE" event (on the cursor movement event).
4. Pass the object name returned from the localiser to the interactivity function, where the ObjectSetInteger() function will be applied to the object, which will force it to change its colour.
As you can see, there is no timer in this scheme, so there is no unnecessary consumption of resources.
Interactivity of interface elements implemented via timer is a strange solution. - Why should it be implemented through (or with) a timer? - Of course, it will consume a lot of resources.
...
As you can see, there is no timer in this scheme, so there is no unnecessary resource consumption.
You are wrong. I have already answered in enough detail in the comments above why it was done this way.
It doesn't consume a lot of resources now (now in Windows 10 too). Did you read the article (and the comments too) ?
//---
P.S. By the way, CPU resource consumption in different terminals (MT4/MT5) and OS versions (Windows) is very different under equal conditions. In Windows 7 the MetaTrader 4 terminal showed itself significantly better than MetaTrader 5. Unfortunately, I can't give you the figures now, as I have already completely switched to Windows 10.
As for optimisation, I have not exhausted all the options yet. There is still something to optimise and an understanding of how.
Allow the use of cookies to log in to the MQL5.com website.
Please enable the necessary setting in your browser, otherwise you will not be able to log in.
You are signed in. Two-factor authentication has been disabled. Set it up again and scan a new QR code, or continue with two-factor authentication disabled.
Anatoly, tell me what the cause of the error is
Everything worked fine before this update. Now when building the CTable table this error pops up.
Please tell me where it is wrong - I have already printed every line - the interface is built, but after somewhere stumbles, and .... error.
File with an example in the archive.
I forgot to make a correction, as it was done earlier in the CCanvasTable class.
In the CTable class, you need to replace the current versions of the CreateScrollV() and CreateScrollH() methods with the ones shown in the listing below:
//|| Creates a vertical scroll bar ||
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
{
//--- Save the form pointer
m_scrollv.WindowPointer(m_wnd);
//--- Coordinates
int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
int y=CElement::Y();
//--- Set dimensions
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);
//--- Creating a scroll bar
if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
return(false);
//--- Hide if not needed now
if(m_rows_total<=m_visible_rows_total)
m_scrollv.Hide();
//---
return(true);
}
//+------------------------------------------------------------------+
//|| Creates a horizontal scroll bar ||
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
{
//--- Save the form pointer
m_scrollh.WindowPointer(m_wnd);
//--- Coordinates
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();
//--- Set dimensions
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);
//--- Creating a scroll bar
if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
return(false);
//--- Hide if not needed now
if(m_columns_total<=m_visible_columns_total)
m_scrollh.Hide();
//---
return(true);
}
//---
Similar changes need to be made in the CLabelsTable class. The fixes will be in the next update.
I forgot to make a correction as it was done earlier in the CCanvasTable class.
In the CTable class, you need to replace the current versions of the CreateScrollV() and CreateScrollH() methods with the ones shown in the listing below:
...
//---
Similar changes need to be made in the CLabelsTable class. The fixes will be in the next update.
I forgot to make a correction as it was done earlier in the CCanvasTable class.
In the CTable class, you need to replace the current versions of the CreateScrollV() and CreateScrollH() methods with the ones shown in the listing below:
//|| Creates a vertical scroll bar ||
//+------------------------------------------------------------------+
bool CTable::CreateScrollV(void)
{
//--- Save the form pointer
m_scrollv.WindowPointer(m_wnd);
//--- Coordinates
int x=(m_anchor_right_window_side)? m_x-m_x_size+m_scrollv.ScrollWidth() : CElement::X2()-m_scrollv.ScrollWidth();
int y=CElement::Y();
//--- Set dimensions
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);
//--- Creating a scroll bar
if(!m_scrollv.CreateScroll(m_chart_id,m_subwin,x,y,m_rows_total,m_visible_rows_total))
return(false);
//--- Hide if not needed now
if(m_rows_total<=m_visible_rows_total)
m_scrollv.Hide();
//---
return(true);
}
//+------------------------------------------------------------------+
//|| Creates a horizontal scroll bar ||
//+------------------------------------------------------------------+
bool CTable::CreateScrollH(void)
{
//--- Save the form pointer
m_scrollh.WindowPointer(m_wnd);
//--- Coordinates
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();
//--- Set dimensions
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);
//--- Creating a scroll bar
if(!m_scrollh.CreateScroll(m_chart_id,m_subwin,x,y,m_columns_total,m_visible_columns_total))
return(false);
//--- Hide if not needed now
if(m_columns_total<=m_visible_columns_total)
m_scrollh.Hide();
//---
return(true);
}
//---
Similar changes need to be made in the CLabelsTable class. The fixes will be in the next update.
Anatoly, the changes have been made. Take the example from MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, correct the table in Program.mqh so that the number of rows coincides with the visible number of rows, or the number of columns coincides with the visible number of columns, or both. For example:
//|| Creates a table|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
{
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL (15)
//--- Save the pointer to the form
m_table.WindowPointer(m_window1);
//--- Coordinates
int x=m_window1.X()+TABLE1_GAP_X;
int y=m_window1.Y()+TABLE1_GAP_Y;
//--- Number of visible columns and rows
int visible_columns_total =6;
int visible_rows_total =15;
//--- Set properties before creation
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);
//--- Create a control
if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
return(false);
//--- Let's fill in the table:
// The first cell is empty
m_table.SetValue(0,0,"-");
//--- Headings for columns
for(int c=1; c<COLUMNS1_TOTAL; c++)
{
for(int r=0; r<1; r++)
m_table.SetValue(c,r,"SYMBOL "+string(c));
}
//--- Headings for rows, text alignment method - to the right
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);
}
}
//--- Data and table formatting (background colour and cell colour)
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);
}
}
//--- Update the table to show changes
m_table.UpdateTable();
//--- Add the object to the common array of object groups
CWndContainer::AddToElementsArray(0,m_table);
return(true);
}
//+------------------------------------------------------------------+
Compile, run the example, click on the lowest row of the table (everything is fine), and then click on it again. On the second click an error pops up:
What to do, and what to do?
Anatoly, the changes have been made. Take the example from MQL5\Indicators\Article07\ChartWindow02\ChartWindow02.mq5, correct the table in Program.mqh so that the number of rows coincides with the visible number of rows, or the number of columns coincides with the visible number of columns, or both. For example, like this:
...
Compile, run the example, click on the lowest row of the table (everything is fine), and then click on it again. An error appears on the second click:
What to do, and what to do?
In the CScrollH and CScrollV classes in the ScrollBarControl() methods, you need to add an additional check on the visibility of the element as shown in the listing below:
//| Scroll control|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- Exit if there is no pointer to the form
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
//--- Exit if the form is blocked by another element
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- Exit if the item is hidden
if(!CElement::IsVisible())
return(false);
//--- Checking the focus over the slider
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//--- Check and remember the state of the mouse button
CScroll::CheckMouseButtonState(mouse_state);
//--- Change the colour of the list scroll bar
CScroll::ChangeObjectsColor();
//--- If control is passed to the scroll bar, define the slider position
if(CScroll::ScrollState())
{
//--- Moving the slider
OnDragThumb(x);
//--- Changes the slider position number
CalculateThumbPos();
return(true);
}
return(false);
}
//---
The fix will be available in the next library update.
In the CScrollH and CScrollV classes in the ScrollBarControl() methods, we need to add an additional check for the visibility of the element as shown in the listing below:
...
The fix will be available in the next library update.
Thanks. I made these changes: in the Scrolls.mqh file in the CScrollH and CScrollV classes I added lines:
//| Slider control|
//+------------------------------------------------------------------+
bool CScrollV::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- Exit if there is no pointer to the form
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
//--- If the form is not locked and the identifiers match
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- Exit if the item is hidden
if(!CElement::IsVisible())
return(false);
//--- Checking the focus over the slider
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//--- Check and remember the state of the mouse button
CScroll::CheckMouseButtonState(mouse_state);
//--- Change the colour of the slider
CScroll::ChangeObjectsColor();
//--- If control is passed to the scroll bar, define the slider position
if(CScroll::ScrollState())
{
//--- Moving the slider
OnDragThumb(y);
//--- Changes the slider position number
CalculateThumbPos();
return(true);
}
//---
return(false);
}
//+------------------------------------------------------------------+
//| Scroll control|
//+------------------------------------------------------------------+
bool CScrollH::ScrollBarControl(const int x,const int y,const bool mouse_state)
{
//--- Exit if there is no pointer to the form
if(::CheckPointer(m_wnd)==POINTER_INVALID)
return(false);
if(m_wnd.IsLocked() && m_wnd.IdActivatedElement()!=CElement::Id())
return(false);
//--- Exit if the item is hidden
if(!CElement::IsVisible())
return(false);
//--- Checking the focus over the slider
m_thumb.MouseFocus(x>m_thumb.X() && x<m_thumb.X2() &&
y>m_thumb.Y() && y<m_thumb.Y2());
//--- Check and remember the state of the mouse button
CScroll::CheckMouseButtonState(mouse_state);
//--- Change the colour of the list scroll bar
CScroll::ChangeObjectsColor();
//--- If control is passed to the scroll bar, define the slider position
if(CScroll::ScrollState())
{
//--- Moving the slider
OnDragThumb(x);
//--- Changes the slider position number
CalculateThumbPos();
return(true);
}
return(false);
}
//+------------------------------------------------------------------+
I compile and run the same test file from \MQL5\Indicators\Article07\ChartWindow02\ChartWindow02 .mq5, in which I changed the table building function in Program.mqh so that the number of all columns and rows coincides with the number of visible columns and rows:
//|| Creates a table|
//+------------------------------------------------------------------+
bool CProgram::CreateTable(void)
{
#define COLUMNS1_TOTAL (6)
#define ROWS1_TOTAL (15)
//--- Save the pointer to the form
m_table.WindowPointer(m_window1);
//--- Coordinates
int x=m_window1.X()+TABLE1_GAP_X;
int y=m_window1.Y()+TABLE1_GAP_Y;
//--- Number of visible columns and rows
int visible_columns_total =6;
int visible_rows_total =15;
//--- Set properties before creation
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);
//--- Create a control
if(!m_table.CreateTable(m_chart_id,m_subwin,x,y))
return(false);
//--- Let's fill in the table:
// The first cell is empty
m_table.SetValue(0,0,"-");
//--- Headings for columns
for(int c=1; c<COLUMNS1_TOTAL; c++)
{
for(int r=0; r<1; r++)
m_table.SetValue(c,r,"SYMBOL "+string(c));
}
//--- Headings for rows, text alignment method is right aligned
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);
}
}
//--- Data and table formatting (background colour and cell colour)
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);
}
}
//--- Update the table to show changes
m_table.UpdateTable();
//--- Add the object to the common array of object groups
CWndContainer::AddToElementsArray(0,m_table);
return(true);
}
//+------------------------------------------------------------------+
Compile and run ChartWindow02.ex5
Several times we click on the lowest row of the table and get a flight outside the array:
...
So nothing has changed?After the changes I made, it doesn't play anymore. I may have made some other changes, but I don't remember. I don't have a history of minor edits.
Just in case, try replacing CScroll::Show() and CScroll::Hide() methods with these versions, if they are different:
//| Shows the menu item|
//+------------------------------------------------------------------+
void CScroll::Show(void)
{
//--- Exit if the number of list items is not greater than the number of the visible part of the list
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);
//--- Update the position of objects
Moving(m_wnd.X(),m_wnd.Y(),true);
//--- Visibility status
CElement::IsVisible(true);
}
//+------------------------------------------------------------------+
//| Hides the menu item|
//+------------------------------------------------------------------+
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);
//--- Visibility status
CElement::IsVisible(false);
}
//---
If it doesn't help, you'll have to wait for the next update.
But after the changes I made, it doesn't play anymore. I may have made some other changes, but I don't remember. I don't mark the history of minor edits.
Just in case, try replacing CScroll::Show() and CScroll::Hide() methods with these versions, if they are different:
//| Shows the menu item|
//+------------------------------------------------------------------+
void CScroll::Show(void)
{
//--- Exit if the number of list items is not greater than the number of the visible part of the list
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);
//--- Update the position of objects
Moving(m_wnd.X(),m_wnd.Y(),true);
//--- Visibility status
CElement::IsVisible(true);
}
//+------------------------------------------------------------------+
//| Hides the menu item|
//+------------------------------------------------------------------+
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);
//--- Visibility status
CElement::IsVisible(false);
}
//---
If it doesn't help, you'll have to wait for the next update.
Thanks, it seems to help. There were missing lines about visibility status in Show():
CElement::IsVisible(true);
: and Hide():
CElement::IsVisible(false);
Thanks, it seems to have worked. There were missing lines about visibility status in Show():
CElement::IsVisible(true);
and Hide():
CElement::IsVisible(false);
One more correction is needed. Visibility should be set before updating the position of the element. Like this:
//--- Visibility status
CElement::IsVisible(true);
//--- Update the position of objects
Moving(m_wnd.X(),m_wnd.Y(),true);
...
Interactivity of interface elements implemented via timer is a strange solution. - Why should it be implemented through (or with) a timer? - Of course, it will consume a lot of resources.
You don't need a timer at all to control the states of controls.
1. Record the current coordinates of all elements in the array (map). Make adjustments to the location coordinates of all form objects as you move the window.
2. Make a function to find elements by coordinates (localiser). The function will loop through the recorded current element coordinates and find the element that is now under the cursor.
3. Call the localiser from the "CHARTEVENT_MOUSE_MOVE" event (on the cursor movement event).
4. Pass the object name returned from the localiser to the interactivity function, where the ObjectSetInteger() function will be applied to the object, which will force it to change its colour.
As you can see, there is no timer in this scheme, so there is no unnecessary consumption of resources.
Interactivity of interface elements implemented via timer is a strange solution. - Why should it be implemented through (or with) a timer? - Of course, it will consume a lot of resources.
...
As you can see, there is no timer in this scheme, so there is no unnecessary resource consumption.
You are wrong. I have already answered in enough detail in the comments above why it was done this way.
It doesn't consume a lot of resources now (now in Windows 10 too). Did you read the article (and the comments too) ?
//---
P.S. By the way, CPU resource consumption in different terminals (MT4/MT5) and OS versions (Windows) is very different under equal conditions. In Windows 7 the MetaTrader 4 terminal showed itself significantly better than MetaTrader 5. Unfortunately, I can't give you the figures now, as I have already completely switched to Windows 10.
As for optimisation, I have not exhausted all the options yet. There is still something to optimise and an understanding of how.