Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 151
  • Last Modified:

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
0
VK
Asked:
VK
  • 8
  • 7
  • 7
  • +1
1 Solution
 
bobbit31Commented:
how bout:

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

   For Each cntrl In Me.Controls
      If cntrl.Container.Name = CtrlContainer.Name Then
          colResult.Add cntrl
      End If
   Next

   Set GetAllContainedControls = colResult
End Function
0
 
gencrossCommented:
You beat me bobbit :)
0
 
bobbit31Commented:
;)
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
Nitin SontakkeDeveloperCommented:
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?

0
 
VKAuthor Commented:
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.
0
 
VKAuthor Commented:
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.
0
 
gencrossCommented:
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
0
 
bobbit31Commented:
have you tried my code yet?
0
 
bobbit31Commented:
> 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.
0
 
Nitin SontakkeDeveloperCommented:
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
0
 
VKAuthor Commented:
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.
0
 
VKAuthor Commented:
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.
0
 
gencrossCommented:
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
0
 
Nitin SontakkeDeveloperCommented:
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

0
 
Nitin SontakkeDeveloperCommented:
and of course, End Case, before, Next.
0
 
VKAuthor Commented:
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.
0
 
gencrossCommented:
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
0
 
Nitin SontakkeDeveloperCommented:
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?
0
 
bobbit31Commented:
i'd have to agree w/ nitinsontakke that you just catch the specific error and ignore it.
0
 
gencrossCommented:
ditto.  It was fun trying though:)
0
 
gencrossCommented:
Points to bobbit
0
 
VKAuthor Commented:
OK, thank to all of you :-).
Points to bobbit !!

V.K.
0
 
Nitin SontakkeDeveloperCommented:
I am not here for points anyway. So fine with me. Mine was the most benign comment..."I am sorry to bother you all.."
0
 
bobbit31Commented:
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
0
 
VKAuthor Commented:
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.
0
 
gencrossCommented:
Good code bobbit.  Works great!
0
 
bobbit31Commented:
thanks! i just hope VK comes back to this question and see's it ;)
0
 
VKAuthor Commented:
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.

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 8
  • 7
  • 7
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now