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?
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
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.
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?
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?
Re: Copy all contents of a Tab in SStab into another
Originally Posted by fabel358
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.
Last edited by gilman; Oct 18th, 2018 at 10:36 AM.
Reason: An error in the atached file
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.
Re: Copy all contents of a Tab in SStab into another
Still something wrong... Why the left of the controls (Frame.left , Flexgrid.left) in the sstab1.tab = 1 give me the value -74760 while .top is correct?
Re: Copy all contents of a Tab in SStab into another
Originally Posted by fabel358
Still something wrong... Why the left of the controls (Frame.left , Flexgrid.left) in the sstab1.tab = 1 give me the value -74760 while .top is correct?
That's how the SSTab hides the controls that are not in the current tab, placing them far on the left.
Code:
If SomeControl.Left < -15000 Then
ActualControlLeft = SomeControl.Left + 75000
Else
ActualControlLeft = SomeControl.Left
End If
Re: Copy all contents of a Tab in SStab into another
Originally Posted by fabel358
Still something wrong... Why the left of the controls (Frame.left , Flexgrid.left) in the sstab1.tab = 1 give me the value -74760 while .top is correct?
If the control is in the current tab, the left property is positive, if the control is not in the current tab the left property is OriginalLeft -75000
→ The Comprehensive Guide to Cloud Computing
A complete overview of Cloud Computing focused on what you need to know, from selecting a platform to choosing a cloud vendor.