Solved

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

Posted on 2002-06-20
28
139 Views
Last Modified: 2010-05-02
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
Comment
Question by:VK
  • 8
  • 7
  • 7
  • +1
28 Comments
 
LVL 18

Accepted Solution

by:
bobbit31 earned 50 total points
Comment Utility
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
 
LVL 4

Expert Comment

by:gencross
Comment Utility
You beat me bobbit :)
0
 
LVL 18

Expert Comment

by:bobbit31
Comment Utility
;)
0
 
LVL 6

Expert Comment

by:Nitin Sontakke
Comment Utility
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
 
LVL 6

Author Comment

by:VK
Comment Utility
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
 
LVL 6

Author Comment

by:VK
Comment Utility
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
 
LVL 4

Expert Comment

by:gencross
Comment Utility
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
 
LVL 18

Expert Comment

by:bobbit31
Comment Utility
have you tried my code yet?
0
 
LVL 18

Expert Comment

by:bobbit31
Comment Utility
> 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
 
LVL 6

Expert Comment

by:Nitin Sontakke
Comment Utility
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
 
LVL 6

Author Comment

by:VK
Comment Utility
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
 
LVL 6

Author Comment

by:VK
Comment Utility
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
 
LVL 4

Expert Comment

by:gencross
Comment Utility
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
 
LVL 6

Expert Comment

by:Nitin Sontakke
Comment Utility
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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 6

Expert Comment

by:Nitin Sontakke
Comment Utility
and of course, End Case, before, Next.
0
 
LVL 6

Author Comment

by:VK
Comment Utility
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
 
LVL 4

Expert Comment

by:gencross
Comment Utility
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
 
LVL 6

Expert Comment

by:Nitin Sontakke
Comment Utility
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
 
LVL 18

Expert Comment

by:bobbit31
Comment Utility
i'd have to agree w/ nitinsontakke that you just catch the specific error and ignore it.
0
 
LVL 4

Expert Comment

by:gencross
Comment Utility
ditto.  It was fun trying though:)
0
 
LVL 4

Expert Comment

by:gencross
Comment Utility
Points to bobbit
0
 
LVL 6

Author Comment

by:VK
Comment Utility
OK, thank to all of you :-).
Points to bobbit !!

V.K.
0
 
LVL 6

Expert Comment

by:Nitin Sontakke
Comment Utility
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
 
LVL 18

Expert Comment

by:bobbit31
Comment Utility
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
 
LVL 6

Author Comment

by:VK
Comment Utility
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
 
LVL 4

Expert Comment

by:gencross
Comment Utility
Good code bobbit.  Works great!
0
 
LVL 18

Expert Comment

by:bobbit31
Comment Utility
thanks! i just hope VK comes back to this question and see's it ;)
0
 
LVL 6

Author Comment

by:VK
Comment Utility
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

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now