Results 1 to 25 of 25

Thread: Detect whether an event handler is attached to a VB6 ActiveX control's event

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Detect whether an event handler is attached to a VB6 ActiveX control's event

    I have a VB6 OCX control used on MS Access forms. It turned out that raising an event from my ActiveX may slow down code execution dramatically when the control is hosted by an MS Access form. This does not happen in VB6 apps - only in MS Access.

    My idea is not to raise the events if they do not have attached event handlers in MS Access VBA code. Is there a way to detect (from inside an ActiveX control) whether an event has an attached event handler?

  2. #2
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Tough question: I don't know - that would take a bit of spelunking the COM event system, IConnectionPoint and the like to figure out.
    I don't believe COM events are that granular - whether you sink all events of an object, or specific ones.
    I suspect an object sinks all events, and thus I don't know that an object itself can actually tell which events have handlers.
    Forwarding an event may specifically be handled by the runtime (MS Access VBA in your case)

    Personally Instead of dissassembling how the runtime keeps track of which events have handlers - I would probably just make an initializing code to specify which "events" I want fired from my Control.
    This would at least allow you to test your theory.

  3. #3
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    I was thinking of a property ... IsVBA ... default it to false... but you'd set it to true when using it in Access... and then before the events are raised, you'd check the flag and not raise them if it's set... of course... this is assuming you're the author of the control ... if you're not... well.... that certainly complicates things.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  4. #4
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    alternatively you can use a callback interface, and sidestep the Event overhead altogether.

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Guys, sure I also have this idea of implementing a special Boolean property to enable/disable event firing. But I am searching for a more professional 'automatic' solution, when the user of my control should not worry about learning these special properties to optimize the performance.

    To DEXWERX: What do you mean by "theory"? I already compiled my control with the RaiseEvent's commented out. This was the way how I detected that event firing slows down execution dramatically in Access.

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by DEXWERX View Post
    alternatively you can use a callback interface, and sidestep the Event overhead altogether.
    Yes, interfaces are another good thing we can use to speed up our components. I already used this idea in another ActiveX DLL tool that enumerates files and folders. Unfortunately, I can't change the interface of the existing OCX because of backward compatibility.

  7. #7
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,871

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Is there way to detect in which environment (VB6/VBA/etc) a component is used?
    If there is then you can always turn events automatically off, unless a special property is set.

  8. #8

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by Arnoutdv View Post
    Is there way to detect in which environment (VB6/VBA/etc) a component is used?
    The problem is that we may need those events in VBA, and we should not decide whether to raise them based on the environment.

  9. #9
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    You could use GetModuleFileName to get the executable's name. Maybe something like the following...

    Code:
    
    Option Explicit
    
    Private Declare Function GetModuleFileNameW Lib "kernel32" (ByVal hModule As Long, ByVal lpFileName As Long, ByVal nSize As Long) As Long
    
    Private Function MyExeSpec() As String
        ' Handles unicode paths and file names.
        ' Returns full file spec of executable, including the .EXE.
        Const MAX_PATH As Long = 260
        MyExeSpec = Space$(MAX_PATH)
        MyExeSpec = Left$(MyExeSpec, GetModuleFileNameW(0, StrPtr(MyExeSpec), MAX_PATH))
    End Function
    
    
    That's not going to tell you whether or not events are hooked though. Dex's idea of using a callback instead of event hooks would certainly work though, especially if combined with use of GetModuleFileName.

    EDIT1: I just tested it and it returns something like "C:\Program Files (x86)\Microsoft Office 2010\Office14\MSACCESS.EXE" when called from within Access. I didn't try it from within an OCX, but it should return the same thing.
    Last edited by Elroy; Feb 7th, 2017 at 11:09 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Guys, you started to think in a wrong direction. I am waiting for a COM guru who knows how to detect whether an event handler is attached to an event.

  11. #11
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,871

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by wisekat View Post
    The problem is that we may need those events in VBA, and we should not decide whether to raise them based on the environment.
    Then you can have a property to overrule the default settings.

  12. #12
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by wisekat View Post
    Guys, you started to think in a wrong direction. I am waiting for a COM guru who knows how to detect whether an event handler is attached to an event.
    Wisecat,

    There are certainly a couple of COM gurus around here, and I'll be quite interested to see if someone can actually figure that out. I think of hooking an event handler in the same way I think of subclassing. The only real difference is that the VB6 IDE keeps track of hooked event handlers much better than it does subclassing, and therefore unhooks them when the "Stop" button is clicked.

    In other words, it's just code that has inserted itself into an address-chain. I'm not sure that Windows has any "event" that fires when some other event is being hooked. I'd be surprised if it does because that could potentially slow down the entire operating system. That's basically the core of the OS.

    But best of luck with it.

    Elroy

    EDIT1: Just thinking about it some more, I'm sure the starting address to the address-chain of an event is stored somewhere. And, it's probably zero if there are no events for that "potential event". I've personally got no idea how to find that address though. There are lots of assumptions in that statement though, and you'd have to proceed carefully.
    Last edited by Elroy; Feb 7th, 2017 at 11:30 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  13. #13
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,852

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    I was playing around with this a bit more, and you could play around with SetWinEventHook and further hook your events. I'm still not exactly sure what that gets you though. You could do that with something like the following:

    For BAS:

    Code:
    
    Option Explicit
    '
    Public Declare Function SetWinEventHook Lib "user32" (ByVal eventMin As Long, ByVal eventMax As Long, ByVal hmodWinEventProc As Long, ByVal pfnWinEventProc As Long, ByVal idProcess As Long, ByVal idThread As Long, ByVal dwFlags As Long) As Long
    Public Declare Function UnhookWinEvent Lib "user32" (ByVal hWinEventHook As Long) As Long
    '
    
    Public Sub WinEventProc( _
                            ByVal hWinEventHook As Long, _
                            ByVal dwEvent As Long, _
                            ByVal hWnd As Long, _
                            ByVal idObject As Long, _
                            ByVal idChild As Long, _
                            ByVal dwEventThread As Long, _
                            ByVal dwmsEventTime As Long)
    
    
        Debug.Print dwEvent
    
    End Sub
    
    
    
    And for Form1:

    Code:
    
    Option Explicit
    
    Private hWinEventHook As Long
    
    Private Sub Form_Load()
        hWinEventHook = SetWinEventHook(0, &HFF, 0, AddressOf WinEventProc, 0, 0, 0)
        Debug.Print "The prior hook address: "; hWinEventHook
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
        If hWinEventHook Then UnhookWinEvent hWinEventHook
    End Sub
    
    
    (EDIT: To understand the above dwEvent, you'd need to study this).

    But upon even more thought, why not just adopt a convention for yourself to tell the ActiveX module when it's hooked using WithEvents. In other words, just create some property named "ImHooked", and be sure and set it whenever you're using its events.
    Last edited by Elroy; Feb 7th, 2017 at 12:05 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  14. #14
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by wisekat View Post
    Guys, sure I also have this idea of implementing a special Boolean property to enable/disable event firing. But I am searching for a more professional 'automatic' solution, when the user of my control should not worry about learning these special properties to optimize the performance.

    To DEXWERX: What do you mean by "theory"? I already compiled my control with the RaiseEvent's commented out. This was the way how I detected that event firing slows down execution dramatically in Access.
    Quote Originally Posted by Arnoutdv View Post
    Is there way to detect in which environment (VB6/VBA/etc) a component is used?
    If there is then you can always turn events automatically off, unless a special property is set.
    Quote Originally Posted by wisekat View Post
    The problem is that we may need those events in VBA, and we should not decide whether to raise them based on the environment.
    and yet... that's EXACTLY what you've asked for. So now you're wanting to selectively fire events... you're back to a flag of some sort.

    Quote Originally Posted by wisekat View Post
    Guys, you started to think in a wrong direction. I am waiting for a COM guru who knows how to detect whether an event handler is attached to an event.
    Arnoutdv is about as close to a guru as you're going to get. His knowledge of the inner workings of VB6 is (in my opinion) phenominal, there's few that I know that have his depth of knowledge.

    So maybe take a step back, take a deep breath and think... really THINK about what it is you're after... don't worry about the how, just the WHAT... WHAT is it you're trying to accomplish? Once you can articulate the problem, then the answer may become more apparent. Again, don't worry about the how.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  15. #15
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    I alluded to this earlier - as far as the Component is concerned, an event Sink supplies a Source interface, and it's is all or nothing. it's not selective - per event.
    You either have events or you don't.
    The runtime hides the implemented source interface and selectively forwards to the events you supplied handlers for.

    so anything short of dissassembling the access VBA runtime to see which events have handlers, isn't going to get you there from the component side.

    sources:
    http://www.codeguru.com/cpp/com-tech...time-Sinks.htm
    http://thrysoee.dk/InsideCOM+/ch08b.htm#171

    this also tells me that it's not possible to speed up a single event by "disabling" other events.
    @wisekat That's what I thought your theory was.

    every RaiseEvent is basically an IDispatch::Invoke() on a runtime supplied Sink.


    you're going to have to break binary compatibility and add a function to filter which events you want raised from the component.
    Last edited by DEXWERX; Feb 7th, 2017 at 03:03 PM.

  16. #16
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    I doubt this is viable. The "plumbing" that implements COM Events is designed to be anonymous. You never know how many (if any) listeners there are, have no assurance of the order an event gets processed by the listeners, and so on.

    If this was a big deal it would have been addressed a long time ago.

    Your best bet is probably going to be to implement those "notify me of..." properties already described above. If performance is a serious issue then COM Callbacks would be a better choice than Events anyway.

  17. #17
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by DEXWERX View Post
    ... this also tells me that it's not possible to speed up a single event by "disabling" other events...
    Without more detail it is hard to be sure, but I suspect he has one or more very chatty Events that get raised with high frequency. By not raising them at all for a client that ignores them performance might be improved quite a bit.

  18. #18
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by dilettante View Post
    Without more detail it is hard to be sure, but I suspect he has one or more very chatty Events that get raised with high frequency. By not raising them at all for a client that ignores them performance might be improved quite a bit.
    I think that's exactly what he's trying to do.

    edit:@wisekat quick question, have you tried supplying empty event handlers for all the events, to see if that helps performance at all?
    Last edited by DEXWERX; Feb 7th, 2017 at 03:23 PM.

  19. #19
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Another possible culprit might be use of the gratuitously bloated 64-bit build of MS Access.

    That puts an extra layer of COM proxy, a thunk, and some expensive cross-process marshaling overhead between MS Access and the 32-bit Control. If so then making sure the chatty Event(s) have no (or only ByVal) arguments could improve performance.

    However the only reason for a really chatty Event is to let clients do some sort of intermediate processing and return altered data.

    Ahh yes, the manual: How Marshaling Affects ActiveX Component Performance

    If that's what is going on there isn't much you can do except make the raising of such Events conditional, and I'm still not sure there is any practical way to accomplish this by "sniffing the plumbing."
    Last edited by dilettante; Feb 7th, 2017 at 04:02 PM. Reason: added link to That Fine Manual

  20. #20

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by DEXWERX View Post
    edit:@wisekat quick question, have you tried supplying empty event handlers for all the events, to see if that helps performance at all?
    Yes, I use those chatty events in WinAPI drawing code, and I get some data that may change the appearance of the screen items on-the-fly through the parameters of the events passed ByRef. Removing event parameters does not make sense for me.

    Perhaps, it was not an ideal choice to use events for that. But the users of my control prefer events - sometime they hardly understand the concept of interfaces and callback calls based on them.
    Last edited by wisekat; Feb 8th, 2017 at 04:45 AM.

  21. #21

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by dilettante View Post
    Another possible culprit might be use of the gratuitously bloated 64-bit build of MS Access.

    That puts an extra layer of COM proxy, a thunk, and some expensive cross-process marshaling overhead between MS Access and the 32-bit Control.
    That's interesting! Do we really have the ability to use 32-bit OCX's produced with VB6 in 64-bit Office apps? This would help me and my customers a lot. Can you provide more info about that? Does it apply only to MS Access, or to 64-bit Excel and Word too?

    I've thought that Microsoft made completely impossible the use of 32-bit OCX's in its 64-bit Office after reading this (see the ActiveX Control and COM Add-in Compatibility subsection):

    http://msdn.microsoft.com/en-us/library/ee691831.aspx

  22. #22
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by wisekat View Post
    That's interesting! Do we really have the ability to use 32-bit OCX's produced with VB6 in 64-bit Office apps?
    No, I think that's not possible (because "Visual" COMponents will have the additional problem
    of correct "siting" on a given - 64Bit - ParentContainer - and I cannot imagine how that shall
    work across Process-boundaries).

    For COM-Dlls though, the solution is quite simple with an intermediate ActiveX-Exe
    (altough at the cost of performance, due to cross-process-marshalling).

    Not sure, what kind of OCX-COMponent you have developed - but a lot of
    self-developed Controls could be re-designed with relative ease, to work
    from "pure, normal Classes" (from inside an ActiveX-Dll then) - in conjunction
    with an already existing "hWnd-based target-container".

    Within the VB6-IDE you could try out this approach, using a Pairing of a
    Drawing-Class, and a PictureBox.

    Olaf

  23. #23
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    I'm not sure there is such a thing as a system-supplied standard surrogate process to house a 32-bit OCX as there is for a 32-bit ActiveX DLL that doesn't define controls. For such DLLs containing only classes it becomes a simple matter of some additional steps when registering the ActiveX DLL.

    Since those "steps" can be a little exotic to work out if you don't do this a lot, the common workaround is to move the classes to an ActiveX EXE.

    So with a DLL surrogate process or an ActiveX EXE, as long as you register in the 64-bit portion of the registry COM handles the thunking between 64-bit clients and your 32-bit servers.

    However I have tried to make that work for controls by moving them into an ActiveX EXE.

    Here is one old blog post: Accessing 32-bit DLLs from 64-bit code


    Sorry to get you excited. I probably mislead you on this, thinking you were talking about a non-control Class.

  24. #24

    Thread Starter
    Lively Member
    Join Date
    Oct 2014
    Posts
    94

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    Quote Originally Posted by dilettante View Post
    Sorry to get you excited. I probably mislead you on this, thinking you were talking about a non-control Class.
    I started this thread with the words "I have a VB6 OCX control", which means I have a visual ActiveX control. But not a problem. It's off-topic, but if someone ever finds a way how to use our legacy VB6 OCX's in the 64-bit MS Office environment (by changing them or doing something in MS Office, etc.), do let me know. Event if it happens in a year or more - this is very important to me and my customers. TIA

  25. #25
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,871

    Re: Detect whether an event handler is attached to a VB6 ActiveX control's event

    To my knowledge it's impossible by design to use 32bit dll/ocx in a 64bit application (process).
    Like said before only a 32bit ActiveX can be used, because that's running in it's own process.

    So advice your clients not use 64bit version of Office if they want to use your product(s)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width