Discussion of article "DoEasy. Controls (Part 19): Scrolling tabs in TabControl, WinForms object events"

 

New article DoEasy. Controls (Part 19): Scrolling tabs in TabControl, WinForms object events has been published:

In this article, I will create the functionality for scrolling tab headers in TabControl using scrolling buttons. The functionality is meant to place tab headers into a single line from either side of the control.

Compile the EA and launch it on the chart:


As we can see, everything works as intended.

There are two shortcomings though: if you hover over the tab header area that is hidden, the header reacts by changing color, as if it were visible in this area. This is the reason why the active area of the control does not change its size when the visible area is resized. To fix this, I will need to calculate and resize the active area in accordance with the visible one.

The second shortcoming is that if you move the selected header outside the container and move the panel, then two pixels of the hidden header will be displayed. This has to do with sizing the tab for the scope calculation, as the selected header increases in size on each side by two pixels. To fix this, I need to find a way to get the size of the adjacent header inside the tab header object, according to which the size of the visibility area is calculated.

Author: Artyom Trishkin

 
Wow. That's handy. So much potential for use.
I'll have to check out the other articles in the series.
Thanks to the author
 

When moving the mouse and scrolling the wheel above the panel, the chart itself can sometimes scroll.

How to get the created element unambiguously? If we have already had elements of GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL type before, then using index 0 will be wrong.

pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,InpTabControlX,InpTabControlY,pnl.Width()-30,pnl.Height()-40,clrNONE,255,true,false);
CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0);

Next... We got the id of the header of the tab of interest:

int my_id=-1;
...
CTabHeader *th=tc.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_HEADER,4);
my_id=th.ID();

Catch the change event of the active tab, more precisely, the event of clicking on the header. When clicking on the active tab, the event is still generated.

if((id-CHARTEVENT_CUSTOM==WF_CONTROL_EVENT_TAB_SELECT)&&(lparam==my_id))
     {
      Print(sparam);
     }

Now how to get the object of the active field? It's a CTabField, right?

How to find out the parent object?

 
Aliaksandr Hryshyn tab, the event is still generated.

Now how to get the object of the active field? It's a CTabField, right?

How to find out the parent object?

1. Index 0 is used for the very first created attached object to the element. Index 1 is for the second, index 2 is for the third, and so on.

2. You can retrieve a field from the retrieved header by the index of interest:

         //--- Create TabControl control element
         pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,InpTabControlX,InpTabControlY,pnl.Width()-30,pnl.Height()-40,clrNONE,255,true,false);
         CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0);
         if(tc!=NULL)
           {
            CTabHeader *th=tc.GetTabHeader(index);
            CTabField  *tf=th.GetFieldObj();
           }

2.1 You can retrieve the tab field from the TabControl object at the index of interest:

         //--- Create TabControl control element
         pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,InpTabControlX,InpTabControlY,pnl.Width()-30,pnl.Height()-40,clrNONE,255,true,false);
         CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0);
         if(tc!=NULL)
           {
            CTabField  *tf=tc.GetTabField(index);
           }

3. I don't quite understand the question. If you need to find out which object the current one is bound to, it should work like this:

      pnl=engine.CreateWFPanel("WinForms Panel"+(string)i,(i==0 ? 50 : 70),(i==0 ? 50 : 70),410,200,array_clr,200,true,true,false,-1,FRAME_STYLE_BEVEL,true,false);
      if(pnl!=NULL)
        {
         pnl.Hide();
         Print(DFUN,"Panel Description: ",pnl.Description(),", Type and name: ",pnl.TypeElementDescription()," ",pnl.Name());
         //--- Set Padding to 4
         pnl.SetPaddingAll(3);
         //--- Set the flags for displacement, auto resize and auto resize mode from the input parameters
         pnl.SetMovable(InpMovable);
         pnl.SetAutoSize(InpAutoSize,false);
         pnl.SetAutoSizeMode((ENUM_CANV_ELEMENT_AUTO_SIZE_MODE)InpAutoSizeMode,false);
   
         //--- Create TabControl control element
         pnl.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,InpTabControlX,InpTabControlY,pnl.Width()-30,pnl.Height()-40,clrNONE,255,true,false);
         CTabControl *tc=pnl.GetElementByType(GRAPH_ELEMENT_TYPE_WF_TAB_CONTROL,0);
         if(tc!=NULL)
           {
            CTabField  *tf=tc.GetTabField(index);  // Get tab field from TabControl element tc
            CWinFormBase *base=tf.GetBase();       // Find out the base object for the tab field - must be TabControl tc
            CWinFormBase *main=tf.GetMain();       // Find out the main object for the tab field - must be CPanel pnl
           }

If it doesn't return the objects specified in the comments this way, then it's a bug and needs to be refined