dcsimg
Results 1 to 7 of 7

Thread: Copy all contents of a Tab in SStab into another

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Nov 2016
    Posts
    21

    Copy all contents of a Tab in SStab into another

    In a my project I have an indexed sstab container and I want to dynamically increase or decrease the number of tabs by copying all the content from the first into the new ones so that they all have the same contents (Frame, msflexgrid, etc.) with the same dimensions and locations. How can I do it? Is it possible with a "For ... each" loop?

  2. #2
    New Member
    Join Date
    Jan 2017
    Posts
    7

    Re: Copy all contents of a Tab in SStab into another

    Here is a simply way to copy the contents o a Tab is creating the controls as a control array.
    Now a control, in a SSTab, is in the current tab is if the left property is postive else left is negative.
    It could be used for positioning correctly the loaded control in the correct tab.
    I don't know how automate the Load of the new tab, but it can be done manually.
    You can see how to do it in the atacched file
    Attached Files Attached Files

  3. #3
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    4,617

    Re: Copy all contents of a Tab in SStab into another

    Here's some code that may help you to understand how the SSTab works. It's just used to dynamically (runtime) change the tab on which a control resides (be sure to read my comments in that code):

    Code:
    
    
    Public Sub ChangeTheSSTab(SSctl As Control, ctl() As Control, OldTab As Long, NewTab As Long, Optional bRestoreTheTab As Boolean)
        ' Hide the form with the SSTab before doing this.
        ' You must get the OldTab correct or everything blows up.
        ' Alternatively, this procedure could have "found" it, but that wastes time.
        ' This procedure does NOT work in form_load, but it DOES work in form_activate.
        ' Also, when using this, don't forget to deal with the TabIndex if you need to !!!!
        Dim OrigTab As Long
        Dim i As Long
        '
        If bRestoreTheTab Then OrigTab = SSctl.Tab
        '
        SSctl.Tab = OldTab
        For i = LBound(ctl) To UBound(ctl)
            If TypeName(ctl(i)) = "Line" Then
                ctl(i).x1 = ctl(i).x1 - 75000
                ctl(i).x2 = ctl(i).x2 - 75000
            Else
                ctl(i).Left = ctl(i).Left - 75000
            End If
        Next i
        SSctl.Tab = NewTab
        For i = LBound(ctl) To UBound(ctl)
            If TypeName(ctl(i)) = "Line" Then
                ctl(i).x1 = ctl(i).x1 + 75000
                ctl(i).x2 = ctl(i).x2 + 75000
            Else
                ctl(i).Left = ctl(i).Left + 75000
            End If
        Next i
        '
        If bRestoreTheTab Then SSctl.Tab = OrigTab
    End Sub
    
    

    Some people are confused about this, but the SSTab control is a single container. Each tab isn't a separate container. That code above sort of illustrates this.

    ---------

    And also, in one spot, I do pretty much exactly what you outlined. However, it's so integrated into my software that it's difficult to cut out. Basically, in design view, I've got an SSTab with one tab, and a zero-indexed invisible control for any/all controls I may want to add as tabs are dynamically added.

    Basically, I increment the SSTab.Tabs property to add tabs. Then, I use SSTab.Tab to set the new tab as current. And then, I just use Load txt(NextIndex) to add controls, using txt(NextIndex).Container = SSTab to set the container (remembering to set the .Tab property before doing this).

    Then, just set your .Left and .Top properties of your controls, and you've got it. Here's a code snippet (not complete) that shows how I do it. The rs is a DAO Recordset that defines how many tabs and controls I want.

    Code:
    
        '
        ' Now we build the SSTab.
        '
        ' Just add all the tabs first.
        iTab = 0
        rs.Index = "PrimaryKey"
        rs.MoveFirst    ' We've already verified that it has records.
        '
        Do While Not rs.EOF
            If iTab <> 0 Then tabKeywords.Tabs = tabKeywords.Tabs + 1
            lInc iTab
            rs.MoveNext
        Loop
        '
        ' Figure out how many tab rows.
        ' iTab will be a true count at this point.
        iTabRows = (iTab + 3) \ 4
        Height = Height + (iTabRows - 1) * tabKeywords.TabHeight
        Top = (ScreenHeight - Height) \ 3
        tabKeywords.Height = tabKeywords.Height + (iTabRows - 1) * tabKeywords.TabHeight
        '
        ' And now add all the comboboxes.
        iTab = 0
        rs.Index = "PrimaryKey"
        rs.MoveFirst    ' We've already verified that it has records.
        '
        Const TopDiff = 420
        Const lblTopFirst = 840
        Const cboTopFirst = 780
        Const cmdTopFirst = 840
        Const lblLeft = 3300
        Const cboLeft = 7380
        Const cmdLeft = 12120
        Do While Not rs.EOF
            tabKeywords.Tab = iTab
            tabKeywords.TabCaption(iTab) = TextVal(rs![category])
            iCnt = LongValNum(rs![MaxKeywords])
            For i = 1 To iCnt
                lInc ctlIdxAdd
                Load cbo(ctlIdxAdd): Set cbo(ctlIdxAdd).Container = tabKeywords
                Load lbl(ctlIdxAdd): Set lbl(ctlIdxAdd).Container = tabKeywords
                Load cmd(ctlIdxAdd): Set cmd(ctlIdxAdd).Container = tabKeywords
                '
                lbl(ctlIdxAdd).Left = lblLeft
                lbl(ctlIdxAdd).Top = lblTopFirst + ((i - 1) * TopDiff) + ((iTabRows - 1) * tabKeywords.TabHeight)
                lbl(ctlIdxAdd).Visible = True
                lbl(ctlIdxAdd).Caption = TextVal(rs![category]) & " #" & Format$(i) & ":"
                lbl(ctlIdxAdd).Tag = TextVal(rs![category]) ' This is the NON-lower-case version.
                '
                cbo(ctlIdxAdd).Left = cboLeft
                cbo(ctlIdxAdd).Top = cboTopFirst + ((i - 1) * TopDiff) + ((iTabRows - 1) * tabKeywords.TabHeight)
                cbo(ctlIdxAdd).Visible = True
                cbo(ctlIdxAdd).Tag = LCase$(TextVal(rs![category]))
                '
                cmd(ctlIdxAdd).Left = cmdLeft
                cmd(ctlIdxAdd).Top = cmdTopFirst + ((i - 1) * TopDiff) + ((iTabRows - 1) * tabKeywords.TabHeight)
                cmd(ctlIdxAdd).Visible = True
            Next i
            lInc iTab
            rs.MoveNext
        Loop
    
    

    Maybe that'll help.

    Elroy
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Nov 2016
    Posts
    21

    Re: Copy all contents of a Tab in SStab into another

    Thanks Elroy and gilman.
    I've tried the Gilman code.
    This code do not add the controls that are inside the frames and the program stops with the error "5".
    Is there any other solution?

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Nov 2016
    Posts
    21

    Re: Copy all contents of a Tab in SStab into another

    Thanks Elroy and gilman.
    I've tried the Gilman code.
    This code do not add the controls that are inside the frames and the program stops with the error "5".
    Is there any other solution?

  6. #6
    New Member
    Join Date
    Jan 2017
    Posts
    7

    Re: Copy all contents of a Tab in SStab into another

    Quote Originally Posted by fabel358 View Post
    Thanks Elroy and gilman.
    I've tried the Gilman code.
    This code do not add the controls that are inside the frames and the program stops with the error "5".
    Is there any other solution?
    A posible solution is to clon the Frame, but it force the contained controls to be an array of controls, and the cloning function must be recursive, another aproach is create a user control to substitute each controls container, see the project contained in the atacched file.
    It is based in the other project, but have slight modifications, and the changes can be aplied to the other porject.
    Attached Files Attached Files
    Last edited by gilman; Yesterday at 10:36 AM. Reason: An error in the atached file

  7. #7
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    4,617

    Re: Copy all contents of a Tab in SStab into another

    The following is a little class module I use to fix a problem with the TabStops on the SSTab control. You're welcome to use it as is. However, the reason I'm posting it is that it provides an example of how to identify all the controls that are on a particular SSTab. You've got to recursively check the container of all the controls (including the container's container, etc, recursively).

    Doing that will allow you to figure out the complete list of controls on any SSTab, and then do with them what you like. Feel free to work that code into anything that'll help you get your task done.


    Code:
    
    Option Explicit
    '
    Dim WithEvents tabCtl As SSTab
    Dim frm As Form
    Dim TabStops() As Boolean
    '
    ' A primary purpose of this fix is to correctly control the tab stops.
    ' To make the appearance of tabs, the SSTab control simply moves the controls out of view.
    ' An artifact of this approach is that the controls are still able to get the focus when the
    ' user uses the TAB key.  The following code corrects this problem by appropriately turning
    ' on and off the TabStop properties of the controls as the user tabs from one tab to another.
    '
    ' Another problem has to do with ComboBoxes.  When changing to a new tab, dropdown comboboxes
    ' will have their text selected.  The combobox will not have the focus, but their text will be
    ' selected.  The primary problem with this is that it right-justifies the text when there is more
    ' text than will fit in the textbox portion of the combobox, and this is confusing to users.
    ' This problem is corrected in the following code.
    '
    
    Friend Sub SetTabControl(TheTabControl As SSTab, TheForm As Form)
        ' Call this in the form load event.
        Dim ctl As Control
        Dim Ptr As Long
        '
        Set tabCtl = TheTabControl
        Set frm = TheForm
        '
        ' Store the true value of the TabStops.
        ReDim TabStops(0 To frm.Controls.Count - 1)
        ' Not all controls have TabStop property, so we must set error trapping.
        On Error Resume Next
            For Ptr = 0 To frm.Controls.Count - 1
                TabStops(Ptr) = frm.Controls(Ptr).TabStop
            Next Ptr
        On Error GoTo 0
    End Sub
    
    Friend Sub SetTabStopsAccordingly()
        ' Call this in the form activate event.
        ' After this first call, it will automatically be called when the tabs change.
        Dim ctl As Control
        Dim ctlTheControlOrContainer As Control
        Dim ItsOnTheTabControl As Boolean
        Dim Ptr As Long
        '
        For Ptr = 0 To frm.Controls.Count - 1
            Set ctl = frm.Controls(Ptr)
            If bHasContainer(ctl) Then
                Set ctlTheControlOrContainer = ctl ' The control might be on a container that's on the SSTab, rather than directly on the SSTab.
                Do
                    Select Case True
                    Case TypeOf ctlTheControlOrContainer.Container Is SSTab
                        ItsOnTheTabControl = True
                        Exit Do ' The way out.
                    Case TypeOf ctlTheControlOrContainer.Container Is Form
                        ItsOnTheTabControl = False
                        Exit Do ' The way out.
                    End Select
                    Set ctlTheControlOrContainer = ctlTheControlOrContainer.Container ' Must deal with controls nested deeper than the SSTab control.
                Loop
                If ItsOnTheTabControl Then
                    ' Not all controls have TabStop property, so we must set error trapping.
                    On Error Resume Next
                        If ctlTheControlOrContainer.Left >= 0 Then
                            ctl.TabStop = TabStops(Ptr) ' If it's showing, restore the original TabStop value.
                            ' Must also fix the problem with combo boxes having an internal focus set.
                            ctl.SelStart = 0
                            ctl.SelLength = 0
                        Else
                            ctl.TabStop = False
                        End If
                    On Error GoTo 0
                End If
            End If
        Next Ptr
    End Sub
    
    Private Sub tabCtl_Click(PreviousTab As Integer)
        SetTabStopsAccordingly
    End Sub
    
    Private Sub tabCtl_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
        ' This allows other controls to close up when user click off.
        ' The problem is that clicking into the body of the tab control does NOT cause change in focus.
        ' The control with the focus keeps it, and it may not close up as typically happens when clicking on dead space of a form.
        ' You may also want to consider placing this "SetFocus" code on the labels on the tabs.  This is NOT automatically done
        ' because the programmer may want to use a label click for other purposes.
        tabCtl.SetFocus
    End Sub
    
    

    If you wish to use that class "as is", I typically have it named "cls_Gen_FixTabCtl", and then put the following at the top of any form that'll be using it:

    Code:
    
    Dim FixTabControl As New cls_Gen_FixTabCtl
    

    And then, this in the Form_Load event:

    Code:
    
    FixTabControl.SetTabControl tabExamData, Me
    

    And lastly, this in the Form_Activate event:

    Code:
    
    FixTabControl.SetTabStopsAccordingly
    

    Everything else takes care of itself.


    Maybe That'll Help,
    Elroy

    EDIT1: Here's the bHasContainer code:

    Code:
    
    Public Function bHasContainer(TheControl As Control) As Boolean
        Dim TheContainer As Control
        On Error GoTo NoContainer
        Set TheContainer = TheControl.Container
        bHasContainer = True
    NoContainer:
    End Function
    
    
    Any software I post in these forums written by me is provided “AS IS” without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. Please understand that I’ve been programming since the mid-1970s and still have some of that code. My contemporary VB6 project is approaching 1,000 modules. In addition, I have a “VB6 random code folder” that is overflowing. I’ve been at this long enough to truly not know with absolute certainty from whence every single line of my code has come, with much of it coming from programmers under my employ who signed intellectual property transfers. I have not deliberately attempted to remove any licenses and/or attributions from any software. If someone finds that I have inadvertently done so, I sincerely apologize, and, upon notice and reasonable proof, will re-attach those licenses and/or attributions. To all, peace and happiness.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width