At the other extreme, I have a highly complex form used for multiple purposes with around 500 controls.
It has around 20-25 groups of tagged controls which are made hidden/visible; locked/unlocked; enabled/disabled; highlighted or not ... all using tags.
If Ctrl.Form.Hwnd = oForm.Hwnd Then
blnIsA_Sub = True
End If
...although it looks like Hwnd is working, is use "Is", like...
Code:
If Ctrl.Form Is oForm Then
blnIsA_Sub = True
End If
...which, of course, can be further reduced to...
Code:
blnIsA_Sub = Ctrl.Form Is oForm
Is compares instances, not types, so it is only true if the two operands point to the same instance of the object.
I do not get an error running your code from the load event of a subform.
Also, given how much effort this code goes thru to determine if the object is a subform, therefore I would rather do this test, event though it means intentionally raising an error...
Code:
Property Get MeIsASubform As Boolean
On Error Resume Next
MeIsASubform = Left(Typename(Me.Parent), 4) = "Form"
End Property
...and it also always makes more sense to me for an object to expose it's own properties that to hand the object over to an external routine to run a test on it from the outside. For encapsulation, I want that test to run INSIDE the object, and for the result to be exposed as a property or method.
Does this address the topic you raise, or have I missed the point?
Mark
Colin, I was going to say "no, I won't do it," because what starts to cloud the issue is the infrastructure or maybe the "meta-structure" required to demonstrate the issue.
At its simplest, here's what we are talking about: We might need to selectively enable or disable four buttons until all data is entered in a form, say. At that level, I can
.Tag those four buttons and run a big loop thru all controls, test for .Tag, and set the state, or I can
expose a four member array I pre-populated with said buttons, enumerate that array, and set the state.
Two simple choices for how to make that work.
But looking at your form, there are groups, and mixed groups, and labels that belong to other controls, and so on, and so suddenly there is the bigger problem, like a meta-problem, of managing all the different groups that get hidden while the other group gets disabled. And once all that overhead is taken into account, will the simple two point description, above, be significantly improved? Probably not. You still either gonna .Tag them, or put 'em in an array.
But as to your last post, if I wrote a demo like the one you did, I would write a class, maybe called cControlGroup, that has properties like .Visible and .Enabled. Also, there would be a .Load method that takes a ParamArray which would be the list of controls, untagged, that belong to that group. Maybe this goes to what you are talking about with your 500 control form.
Imagine a cControlGroup class that could be used like this...
Code:
Private m_ccgA as cControlGroup
Private m_ccgB as cControlGroup
Property Get GroupA As cControlGroup
If m_ccgA Is Nothing then
Set m_ccgA = New cControlGroup
m_ccgA.Load [COLOR="Blue"]Me.Text0, Me.Text2, Me.Text[/COLOR]
End If
Set GroupA = m_ccgA
End Property
Property Get GroupB As cControlGroup
If m_ccgB Is Nothing then
Set m_ccgB = New cControlGroup
m_ccgB.Load [COLOR="blue"]Me.cmd1, Me.cmd2, Me.cmd3[/COLOR]
End If
Set GroupB = m_ccgB
End Property
Private Sub Text0_AfterUpdate()
Me.GroupB.Enabled = Me.GroupA.HasNoNullValue
End Sub
So if we write a class that manages a set of controls, and that set of controls is defined by simply passing them into that class in the constructor, that makes a lot of sense to me. See what's going on in that code? Constructors, essentially, for classes that manage groups of controls, and then the form's code just leverages those classes.
That's how I'd approach that problem. But I'm not going to because I don't have time right now, but I would comment on it, as I'm doing, like this, in this post...
Yes that makes sense ... I think but I'd need to try it to be sure I understand properly.
Unfortunately, I don't have the time right now either!
I don't blame you in the least for not spending the time on the challenge
If you had asked me to do the same in reverse, I would probably have declined as well!
Just to give you an idea of the multi-purpose form I mentioned, attached are 4 randomly selected views showing a few of its many different uses.
Also attached is the same form in design view though most of the controls are hidden under other controls ....
Its taken many years to reach this level of complexity & it works well.
The main advantage is being able to reuse the same code repeatedly
BUT whether I'd do it again like this if I started again now is another matter...
Apologies to the OP - this thread has moved away from the original question onto a much wider discussion
In fact following Tony's reply, possibly the most fundamental question of all
I remember using Douglas Adams famous answer to
"what's the meaning of life, the universe and everything?"
Anyway, as it was obscure, I promptly forgot about the code until about a year later a client demanded to know why the app gave had a message box saying 42 when he performed a particular action ....
Needless to say they'd never heard of Douglas Adams so it was a bit hard to explain
Anyway, the real answer is that I not only would, but do, continue to create multi-purpose forms.
However, none so far have reached the same degree of complexity as the one I described
Hi Mark,
I have Incorporated your suggested update to the code thank you!
You said it worked for you, which puzzled me because it threw an error when I used it. I wondered what could be the difference between our two set-ups.
It occurred to me you would probably try it on a main form with a single subform, I’m using a main form with two subforms. I did an experiment with a main form and single subform and sure enough it worked!
That hints at the cause of the error. The code is checking all of the subform/subreport controls. It must be finding one which has yet to load. I'm readdressing the code to see if I can get it to only look at itself so to speak. If/when I get it working without error, I will repost it!