Home All Groups Group Topic Archive Search About

VB6 : Attach Event Handlers to Dynamically Generated Controls

Author
20 Sep 2005 12:09 PM
Yep
Hi,

On our current project we would like to implement a flexible design,
based on form controls generation in regards of data structures
retrieved from a database.

For instance, if we have two fields in a table (say employee and date),
we would like our program to automatically populate a form with two
fields (employee and date).

We've been successful so far with this approach, but we've encountered
a problem while trying to bind handlers for events of these generated
controls; when the number of controls is known, using a WithEvents
declaration works fine, but in our case we don't know the number of
controls (it's dynamic), hence we cannot make the appropriate
declaration (WithEvents doesn't work with arrays, or the like).

We've looked the archives for VB6 reflection, or for an Excel-like
OnAction event - without success. However we've come across an
interesting thread located at

<URL:http://groups.google.fr/group/microsoft.public.vb.general.discussion/browse_frm/thread/406d8a574bec6e84/dbf90a95081f2e20>

....with a post by Mr. Jeff Johnson who, while stating that the problem
cannot be solved directly, suggests that there are alternate ways which
could be used, without unfortunately discussing them much.

We'd be grateful for any hint/example which could help us into solving
this issue (or advice on better ways to achieve our goal).

Thanks in advance.


Regards,
Yep.

Author
20 Sep 2005 1:02 PM
Martin
Make a wrapper for a Textboxcontrol:
-------
Private WithEvents moTextbox As TextBox
Private moForm As Form

Public Sub Create(ByVal voTextbox As TextBox, voForm As Form)
   Set moTextbox = voTextbox
   Set moForm = voForm
End Sub

Private Sub moTextbox_Click()
   Call moForm.DoSomeCommonEvent
End Sub
--------

Add for each dynamic created control the wrapper to a collection to hold a
reference to the wrapper:
set oWrapper = new Wrapper
oWrapper.Create(oTextbox, me)
call oSomeCollection.Add(oWrapper)

ML



Show quoteHide quote
"Yep" <y-e.pe***@em-lyon.com> schreef in bericht
news:1127218162.117587.275570@g49g2000cwa.googlegroups.com...
> Hi,
>
> On our current project we would like to implement a flexible design,
> based on form controls generation in regards of data structures
> retrieved from a database.
>
> For instance, if we have two fields in a table (say employee and date),
> we would like our program to automatically populate a form with two
> fields (employee and date).
>
> We've been successful so far with this approach, but we've encountered
> a problem while trying to bind handlers for events of these generated
> controls; when the number of controls is known, using a WithEvents
> declaration works fine, but in our case we don't know the number of
> controls (it's dynamic), hence we cannot make the appropriate
> declaration (WithEvents doesn't work with arrays, or the like).
>
> We've looked the archives for VB6 reflection, or for an Excel-like
> OnAction event - without success. However we've come across an
> interesting thread located at
>
>
<URL:http://groups.google.fr/group/microsoft.public.vb.general.discussion/br
owse_frm/thread/406d8a574bec6e84/dbf90a95081f2e20>
Show quoteHide quote
>
> ...with a post by Mr. Jeff Johnson who, while stating that the problem
> cannot be solved directly, suggests that there are alternate ways which
> could be used, without unfortunately discussing them much.
>
> We'd be grateful for any hint/example which could help us into solving
> this issue (or advice on better ways to achieve our goal).
>
> Thanks in advance.
>
>
> Regards,
> Yep.
>
Author
20 Sep 2005 1:13 PM
Larry Lard
Yep wrote:
Show quoteHide quote
> Hi,
>
> On our current project we would like to implement a flexible design,
> based on form controls generation in regards of data structures
> retrieved from a database.
>
> For instance, if we have two fields in a table (say employee and date),
> we would like our program to automatically populate a form with two
> fields (employee and date).
>
> We've been successful so far with this approach, but we've encountered
> a problem while trying to bind handlers for events of these generated
> controls; when the number of controls is known, using a WithEvents
> declaration works fine, but in our case we don't know the number of
> controls (it's dynamic), hence we cannot make the appropriate
> declaration (WithEvents doesn't work with arrays, or the like).

As an alternative to Martin's approach, you could create at design time
one of each control that you might want to create dynamically, with
Visible set to False, and Index set to zero. Then just Add to these
control arrays as you create new controls dynamically - they will all
use the same event handler.


--
Larry Lard
Replies to group please
Author
20 Sep 2005 1:43 PM
Jeff Johnson [MVP: VB]
"Yep" <y-e.pe***@em-lyon.com> wrote in message
news:1127218162.117587.275570@g49g2000cwa.googlegroups.com...

> We've looked the archives for VB6 reflection, or for an Excel-like
> OnAction event - without success. However we've come across an
> interesting thread located at
>
> <URL:http://groups.google.fr/group/microsoft.public.vb.general.discussion/browse_frm/thread/406d8a574bec6e84/dbf90a95081f2e20>
>
> ...with a post by Mr. Jeff Johnson who, while stating that the problem
> cannot be solved directly, suggests that there are alternate ways which
> could be used, without unfortunately discussing them much.

I guess you're referring to this statement:

-------------
I am sorely disappointed with what I thought would be a really powerful way
of building a dynamic interface, and I have yet to find ANY way to create a
"pluggable" interface that doesn't suffer from some sort of glitch.
-------------

Being over two years ago and being that even then whatever I had tried was
probably a year or two prior, I don't remember what "alternate ways" I've
looked at; I've simply given up on it in VB. Did you look at the link
mentioned by Ken Halter in the next post in that thread?
Author
20 Sep 2005 2:36 PM
Ken Halter
Show quote Hide quote
"Jeff Johnson [MVP: VB]" <i.get@enough.spam> wrote in message
news:uIZpIlevFHA.2792@tk2msftngp13.phx.gbl...
>
> I guess you're referring to this statement:
>
> -------------
> I am sorely disappointed with what I thought would be a really powerful
> way of building a dynamic interface, and I have yet to find ANY way to
> create a "pluggable" interface that doesn't suffer from some sort of
> glitch.
> -------------
>
> Being over two years ago and being that even then whatever I had tried was
> probably a year or two prior, I don't remember what "alternate ways" I've
> looked at; I've simply given up on it in VB. Did you look at the link
> mentioned by Ken Halter in the next post in that thread?

Darn link in that post went stale on us <g> Here's the updated link.

EventCollection Class v2.0 - Add event support to Collections
http://www.mvps.org/emorcillo/en/code/vb6/index.shtml

.....and, here's my attempt..... uses arrays instead of collections.

Add Controls at Runtime With Events (kind of)
http://www.vbsight.com/Code.htm


--
Ken Halter - MS-MVP-VB - http://www.vbsight.com
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm
Please keep all discussions in the groups..
Author
20 Sep 2005 3:41 PM
Someone
The easiest solution is to use control array.  At design time add all the
controls that you could possibly use, set Index to 0, and Visible to False.
Use Load statement at runtime to add more controls.

Some solutions depends on the fact that ObjPtr() does not increase the
reference count of an object. The pointer is added as a text to a collection
and used later to refer to the object. See the comments about ObjPtr here:

http://support.microsoft.com/default.aspx?scid=kb;en-us;199824

While playing with these ideas, you may find the following code useful,
which came from another poster. It lets you see the reference count. I
modified it a little since I found a variable that was not declared. If the
compiler complains about "IUnknown", make sure that you have "OLE
Automation" in the list of references.

Source:

http://groups.google.com/group/microsoft.public.vb.com/browse_thread/thread/9ab3e23591a2ea8e/7db48efc98f6a4ee

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest
As Any, hpvSource As Any, ByVal cbCopy As Long)

Public Function GetRefCount(ByVal unk As IUnknown) As Long
  Dim RefCountAddr As Long
  Dim RefCounter As Long

  RefCountAddr = ObjPtr(unk) + 4
  If RefCountAddr = 4 Then
    ' Object was not set
    GetRefCount = 0
    Exit Function
  End If
  CopyMemory RefCounter, ByVal RefCountAddr, 4
  GetRefCount = RefCounter - 2
End Function

Public Sub AddRef(ByVal unk As IUnknown)
  Dim RefCountAddr As Long
  Dim RefCounter As Long


  RefCountAddr = ObjPtr(unk) + 4
  If RefCountAddr = 4 Then
    ' Object was not set
    Exit Sub
  End If
  CopyMemory RefCounter, ByVal RefCountAddr, 4
  RefCounter = RefCounter + 1
  CopyMemory ByVal RefCountAddr, RefCounter, 4
End Sub

Public Sub ReleaseRef(ByVal unk As IUnknown)
  Dim RefCountAddr As Long
  Dim RefCounter As Long


  RefCountAddr = ObjPtr(unk) + 4
  If RefCountAddr = 4 Then
    RefCounter = 0
    Exit Sub
  End If
  CopyMemory RefCounter, ByVal RefCountAddr, 4
  RefCounter = RefCounter - 1
  CopyMemory ByVal RefCountAddr, RefCounter, 4
End Sub




Show quoteHide quote
"Jeff Johnson [MVP: VB]" <i.get@enough.spam> wrote in message
news:uIZpIlevFHA.2792@tk2msftngp13.phx.gbl...
>
> "Yep" <y-e.pe***@em-lyon.com> wrote in message
> news:1127218162.117587.275570@g49g2000cwa.googlegroups.com...
>
>> We've looked the archives for VB6 reflection, or for an Excel-like
>> OnAction event - without success. However we've come across an
>> interesting thread located at
>>
>> <URL:http://groups.google.fr/group/microsoft.public.vb.general.discussion/browse_frm/thread/406d8a574bec6e84/dbf90a95081f2e20>
>>
>> ...with a post by Mr. Jeff Johnson who, while stating that the problem
>> cannot be solved directly, suggests that there are alternate ways which
>> could be used, without unfortunately discussing them much.
>
> I guess you're referring to this statement:
>
> -------------
> I am sorely disappointed with what I thought would be a really powerful
> way of building a dynamic interface, and I have yet to find ANY way to
> create a "pluggable" interface that doesn't suffer from some sort of
> glitch.
> -------------
>
> Being over two years ago and being that even then whatever I had tried was
> probably a year or two prior, I don't remember what "alternate ways" I've
> looked at; I've simply given up on it in VB. Did you look at the link
> mentioned by Ken Halter in the next post in that thread?
>
Author
20 Sep 2005 4:06 PM
Jeff Johnson [MVP: VB]
"Someone" <nob***@cox.net> wrote in message
news:l4WXe.44103$ct5.11378@fed1read04...

> The easiest solution is to use control array.  At design time add all the
> controls that you could possibly use, set Index to 0, and Visible to
> False. Use Load statement at runtime to add more controls.

What I wanted most was to be able to add ANY control dynamically (including
UserControls that may or may not even have been developed when the parent
app was first written) and hook it up to an event handler so that I could
take advantage of VB's "internal plumbing" for events. Such a thing just
isn't to be found in VB6. I'll hand it to .NET: they made this a snap.
Author
20 Sep 2005 3:23 PM
Yep
Yep wrote:

Hi,

> On our current project we would like to implement a flexible design,
> based on form controls generation in regards of data structures
> retrieved from a database.

First thank you all; not only has our problem been solved by your
suggestions, but some of the ideas proposed have made us think about
new ways to solve other problems.

Martin/Larry :
We've been able to build quick test cases with your suggestions, and
both work perfectly; Martin's pattern is excellent (I'll keep that at
hand) and Larry's usage of the language is quite clever - thank you
very much!

Jeff/Ken:
First sorry for the incomplete quote, the paragraph you're quoting,
Jeff, is exactly the one I was referring to. I'd tried the link but it
was 404 at the time, with Ken's updating I've been able to retrieve his
work. I'm currently reading the code (and will probably spend more time
on the website on my free time), and we might go for it as it is nicely
implemented (that would save us the time to build our own encapsulation
of any of Martin's or Larry's technique).

Again, thank you all for your time and insightful suggestions.


Cheers,
Yep.
Author
21 Sep 2005 7:36 AM
J French
Show quote Hide quote
On 20 Sep 2005 05:09:22 -0700, "Yep" <y-e.pe***@em-lyon.com> wrote:

>Hi,
>
>On our current project we would like to implement a flexible design,
>based on form controls generation in regards of data structures
>retrieved from a database.
>
>For instance, if we have two fields in a table (say employee and date),
>we would like our program to automatically populate a form with two
>fields (employee and date).
>
>We've been successful so far with this approach, but we've encountered
>a problem while trying to bind handlers for events of these generated
>controls; when the number of controls is known, using a WithEvents
>declaration works fine, but in our case we don't know the number of
>controls (it's dynamic), hence we cannot make the appropriate
>declaration (WithEvents doesn't work with arrays, or the like).

<snip>

Personally I would use Control Arrays
- just plant one on the Form, set its Index property to 0
- and then load as many intances as you need
Author
21 Sep 2005 8:51 AM
Martin
This is the most easy way of doing it. But the controls have the same
container.

Show quoteHide quote
"J French" <erew***@nowhere.uk> schreef in bericht
news:43310baf.83664437@news.btopenworld.com...
> On 20 Sep 2005 05:09:22 -0700, "Yep" <y-e.pe***@em-lyon.com> wrote:
>
> >Hi,
> >
> >On our current project we would like to implement a flexible design,
> >based on form controls generation in regards of data structures
> >retrieved from a database.
> >
> >For instance, if we have two fields in a table (say employee and date),
> >we would like our program to automatically populate a form with two
> >fields (employee and date).
> >
> >We've been successful so far with this approach, but we've encountered
> >a problem while trying to bind handlers for events of these generated
> >controls; when the number of controls is known, using a WithEvents
> >declaration works fine, but in our case we don't know the number of
> >controls (it's dynamic), hence we cannot make the appropriate
> >declaration (WithEvents doesn't work with arrays, or the like).
>
> <snip>
>
> Personally I would use Control Arrays
> - just plant one on the Form, set its Index property to 0
> - and then load as many intances as you need
Author
21 Sep 2005 9:29 AM
J French
On Wed, 21 Sep 2005 10:51:37 +0200, "Martin" <ML@community.nospam>
wrote:

>This is the most easy way of doing it. But the controls have the same
>container.

You can change the container at run time
- but not the Parent - without using APIs