Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Some more info, I now concluded that the change from -74880 set of values to the -8583 set happens somewhere between Form_Load() and Form_Activate(), meaning they have changed when checked in the latter event. I don't have the order of form events in my head, so not sure if there is an even in between or not, but too tired to check any further right now.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Ok that didn't work, sleep I mean... but think I'm closer to solving the mystery. It appears the whole thing with trowing the containers a hard left jab happens in the Form_Resize event, even though I have no code there - except for debug code now. However, I do have a resizer control on the form that resize controls proportionally on form resize and I suspect that it at least play a part in this. Question is though why it plays havoc with controls placed on SSTabEx and and not other container controls? "It takes two to tango" so to speak, so even if it plays a part, I suspect there may be some "weakness" in SSTabEx's container walls allowing (or even inviting) this to happen. But frankly I don't know and now it's too late to get any further with this.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
However, I do have a resizer control on the form that resize controls proportionally on form resize and I suspect that it at least play a part in this.
That's a very probable cause.
The SStab, and also the SSTaEx hides the controls that are not in the current tab by positioning them .Left - 75000
These resize controls usually changes sizes and position of controls to fit a new window size.
The control may be ready to handle SStab, but not SSTabEx because it doesn't know about it.
On the other hand (probably unrelated), I suggest if possible to use the SStabEx compiled into an OCX to avoid problems.
If there are bugs, I can investigate and work to fix them, but I need first to be able to reporduce the situation.
Last edited by Eduardo-; Aug 30th, 2020 at 01:49 AM.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
It was too late yesterday to think of that simple thing, and actually was the first thing popping my mind as I woke up today - remove the resizer and we have the answer and yes I can confirm that is the problem. Removing it, all is fine, putting it back and the problem is back. Strange though how it first worked for several runs, then problem first time. I remove and recreate the SSTabEx on the form and it works again for some time while I work, make changes, even added another tab and its container, still ran fine and then suddenly...
Anyhow, the good thing here is that the resizer is actually my own control I created a few years ago by merging together some work/ideas from PSC and added my own thoughts to it to get what I wanted/needed. I just don't have it setup to run in IDE mode currently as I finished my testing and have just used the compiled OCX. I guess I will have to bring it back in to find out what's happening and adjust it.
I'm glad the problem as such wasn't in SSTabEx though, although it kind of was with the way it hides the tab containers. Didn't realize that was the case as I haven't looked closer at the SSTabEx code, but obviously it trips up my resizer. Just another challenge to face and thanks for your fast reply.
BTW I do SStabEx compiled into an OCX, in fact it lives in the OCX together with other of my own or modified controls for the sole use of my own programs.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
In the last version the shift to the left to hide controls is no more fixed in -75000, now to handle very high DPI settings (above 300 DPI) it is dynamic, I mean, it changes with the DPI setting.
This is transparent for normal operations, but if you want to know the actual Left of the controls you can no more just add 75000 twips.
If you want to know this value, it is now not exposed in the current version but you can add the property in the SSTabEx code:
Code:
Public Property Get LeftShiftToHide() As Long
LeftShiftToHide = mLeftShiftToHide
End Property
Or, I could add a couple of methods to set and retrieve the Left of any contained control, regardless it is visible or not.
If you or anyone else need that, I'll do it.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Ok, this is the new code, I'll add it in the next update:
Code:
Public Property Get LeftShiftToHide() As Long
LeftShiftToHide = mLeftShiftToHide
End Property
Public Property Let ContainedControlLeft(ByVal ControlName As String, Left As Single)
Dim iCtl As Control
Dim iFound As Boolean
ControlName = LCase$(ControlName)
For Each iCtl In UserControl.ContainedControls
If LCase$(iCtl.Name) = ControlName Then
iFound = True
Exit For
End If
Next
If Not iFound Then
RaiseError 1501, , "Control not found."
Else
If iCtl.Left < -mLeftThresholdHided Then
iCtl.Left = Left - mLeftShiftToHide
Else
iCtl.Left = Left
End If
End If
End Property
Public Property Get ContainedControlLeft(ByVal ControlName As String) As Single
Dim iCtl As Control
Dim iFound As Boolean
ControlName = LCase$(ControlName)
For Each iCtl In UserControl.ContainedControls
If LCase$(iCtl.Name) = ControlName Then
iFound = True
Exit For
End If
Next
If Not iFound Then
RaiseError 1501, , "Control not found."
Else
If iCtl.Left < -mLeftThresholdHided Then
ContainedControlLeft = iCtl.Left + mLeftShiftToHide
Else
ContainedControlLeft = iCtl.Left
End If
End If
End Property
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Thanks Eduardo,
I have now setup my project as a group with both my resizer control and the SSTabEx control to have a closer look at what's happening. It's 2-3 years since I completed my resizer though and haven't looked at it since, so will probably take me some time to refresh my memory of what the code actually is doing and where... I'll be back when I know more.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Eduardo, I just realized that I am using the 28 April release and that you actually done 2 updates since, so I will start out with doing that update and see what the result is. However, looking at the code changes in my file comparison app I notice that you are changing many numeric variables from type Long to Integer, may I ask why? I already noticed that you often use the Integer type where I normally would go for Long as well Integer is 16-bit and kind of Windows 3.x
The only (legit) reason I can see is if you want it to be a 100% drop-in replacement of SSTab, although I would probably still keep the use of Integer type to a minimum, limited to the public interfaces and internally converting input/output between Long and Integer. Personally, I don't find the idea of 100% drop-in compatibility that useful and would gladly make smaller changes to some of my code (like variable types) to get a much better end result - after all there is usually a reason why you want to change from something old to something new, right. Anyway, just some thoughts.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
looking at the code changes in my file comparison app I notice that you are changing many numeric variables from type Long to Integer, may I ask why?
I changed the API declaration for ColorRGBToHLS and ColorHLSToRGB APIs from Long to Integer, because although it worked, it were wrong. I changed them to avoid any possible issues that could araise from these wrong declarations.
That led me to also change variables declarations that iteract with those APIs.
Originally Posted by 7edm
I already noticed that you often use the Integer type where I normally would go for Long as well Integer is 16-bit and kind of Windows 3.x
The only (legit) reason I can see is if you want it to be a 100% drop-in replacement of SSTab, although I would probably still keep the use of Integer type to a minimum, limited to the public interfaces and internally converting input/output between Long and Integer.
Yes, that's the reason, full backward compatibility with the SSTab.
Internal use sometimes is to avoid performing so many conversions.
Originally Posted by 7edm
Personally, I don't find the idea of 100% drop-in compatibility that useful and would gladly make smaller changes to some of my code (like variable types)
I prefer to have drop in compatibility, and the speed gain that you propose IMO would be negligible.
Originally Posted by 7edm
to get a much better end result
I don't think that changing Integer to Long could have any noticiable impact, just some few nanoseconds on operations that are not so frequent to have any impact IMO.
You are free to make any changes that you want, but I don't think it worth. Unless you care that for example, when the user clicks a tab, it responds let's say 10 nanoseconds faster.
It would be good to make a test sample, one with Longs and other with Integers, and to measure how much faster it performs. Still, there is any intensive operation in the SSTabEx to care (or measure).
Last edited by Eduardo-; Aug 31st, 2020 at 05:12 PM.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Eduardo,
you might be right of the negligent speed advantage with Integer vs Long, although for me it's also about coding style and convention, same goes with the use of GoSub and GoTo (except for in error handlers with the latter), but peace, I'm not gonna spend time here on such issues, nor do I intend to change anything in your code as long as I don't have a deeper understanding of what it does across the project. I was merely curious to know more about your thinking and I think it's a blessing that you have taken up and realized this project. Great work!
Now to real issues. I upgraded your control to use the latest code and run into a problem, and this time my resizer control isn't involved, meaning, it's in the toolbox but not seated on the form. What happens is that when ever I click on any of the tabs, the first tab (index=0) is always selected. Like if on Form_Load I assign SSTabEx.TabSel = 0, clicking any of the other tabs has no effect, it's "locked/fixed" on tab0. However, if I assign SSTabEx.TabSel = 1 that tab is initially shown, but as soon as I click on any tab, 2, or 0, tab0 is selected and then it's not able to change to any of the other tabs.
I tried to debug what happens after having set a break in SSTabEx the project simply didn't want to run, same if I start with F8 the first thing to open is SSTabEx.UserControl.WriteProperties() event and then it dies on the first line of code. So I really don't know more at this stage, and I am sorry if I bring you worries.
Anyway, I went back to the old version and all works fine again, except for the interaction with my resizer control. So I will first focus on figure that out, probably by setting up a smaller test project to cut down on the potential of 3rd factors interacting.
Oh btw, I did one change. I saw you run the SSTabEx project with the "Single-Threaded" threading model, and I have changed that to "Apartment-Threaded" as I think that's the VB default and what all other of my controls use. But just out of curiosity, is there any special reason you choose to run it single-threaded?
Last edited by 7edm; Sep 1st, 2020 at 07:35 AM.
Reason: typo
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
Oh btw, I did one change. I saw you run the SSTabEx project with the "Single-Threaded" threading model, and I have changed that to "Apartment-Threaded" as I think that's the VB default and what all other of my controls use. But just out of curiosity, is there any special reason you choose to run it single-threaded?
I really don't know how that setting changed, I don't remember I made that change on purpose. Perhaps I was testing something and I forgot it that way.
Originally Posted by 7edm
Now to real issues. I upgraded your control to use the latest code and run into a problem, and this time my resizer control isn't involved, meaning, it's in the toolbox but not seated on the form. What happens is that when ever I click on any of the tabs, the first tab (index=0) is always selected. Like if on Form_Load I assign SSTabEx.TabSel = 0, clicking any of the other tabs has no effect, it's "locked/fixed" on tab0. However, if I assign SSTabEx.TabSel = 1 that tab is initially shown, but as soon as I click on any tab, 2, or 0, tab0 is selected and then it's not able to change to any of the other tabs.
I tried to debug what happens after having set a break in SSTabEx the project simply didn't want to run, same if I start with F8 the first thing to open is SSTabEx.UserControl.WriteProperties() event and then it dies on the first line of code. So I really don't know more at this stage, and I am sorry if I bring you worries.
Anyway, I went back to the old version and all works fine again, except for the interaction with my resizer control. So I will first focus on figure that out, probably by setting up a smaller test project to cut down on the potential of 3rd factors interacting.
I have no idea because I just downloaded the project and it works for me.
Without being able to reproduce the problem I can't do or say anything.
Originally Posted by 7edm
you might be right of the negligent speed advantage with Integer vs Long, although for me it's also about coding style and convention, same goes with the use of GoSub and GoTo (except for in error handlers with the latter), but peace, I'm not gonna spend time here on such issues, nor do I intend to change anything in your code as long as I don't have a deeper understanding of what it does across the project. I was merely curious to know more about your thinking and I think it's a blessing that you have taken up and realized this project. Great work!
If you want to know my thinking, it is:
I think that some things are justified and other are extreme positions where programmers limit themselves but are not always justified (rationally).
About using always Long type intead of Integer (or other types):
It is important on time consuming processes, when they can introduce noticiable delays because they are in long running loops, or something like that.
Still, if I have to choose, I always choose Long, unless I have a reason to use other types and when I think it will have no practical impact.
About GoTo and GoSub:
I know there is a thinking out there that Goto is evil, and never to use it.
Well, you are limiting yourself. Sometimes a GoTo is the perfect option.
Try to avoid it, do not use it as something normal, but in some cases it is a solution, and the code is still easier to follow than the big mess that you would have to do, to perform the task without any GoTo.
If you want to write perfect structured rountines, then never use Exit Sub, Exit For, Exit Do, anything like that, either.
Do you see much difference between an Exit Sub and a GoTo Exit_Sub (where you can do something before exiting the process)?
Same about GoSub. Try to avoid it, but sometimes it is a solution when you need to make some repetitive task inside a procedure that uses many local variables. Otherwise you would have to make another procedure and pass all those variables, just to avoid a Gosub. And why? Because it is a extreme view. It is not rational for me to complicate things so much just to follow a rule that someone stated and other spreaded everywhere.
Still, as I said, try to avoid it, do not use it normally.
There are other rules out there.
Like the one: never, ever use DoEvents, it is evil.
Not true. It is dangerous, yes, you have to think very well what could happend in the middle. The world after DoEvent might be very different of the world before it, but if you handle the possible scenarios right, there is no problem. And it allows to do some things that otherwise would be very difficult or even impossible in VB6, that is single theaded.
Also, try to avoid it all possible, and when you put a DoEvent think very well what could have happened after it returns.
There are also some other options, like using PeekMessage that soometimes can be used intead of DoEvents, a bit less dangerous.
Never use On Error Resume Next, another one.
Do not use that indiscriminately, and set the error control again as soon as you are done (most of the times after one line), but it is a practical solution for many cases.
I think may be more like these, but I don't remember another one now.
That's my thinking.
Of course, there are also some justified:
Never use End.
Yes, that's justified I think.
But I would not say: never use End, intead: using End should be never the solution.
PS: in other words: the rules should be understood, and not to follow rules blindy because someone said it (or because you fear to be doing something wrong).
But when you don't understand some rule, then better follow it, you'lll be safer.
This is programming, you are not breaking the law, either a commandment.
Last edited by Eduardo-; Sep 1st, 2020 at 09:23 AM.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Thanks for sharing your thoughts Eduardo, appreciated. We humans are complex beings and what makes perfectly sense to some, may appear as nonsense (or something else) to others. Personally, I like to take an approach of consistency and simplicity, but of course make an exception where it makes sense (in my mind). You are technically right about GoTo, my sticking point though is that it invites to bad habits and temporary solutions (that by time tend to become permanent) that eventually tends to stack up causing complexities that is both hard to understand and to debug, when need arises. Although a relatively mild example from your code, I would never choose this solution:
Code:
Set iControls = UserControl.Parent.Controls
If iControls Is Nothing Then GoTo Exit_Function
For Each iCtl In iControls
Set iContainer_Prev = Nothing
Set iContainer = Nothing
Set iContainer = iCtl.Container
Do Until iContainer Is Nothing
If iContainer Is nContainer Then
GetContainedControlsInControlContainer.Add iCtl
End If
Set iContainer_Prev = iContainer
Set iContainer = Nothing
Set iContainer = iContainer_Prev.Container
Loop
Next
Exit_Function:
Err.Clear
but like this:
Code:
Set iControls = UserControl.Parent.Controls
If Not iControls Is Nothing Then
For Each iCtl In iControls
Set iContainer_Prev = Nothing
Set iContainer = Nothing
Set iContainer = iCtl.Container
Do Until iContainer Is Nothing
If iContainer Is nContainer Then
GetContainedControlsInControlContainer.Add iCtl
End If
Set iContainer_Prev = iContainer
Set iContainer = Nothing
Set iContainer = iContainer_Prev.Container
Loop
Next
End If
Err.Clear
Anyway, I think I have figured out what the problem is with SSTabEx vs my Resizer control, although I haven't looked in detail what exactly is taking place, just out of how you explained it above.
When proportional resizing takes place it will change the .Left value of each control, with the result that it will differ from what your control expect it to be, causing the end result to be wrong. However, my control can also do anchored resizing, which should work as long as the tabs container control is anchored to the same side as it's moved into hide. Problem though, I just found a bug that has slipped my eyes, and once that is fixed it "should" work and if not I will have to look deeper.
Any special reason to .Move the containers out of view rater than just setting its .Visible property, speed, flicker etc.?
Last edited by 7edm; Sep 1st, 2020 at 02:01 PM.
Reason: clarity
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
Any special reason to .Move the containers out of view rater than just setting its .Visible property, speed, flicker etc.?
Yes.
1) Backward compatibility with existing code that used the original SSTab (and stored properties).
2) Not to mess with the Visible property, that the programmer could have used (or want to use) to show/hide controls. I think that must have been the reason why the original developers of the SStab did that way.
When the host program changes the .Left of a control that is hidden (shifted to the left), the SSTabEx has implemented a way to place it in the right tab anyway. In case of controls that are windows and thus can be subclassed, that is done at the moment, in case of windowless controls, they are handled when the tab changes (it is not possible to know that a label changed place, perhaps only executing a lot of code on every form paint, but that doesn't seem something reasonable to do).
In sum: the SSTabEx has better handling than the SSTab regarding the host program changing control's Left. But still, not perfect.
3) A solution could have been to put the controls into a container, for example a picturebox or a frame, but it is not possible to change the container of a contained control in an UserControl from a container of the host program to one of the component program. I tried, it raises an error.
Any suggestion can be considered, now I don't have an alternative.
Note: Now I remember that I saw some tab control that said it used containers to hide the controls, but I don't remember now where it was. I think it was some old commercial control. Perhaps it worked only with windowed controls and set the parent with the SetParent API.
About your resizer program, test for the TypeName of the control's container, and when it is "SSTabEx", then use ctl.Container.ContainedControlLeft(ctl.Left) instead of ctl.Left. (Add the code, it is on post #47, but you need to be using the latest version)
Did you have code in the resizer to handle the SSTab? How?
About the routine with GoTo Exit_Function that you quoted, it surely won't win any beauty contest, but I don't see a functional problem with it.
If I had made it from the start, surely I would had made it as you suggested, but when I had the control already written and working, I realized that I was leaving the Err object with some errors set in some parts. It wouldn't be a problem most of the times, but I thought better not to leave them because when the control is used in source code, the host program shares the same Err object, and if the host program is checking for errors, it could lead to a false positive.
Then I looked for the places where Exit Sub/Function's where inside an error handling and quicky changed them to GoTo Exit_Sub/Function, added that label, and cleared the Err object at the end before exiting. Without having to resort to adding flags and more code.
That specific case that you quoted could have been resolved without adding a flag, but I replaced all the same way without studing each one in detail.
About picking up bad habits, yes, if you can't control yourself or you are a beginner then you better abide by the rules and never break any.
I know it is not only about beginners, but I don't want to start a war (many here will agree with your view).
They are all good rules, I encourage to follow them... the 99% of the times.
When I code, I am very focused on what I'm doing and don't want to add the burden of "someone won't like it". I'm not saying I don't care or I don't consider that, but I don't like to spend much time on these things.
Anyway I read objections, and I can change things when someone express reasons that I see valid.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
I understand, as SSTabEx is labeled as a replacement, that you like to give priority to keeping it 100% backwards compatible. I have no objections to that. Still, SStab is an old control (one may even argue an unmodern one) and breaking some of that backward compatibility, still building on the base, may not be a totally bad or even unwelcome idea. Not trying to urge you doing this though, as I am just interested in getting it to work with my resizer or resizing in general as I think that probably presents a problem for it. So thinking of how to best accomplish this, and maybe a fork would be a way to go. For the moment only analyzing the situation though, but I need it to work with resizing.
Originally Posted by Eduardo-
3) A solution could have been to put the controls into a container, for example a picturebox or a frame, but it is not possible to change the container of a contained control in an UserControl from a container of the host program to one of the component program. I tried, it raises an error.
Any suggestion can be considered, now I don't have an alternative.
Things that have crossed my mind are that maybe a better solution would be if the control handled the resizing of it's containers itself, and even provided the container for each tab where to site controls. Is this what you tried to do with a picturebox but it didn't work? I know that siting an UC on another UC container control presents a problem as the contained UC's Ambient.UserMode is set to 'True' causing it to behave as in run mode. A picturebox (as a control array matching tabs) shouldn't present the same problem - theoretically - while the practical implementation may present other challenges I'm not aware of at this point.
Anyway, I have now setup a test project to have a closer look on these things. I haven't made my resizer SSTabEx aware so far, as using TypeOf I think require SSTabEx to be referenced in my Resizer project, and it's really its container (a picturebox in this case) I need to deal with. It's possible I have to rethink how I structure the handling of controls in my resizer. But again, maybe the resizing (at least of the main container) would be best handled directly in SSTabEx. I have to put the brilliance of my mind to it!
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
A picturebox (as a control array matching tabs) shouldn't present the same problem - theoretically - while the practical implementation may present other challenges I'm not aware of at this point.
There is *no* other practical approach to tabbed UI, incl. SSTab/SSTabEx. You just *have* to place controls in a "tab container" which will be shown only when it's designated tab becomes current. Otherwise, relying only on SSTab's Left shenanigans, the end-user will be able to focus controls on "non-current" tabs using TAB/Shift+TAB keys which will no doubt become a non-stop stream of support calls. Ouch!
Let me reiterate -- no one writing production code will use SSTab control without container-per-tab + manual hide/show on tab click. At this point, arriving at the PictureBox control array, one has to ask themsleves how hard it is to migrate to themed TabStrip control and be welcome to the new century of OS provided bells and whistles?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by wqweto
relying only on SSTab's Left shenanigans, the end-user will be able to focus controls on "non-current" tabs using TAB/Shift+TAB keys which will no doubt become a non-stop stream of support calls. Ouch!
That was a problem in the SSTab, but in the SStabEx I already fixed that. I set the TabStop property of the hidden (shifted to the left) contained controls to False, and restore to its original setting once they are in the current tab.
Originally Posted by wqweto
Let me reiterate -- no one writing production code will use SSTab control without container-per-tab + manual hide/show on tab click. At this point, arriving at the PictureBox control array, one has to ask themsleves how hard it is to migrate to themed TabStrip control and be welcome to the new century of OS provided bells and whistles?
cheers,
</wqw>
There will be little gain, since the SStabEx is already themed.
And ther are are things to loose, since the VB6's TabStrip is not a control container.
BTW, the .Net's TabStrip is a control container, like the SStab and unlike VB6's TabStrip.
For me, being control container, is the main advantage of the SStab. Mainly to be able to have the controls ordered and easily visible at design time, I never liked the TabStrip for that reason.
If you have a large form with several tabs, it is impossible to place all the tab-containers on the form without overlapping each other. It is very cumbersome IMO.
The main dissavantage of the original SSTab was that it was not themed. It is fixed now here.
Also, the TabStrip can show the tabs stretching their widths to fill all the control width. Setting the SSTabEx with Style set to ssStyleTabStrip does that.
So, in regard to look and behavior at run time, there are little difference between the SStabEx and the TabStrip.
The only thing I didn't implement was:
The TabStrip, when all the tabs do not fit on the control's width, the TabStrip has the option to show more than one row of tabs, or to show a little arrows at the end to let the user navigate to the non visible tabs by clicking them.
I didn't implement the second option (at least for now) in the SSTabEx, so the only option is to show more than one row of tabs.
I didn't do it because I never used and maybe I don't like it. I think the user might not figure that he must click there to show more tabs.
I've implemented other things that sometimes are needed, like being able to change its background color (only works when it is not themed, of course).
To move controls from one tab to another (it can be done in a property page).
Another thing that the SStab has and the TabStrip lacks is to be able to have the tabs in other place than the top. Sometimes I use the tabs at the bottom.
So, there isn't many advantages to list of the TabStrip, could you list some?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
I understand, as SSTabEx is labeled as a replacement, that you like to give priority to keeping it 100% backwards compatible. I have no objections to that. Still, SStab is an old control (one may even argue an unmodern one) and breaking some of that backward compatibility, still building on the base, may not be a totally bad or even unwelcome idea. Not trying to urge you doing this though,
Doing exactly what are you talking about?
Originally Posted by 7edm
as I am just interested in getting it to work with my resizer or resizing in general as I think that probably presents a problem for it. So thinking of how to best accomplish this, and maybe a fork would be a way to go. For the moment only analyzing the situation though, but I need it to work with resizing.
Does your resizer already handle the SStab? How? (post code)
Originally Posted by 7edm
Things that have crossed my mind are that maybe a better solution would be if the control handled the resizing of it's containers itself, and even provided the container for each tab where to site controls.
I'm not going to do a resizer control, not inside the SSTabEx and improbably in other specific control.
I think that having these resizers, most of the times is a wrong concept.
There is no point on making a button bigger because the form was resized, at least not following the form's size, I mean: it can be a couple of steps where you take advantage of the available space to make things more readable, but that's it.
IMO when a form changes size, you need to think the logic of what to do in the available space (smaller or larger that the "normal") for each form particularly, and that would hardly be something that could be automated for every case in a control. Making everything to resize accordingly to the form's size is a wrong approach IMO (and the opinion of many others).
Originally Posted by 7edm
Is this what you tried to do with a picturebox but it didn't work? I know that siting an UC on another UC container control presents a problem as the contained UC's Ambient.UserMode is set to 'True' causing it to behave as in run mode. A picturebox (as a control array matching tabs) shouldn't present the same problem - theoretically - while the practical implementation may present other challenges I'm not aware of at this point.
No, the problem is not that.
I mean error 425 (Invalid object use).
See the attached test project.
Originally Posted by 7edm
Anyway, I have now setup a test project to have a closer look on these things. I haven't made my resizer SSTabEx aware so far, as using TypeOf I think require SSTabEx to be referenced in my Resizer project, and it's really its container (a picturebox in this case) I need to deal with. It's possible I have to rethink how I structure the handling of controls in my resizer. But again, maybe the resizing (at least of the main container) would be best handled directly in SSTabEx. I have to put the brilliance of my mind to it!
Do not use TypeOf, but TypeName (Control). With that you don't need an early-binding reference.
Originally Posted by Eduardo-
About your resizer program, test for the TypeName of the control's container, and when it is "SSTabEx", then use ctl.Container.ContainedControlLeft(ctl.Left) instead of ctl.Left. (Add the code, it is on post #47, but you need to be using the latest version)
If the resizer code is not too complex, post it.
Or, you can use this code in the host program to position the containers:
Code:
Private Sub Form_Load()
Dim c As Long
For c = 0 To picContainer.UBound
picContainer(c).Move SSTabEx1.TabBodyLeft, SSTabEx1.TabBodyTop
Next
End Sub
Private Sub SSTabEx1_Click(PreviousTab As Integer)
picContainer(SSTabEx1.TabSel).Move SSTabEx1.TabBodyLeft, SSTabEx1.TabBodyTop
End Sub
Last edited by Eduardo-; Sep 2nd, 2020 at 12:08 PM.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Updated.
2020-09-02 Added properties ContainedControlLeft and LeftShiftToHide.
2020-09-02 TabBodyLeft, TabBodyTop, TabBodyWidth, TabBodyHeight now return the value in Twips (regardless of the SStabEx's container ScaleMode), that is what the SSTabEx's contained controls use.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Eduardo,
good news, I was able to update SSTabEx to your latest version (from today) - and it works! also with my resizer control, in my test project so far only. Will test and check some bit before I switch over to apply it on my main project. The solution was actually quite simple, and already available - to use anchored resizing rather than proportional. I think this is why I have it working originally, but then it crashed and I had to remove and put back SSTabEx as well as resizer, and it was coded to use proportional resizing by default. I never thought of this and when I checked my Subversion logs I see I completed the control back in 2015 and haven't looked at the code since, just used it.
Anyway, this means I am up and running again! I will try to come back later and respond to your questions/statements above, when I have more time. Just one thing about GoTo :-) I think your changes like:
Code:
If iControls Is Nothing Then GoTo Exit_Sub
....
Exit_Sub:
Err.Clear
are redundant really, as VB automatically fires Err.Clear on any 'Exit Sub', 'Exit Function' and 'Exit Property' call.
Also, I was wondering over this, what do you like to accomplish with this code:
Code:
iTiUsr = -1
iTiUsr = UserControl.Extender.TabIndex
If iTiUsr = -1 Then Exit Sub
from what I understand, iTiUsr can never get a value of -1 here, thus what you are trying to address will never happen i.e. Exit Sub gets called.
Also, let me fill in, the shortcomings of the TabStrip control is what lead me here. The ability to site your controls inside the tab at design time is worth so much, so let me just say that the work you are doing here is of great importance!
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
Eduardo,
good news, I was able to update SSTabEx to your latest version (from today) - and it works! also with my resizer control, in my test project so far only.
It works exactly as it worked before, there is no change that could affect you (and the resizer).
Originally Posted by 7edm
Will test and check some bit before I switch over to apply it on my main project. The solution was actually quite simple, and already available - to use anchored resizing rather than proportional. I think this is why I have it working originally, but then it crashed and I had to remove and put back SSTabEx as well as resizer, and it was coded to use proportional resizing by default. I never thought of this and when I checked my Subversion logs I see I completed the control back in 2015 and haven't looked at the code since, just used it.
Anyway, this means I am up and running again!
I thought we were already clear that the problem is in your resizer and not in the SStabEx.
Originally Posted by 7edm
I will try to come back later and respond to your questions/statements above, when I have more time. Just one thing about GoTo :-) I think your changes like:
Code:
If iControls Is Nothing Then GoTo Exit_Sub
....
Exit_Sub:
Err.Clear
are redundant really, as VB automatically fires Err.Clear on any 'Exit Sub', 'Exit Function' and 'Exit Property' call.
Wrong, and easy to test:
Code:
Private Sub Form_Load()
AAA
Debug.Print Err.Number
End Sub
Private Sub AAA()
On Error Resume Next
Debug.Print 1 / 0
End Sub
When there is an On Error GoTo 0 before leaving it clears the Err object, otherwise the error is left.
Originally Posted by 7edm
Also, I was wondering over this, what do you like to accomplish with this code:
Code:
iTiUsr = -1
iTiUsr = UserControl.Extender.TabIndex
If iTiUsr = -1 Then Exit Sub
from what I understand, iTiUsr can never get a value of -1 here, thus what you are trying to address will never happen i.e. Exit Sub gets called.
If someone changes the CanGetFocus property of the UserControl, then there is not TabIndex property in the Extender.
Originally Posted by 7edm
Also, let me fill in, the shortcomings of the TabStrip control is what lead me here. The ability to site your controls inside the tab at design time is worth so much, so let me just say that the work you are doing here is of great importance!
I always used the SStab instead of the TabStrip for the same reason.
And for the ones that say that it looks old because of the 3D look, they have the option to set Style to ssStylePropertyPage and it looks like the TabStrip.
But a problem arose with the original: it does not apply Windows visual styles.
Last edited by Eduardo-; Sep 2nd, 2020 at 06:06 PM.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Hi Eduardo, it's me again.
While I was able to solve my original problem discussed above, I have now run into another one.
I have a UniSuitePro Listbox on the first tab as part of a controlarray, which gets loaded with records during start of the form. In Code I then set .ListIndex = 0 to triggers the ListIndexChange event that runs this code:
Code:
Private Sub lstChartsOnFile_ListIndexChange(Index As Integer)
Dim bHasSelection As Boolean
With lstChartsOnFile(Index)
bHasSelection = CBool(.ListIndex > -1)
If Index = 0 Then
If bHasSelection Then
mLastChartID = .ItemItemData(.ListIndex)
Set mEditChart = GetChartByIdFromDb(mLastChartID)
End If
tabCM.TabEnabled(1) = bHasSelection
cmdDelete.Enabled = bHasSelection
cmdDelete2.Enabled = bHasSelection 'button outside of SSTabEx for referense
cmdLoad(0).Enabled = bHasSelection
cmdLoad(1).Enabled = bHasSelection
End If
End With
End Sub
The code above is triggered as should at startup and works perfectly fine;
The first list item is select and bHasSelection is set to True,
the mLastChartID variable is asigned a Long from the list items itemdata property
and is the used to fetch a data set from my Sqllite database, which is assigned to a class.
So far all well, and also next operations works as it should in code, the .Enabled property is set to the value in bHasSelection (which is True, I debug.print checked this)
I also debug.print checked that the properties really had a value of True, so so far all is as it should, but...
When the form shows, the List item is not really selected, but is "highlighted" with a light grey stripe, not the blue highlighting it get when clicked on, and furthermore, the buttons are shown in its .Enabled = False state.
To check if this was a SSTabEx issue or not, I placed another button on the form, outside of SSTabEx as a reference (cmdDelete2 in the code) and it gets enabled as it should, and as the other buttons should have been as well.
So something happens there that shouldn't, and my intuition tells me that it might have to do with subclassing, either in UniSuitePro listbox or in SSTabEx, or possibly in both.
If I click on any row in the listbox, the item gets selected as it should (blue highlighting) and the buttons are all set to correct .Enabled state.
Any idea if there is anything that can be done about this? I still haven't had time to look closer on the SSTabEx code as I been too busy with getting my own code working.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
I will try to do that later when I have a bit more time. The issue is not fatal as all works once the user click an item in the list. It just doesn't get selected from the preset value assigned by code on load, or refill of list, as intended. So I can live with it for now while I complete other things.
M$ vs. VB6 = The biggest betrayal and strategic mistake of the century!?
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Originally Posted by 7edm
I will try to do that later when I have a bit more time. The issue is not fatal as all works once the user click an item in the list. It just doesn't get selected from the preset value assigned by code on load, or refill of list, as intended. So I can live with it for now while I complete other things.
I don't figure something of the SStabEx control that could cause that anyway.
Please, for any future possible bug reports, it must be accompanied by a test project.
Last edited by Eduardo-; Sep 30th, 2020 at 06:36 PM.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Updated!
Some bugs fixed:
2021-01-17 Fixed bug in WM_WINDOWPOSCHANGING message for non-integer DPI settings (when windowed controls' lefts in hidden tabs are set at run-time).
2021-01-16 Fixed bug in ContainedControlLeft property, not it can handle controls from control arrays.
2021-01-16 Fixed bug in default TabSelBackColor and TabSelForeColor when upgrading from a previous version of SSTabEx that didn't have these properties, that happens when the values of TabBackColor/ForeColor properties are not set to their default settings.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Hi Eduardo,
As part of updating my VB6 application to support Unicode, I implemented your SSTabEx work.
In short: smooth, no problems, so *GREAT* stuff! (And I have only done the basic conversion at this point. The ability to change the order of the tabs, or moving all controls from one tab to another would have saved me quite some time in the past...) Thank you very much to share it with the world!!!
One thing I noticed though:
My app applies a translation to all controls in a form during the load event. This works perfectly fine with a SSTabEx-control on a form, but I noticed that when a tab contains another SSTabEx-control, the initial display doesn't display the newly assigned TabCaptions. Moving the mouse over one of the tabs, immediately refreshes the screen, and shows the proper captions.
Note: this is running the application from the IDE. I haven't been able yet to check if that's also the case with a final compiled exe.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Hello, thank you for your comments.
I'm not able to reproduce the issue. Please check the test project that is attached.
If you can recreate the situation, and we see that it is indeed a bug, I'll check to fix it.
If not, or you realize that it might be some other third party control or something interfering with the paint messages, you could try SStabEx.Refresh and see if that helps.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Hi Eduardo,
Thanks for the quick feedback.
It works fine with the test you sent. I tried various alternative scenarios, but couldn't reproduce the problem with your test-app, but the problem is consistent with my app.
The only difference is that my app populates some 50 textboxes, comboboxes, and a few pictureboxes after the controls' captions are given their translation. Not sure how that interferes with the painting, that's way beyond my knowledge...
Anyway, the good news is that adding a Refresh in the form Activate event solves the problem.
Re: (VB6) SSTabEx: SSTab replacement. Themed and with new features
Hello @ Eduardo,
Great work you gave the world and i am happy about it so much.
However, i have lost 2 days with issues encountered when i added the SSTAB to my project. When i used the SSTAB as a component, it worked fine and i can compile easily. However, when my users downloaded my software, it keeps complaining the Active X control is not registered. Registering the TabExCtl.ocx on each user system is too cumbersome. Besides i tried it, it registered successfully but i still got an error when the form which uses the SSTAB is launched in the software.
So to avoid all that, i decided to add the User Control directly in the project and i added all other files, property files, BAS, Class Modules but since 2 days now, i keep getting the "Out of Memory" Compile error when i compile my EXE. If i remove the SSTAB forms and compile again, i compile successfully, but if i add the SSTAB and compile, its been giving me "Out of Memory" error.
Meanwhile i can run the program successfully and it works fine. The SSTAB works very fine on the forms when i run program, but i cannot compile for 2 days now and it has driven me nuts.
Please Help.