Trigger Control Events with Code

JaedenRuiner

Registered User.
Local time
Today, 05:15
Joined
Jun 22, 2005
Messages
154
So,
There are listboxes, and buttons, and all sorts of controls.
No imagine a method: DoSomething(byval lb as ListBox)
in this method we do some affects, add some values to the underlying datasource, and execute a lb.Requery.

that part works fine, however, some of these listboxes have their "AfterUpdate" event set which works fine in most circumstances, but I want to basically execute something like: lb.PerformAfterUpdate, or to that effect that would say: if the AfterUpdate event is set, execute it, if not ignore and continue. Same would be true for the Click event, or Enter event, etc. I just want to trigger a control's event without knowing the procedure name. I'm well aware that I could do myform!my_lb_afterupdate(), but that means i'd have to know what listbox the lb variable points to.

Is this possible in VBA/Access?
ThHanks
Jaeden "Sifo Dyas" al'Raec Ruiner
 
The good news and perhaps in its simplest form…

Behind the Form:-
Code:
Option Explicit
Option Compare Text


Private Sub lstC1D1_Enter()
    DoSomething Me.lstC1D1
End Sub


[color=blue]Public[/color] Sub lstC1D1_AfterUpdate()
    MsgBox "Called    lstC1D1_AfterUpdate"
End Sub

In a standard Module:-
Code:
Option Explicit
Option Compare Text


Public Sub DoSomething([color=red]ByRef[/color] lb As ListBox)

    If lb.AfterUpdate = "[Event Procedure]" Then
        CallByName lb.Parent, lb.Name & "_AfterUpdate", VbMethod
    End If

End Sub

The bad news is we can not trigger events, only the system can.
All we can do is call the code in the event handler. If the system sends an event handler some arguments we can not return those arguments to the system simply by calling the code.

Also, the Control’s event property may not be [Event Procedure] but rather a direct call to a Function and that Function may or may not pass arguments.

Chris.
 
Just to note Chris's change from ByVal to ByRef... all objects are always ByRef, regardless if you try to specify ByVal

Theoretically, passing an object ByVal would have to create an entirely new instance of the object... all the memory that one takes up would be doubled, and changes would not be synced between the two, because there'd be two separate objects rather than one.

VBA ignores the ByVal modifier for any paramters other than the basic datatypes.

It is possible to actually duplicate objects using the RtlCopyMemory API, but it's really pretty obscure and not a whole lot of practical use for it with Access/VBA developers.

Cheers,
 
Jack.

This line of code, with the MSComctlLib.TreeCtrl.2, is correct:-
Private Sub Categories_NodeClick(ByVal objNode As Object)

If it is changed to:-
Private Sub Categories_NodeClick(ByRef objNode As Object)

it produces the following error…
---------------------------
Microsoft Visual Basic
---------------------------
Compile Error:

Procedure declaration does not match description of event or procedure having the same name
---------------------------
OK Help
---------------------------

The reason I simply highlighted the change, and did not comment on it, is that it is not correct to say “all objects are always ByRef, regardless if you try to specify ByVal”.

Words like ‘all’ and ‘always’ are absolutes and absolutes can be disproved by any one single exception. I think it is best to avoid absolutes and stick to the scope of our knowledge.

I would also like to ask some questions with regards to your statement:-
>>It is possible to actually duplicate objects using the RtlCopyMemory API, but it's really pretty obscure and not a whole lot of practical use for it with Access/VBA developers.<<
Have you ever been able to use the RtlCopyMemory API in Access/VBA?
If so; was it used to copy an object?
If so; how did you determine the size of the object to copy?

Chris.
 
Correct on the byval/byref note... I had forgetten about certain activeX's which do that.

As for RtlCopyMemory, I've used RtlMoveMemory, but not the RtlCopyMemory (although I'm not sure there'd be a difference based on the way it was used). The task was to pass the pointer of a non-global object through an openarg and assign the pointer to a new object variable within the form's scope. So no, it wasn't a direct copy of the object but rather a means to cheat scope and, in essence, pass an object via openargs. (for the record, I was shown the method rather than having figured it out on my own).

Indeed after a quick investigation there seems to be no means of determining an object's in memory size to make a physical copy of it.

Cheers,
 
Thanks for the reply, Jack.

Two part comment…
1.
The ByVal and ByRef apparent mix-up with the tree-view control is known by at least two people, Brent Spalding and myself. There may be many other people who also know it. So it seems to me that speaking in absolute terms can fail at the drop of a hat. When it fails the person that made the absolute assertion is left with egg on their face. It seems best to me to avoid the egg by avoiding absolutes.


2.
I can’t say I have ever seen the RtlCopyMemory API used in VBA or VB for that matter even though Microsoft list it on their site. Only the RtlMoveMemory seems to work in VBA. As for the size of the Object moved well, it doesn’t matter. The way it is used is to move/copy the value of the pointer to the Object. Now since we are talking about a 32 bit operating system, the pointers are 32 bit irrespective of the Object to which they point.

This means that the move/copy is fixed at 4 bytes and those 4 bytes are transferred to a Long. The Long is sent through OpenArgs and converted back to a 32 bit pointer by using the same RtlMoveMemory API call but in the reverse order. So we are not passing an Object through OpenArgs but rather we are passing a pointer to an Object.

I can not test it but when it is used on a 64 bit system then the number of bytes moved should be 8 and the datatype used should be a LongLong. If OpenArgs can handle a LongLong in the 64 bit system then the method to pass a pointer to an Object should be the same.

Now, since pointers are the same length the Objects can be of any type… least I have not seen as yet an Object it doesn’t work on. So a pointer to a Collection can also be passed and that Collection can contain other pointers.

There is a demo in the Sample Database forum on this site which uses that technique. It passes a 4 byte pointer to a Collection through OpenArgs which results in the calling of 2449 Classes.

So, in fact, it becomes a very lightweight way to pass a lot of data through OpenArgs.

Chris.
 

Users who are viewing this thread

Back
Top Bottom