Link to home
Start Free TrialLog in
Avatar of VK
VKFlag for Germany

asked on

Smart function which provides me all controls that are contained in a Control Container

Hello Experts !

I need a smart function like below:

Private Function GetAllContainedControls(CtrlContainer As Control) As Collection
    Dim colResult As Collection
    '.....
    'If ... Then
        'Set colResult = New Collection
        '....
        'Call colResult.Add(..., ...)
    'end if
    '...
    Set GetAllContainedControls = colResult
End Function
ASKER CERTIFIED SOLUTION
Avatar of bobbit31
bobbit31
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of gencross
gencross

You beat me bobbit :)
Avatar of Nitin Sontakke
I am sorry to bother you all, but could you please let me know the utility of such a function. I mean when this information is available to you at runtime anyway, why would one want to put it in yet another collection?

Avatar of VK

ASKER

Hello Experts !

To eliminate the obscurities:

I need that function for example to disable all "Sub-Controls" of a control. When i have a frame Frame1 and i set Frame1.Enabled=False then the "Sub-Controls" are disabled too but are not greyed if i don't disable them too.

Regards

V.K.
Avatar of VK

ASKER

Hello bobbit31 !

Thanks for the reply.
I tried your function.
Not every control has an container.
It works if i add an "on error resume next"-statement.
If i use that statement the function isn't smart anymore.

Nevertheless i will gave you the points, but i hope you can tell me a version without error handling.

V.K.
I thought that is what you were trying to do:)  

What you may want to is not put the controls in a collection.  Instead use the code to go ahead and disable the control once you see that it is part of the container.  This way you do not use more memory and eliminate a step...

Private Function DisableAllContainedControls(CtrlContainer As Control) As Collection
  Dim cntrl As Control

  For Each cntrl In Me.Controls
     If cntrl.Container.Name = CtrlContainer.Name Then
         cntrl.Enabled = False
     End If
  Next

End Function
have you tried my code yet?
> Not every control has an container.

can you give an example?  If it's on a form, then the form is the container unless it's in another container.
Now, that makes some sense to me!

Here is code to achieve if, unfortunately, gencross has already put similiar code above, anyway. But now that i have written it might as well paste it.

Points to gencross, please!

Private Sub Command1_Click()
    Dim objCon As Control
    Frame1.Enabled = Not Frame1.Enabled
    For Each objCon In Me.Controls
        If objCon.Container.Name = Frame1.Name Then
            objCon.Enabled = Frame1.Enabled
        End If
    Next
End Sub
Avatar of VK

ASKER

Hello bobbit31 !

I have already tested the your function.
If cntrl is an commondialog-control for example then it hasn't a container and i get error 438.

V.K.
Avatar of VK

ASKER

To all who replied to my question !

OK, now i got 3 suggestions. And they are all similar.
The one who tells me a way without error handling will get the points. If nobody can find a "straight" way doing that bobbit31 will get the points because he was first.

regards

v.k.
Here is your original call, not my modified one

You can add a TypeOf for each control without a container.


Private Function GetAllContainedControls(CtrlContainer As Control) As Collection
  Dim colResult As New Collection
  Dim cntrl As Control

  For Each cntrl In Me.Controls
    If Not TypeOf cntrl Is CommonDialog Then
        If cntrl.Container.Name = CtrlContainer.Name Then
            colResult.Add cntrl
            MsgBox cntrl.Name
        End If
    End If
  Next

  Set GetAllContainedControls = colResult
 
End Function
Sorry, gencross, a minor improvement over your code. Not tested by me.

No points to me, please!

Private Function GetAllContainedControls(CtrlContainer As Control) As Collection
Dim colResult As New Collection
Dim cntrl As Control

For Each cntrl In Me.Controls
    Select Case True
        Case TypeOf cntrl Is CommonDialog
'       Add case with any other controls you may find have not container property...
        Case Else
            If cntrl.Container.Name = CtrlContainer.Name Then
               colResult.Add cntrl
               MsgBox cntrl.Name
            End If
   End If
Next

and of course, End Case, before, Next.
Avatar of VK

ASKER

Hello  gencross.

Ok, we know now that a CommonDialog-Contol has no Container Member. But:

1. Do you know all the types of controls who have no container member. I think not because of usercontrols or third party controls or whatever.

2. This function should work for every form regardless which controls containing.

I found out that the Commondialog-Contol for example has a parent property. But if so when to use .container and when to use .parent without getting an error ?

V.K.
NitanSontakke,

I tried quickly to get the select to work, but I think I messed the syntax up (I was in a hurry).  Yours works great:)

Using a select case is the way to go.  Here is the call that disables the controls with the modified code if your interested...

Private Function DisableAllContainedControls(CtrlContainer As Control) As Collection
 Dim cntrl As Control

 For Each cntrl In Me.Controls
    Select Case True
        Case TypeOf cntrl Is CommonDialog
        Case Else
   
           If cntrl.Container.Name = CtrlContainer.Name Then
               cntrl.Enabled = False
           End If
    end select
 Next

End Function
VK,

I personally, don't see a way out, but to have 'On error resume next' and then check explicitely for the error 'Object doesnot support this property' or whatever it is.

Unfortunately, VB doesn't, to the best of my current knowledge, allow you to query the properties before accessing them. Something which is now available in .NET with Reflection classes.

What do you think?
i'd have to agree w/ nitinsontakke that you just catch the specific error and ignore it.
ditto.  It was fun trying though:)
Points to bobbit
Avatar of VK

ASKER

OK, thank to all of you :-).
Points to bobbit !!

V.K.
I am not here for points anyway. So fine with me. Mine was the most benign comment..."I am sorry to bother you all.."
i knew i could get it w/ api... here ya go

Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Const GW_CHILD = 5
Private Const GW_HWNDNEXT = 2

Dim l As Long
Dim s As String * 255

Private Sub Command1_Click()
Dim i As Integer
Dim colControls As Collection

Set colControls = GetAllContainedControls(Frame1)

For i = 1 To colControls.Count
  MsgBox colControls(i).Name
Next

End Sub


Private Function GetAllContainedControls(CtrlContainer As Control) As Collection
  Dim colResult As New Collection
  Dim cntrl As Control

  l = GetWindow(CtrlContainer.hwnd, GW_CHILD)
  If l <> 0 Then
    GetWindowText l, s, 255
    colResult.Add (Me.Controls(Left$(s, InStr(s, Chr(0)) - 1)))
    Do
    l = GetWindow(l, GW_HWNDNEXT)
    If l <> 0 Then
        GetWindowText l, s, 255
        colResult.Add (Me.Controls(Left$(s, InStr(s, Chr(0)) - 1)))
    End If
    Loop While l <> 0
  End If

  Set GetAllContainedControls = colResult
End Function
Avatar of VK

ASKER

Hi NitinSontakke !

You comment was the best (but not the entire solution).
Bobbit31's solution was the first solution (without error handling). I decided to give the points to Bobbit31 becaus i didn't need help in writing an error handler. The key senmtence is "cntrl.Container.Name = CtrlContainer.Name" and that he wrote first. Sorry.

Regards

V.K.
Good code bobbit.  Works great!
thanks! i just hope VK comes back to this question and see's it ;)
Avatar of VK

ASKER

Hello bobbit31 !

Nice approach !! Now you have unclearly deseved the points.
The function (i tested it meanwhile) works too, but i get an error 738 in the configuration below:

Picture1 containing a ListView1.

Also: Windowless controls aren't detected. Usercontrols raise error 738.

Nevertheless, good work !!

V.K.