But...my object DOES source automation events! 
Author Message
 But...my object DOES source automation events!

Hi all,

"Object does not source automation events". That's what VB says.
"My object does source events, and I can prove it!" That's what I say.

How can I make VB see the light?

The details:

I use and ActiveX-Control ("Core") within another ActiveX-Control
("Curve") within an application ("App").
"Core" has several classes of type "Public - not creatable". A certain
one, called "ccvChannel" has two public events.

When I compile "Core", and use the executable (OCX) within "Curve",
everything is just fine.
When I open the "Curve" and "Core" projects as a group, with the same
source code I just used to compile "Core", the compiler will rebuff
me:

WithEvents objChannel As ccvChannel
--> Object does not source automation events!

When I go into the browser (F2), and look at ccvChannel, I see(!) the
two events.
I've tried closing and opening the projects.
I've tried re-compiling everthingy (that works)
I've tried deleting all VB temp files

Dear internet community,
how can I make my VB like me again?

Thank you for your attention.
Thank you for your suggestions!

Robert



Mon, 30 Jan 2012 22:52:10 GMT  
 But...my object DOES source automation events!


Quote:
> Hi all,

> "Object does not source automation events". That's what VB says.
> "My object does source events, and I can prove it!" That's what I say.

> How can I make VB see the light?

> The details:

> I use and ActiveX-Control ("Core") within another ActiveX-Control
> ("Curve") within an application ("App").
> "Core" has several classes of type "Public - not creatable". A certain
> one, called "ccvChannel" has two public events.

> When I compile "Core", and use the executable (OCX) within "Curve",
> everything is just fine.
> When I open the "Curve" and "Core" projects as a group, with the same
> source code I just used to compile "Core", the compiler will rebuff
> me:

> WithEvents objChannel As ccvChannel
> --> Object does not source automation events!

> When I go into the browser (F2), and look at ccvChannel, I see(!) the
> two events.
> I've tried closing and opening the projects.
> I've tried re-compiling everthingy (that works)
> I've tried deleting all VB temp files

You might find comfort in the fact that this error is always fustrating once
the obvious cause - no published events - has been eliminated. But before
you resort to defenestration appreciate a cure will be found. <grin>

From a 10,000 foot view the error occurs because VB6 (the parser) with your
current configuration sees either a different Interface for "ccvChannel" or
an invalid/incorrect one when it gets to that point. So ...

First off clean-out the projects. Remove all temp files and especially any
.OCAs that may exist. Using VSS is always handy for this. Check-in source,
burn the projects down to the water-line and then check-out the project
anew.
Run a Registry Cleaner so that there exists only one, or best, no entry for
either object/component. Let VB re-register them.
Also try changing the order of compile in the group file. (a simple text
file, just move one project above the other.)
Re-order the reference preferences. Core before Curve ???
Examine the references carefully to make sure they are pointing to what they
should.
Try fully referencing the offending interface, ie, something like
       Dim WithEvents objChannel As Core.ccvChannel
       [Warning Air Code]
And of course make sure you haven't accidently exposed a "ccvChannel" thingy
somewhere else.

hth
-ralph



Tue, 31 Jan 2012 00:21:54 GMT  
 But...my object DOES source automation events!
Meant to add - these steps are not necessary the "fix" in itself, but rather
by doing the above - you often uncover an anomaly which will guide you to
the "fix".

-ralph



Tue, 31 Jan 2012 00:35:51 GMT  
 But...my object DOES source automation events!
Thanks for your detailed reply!

Here's what I found out:
Cleaned temp files, unregistered all controls, ran two different reg
cleaners (one specifically written to clean out our own controls),
manually searched through the registry and found no leftover
references to "Core".
Checked the order in the VBG file (I had flipped it yesterday, now
it's Core - Curve - App again.

Registered everything again, and compiled the controls in question,
just to be sure.

Still didn't work.

BUT, I thought to search for ccvChannel in the registry while
everything was unregistered, and voila! Dozens of references in the
CLASSES_ROOT.

Now, my understanding is that once a control is unregistered, all of
it's interfaces should be gone from the registry?

I'll make backups, then remove those entries by hand, and see what
happens.

Thanks again!

Robert



Tue, 31 Jan 2012 17:05:01 GMT  
 But...my object DOES source automation events!
Having manually removed around 1 MB(!) worth of orphaned references in
CLASSES_ROOT, the error still occurs.

Any further ideas?

BTW, when I combine "Core" with a different project that uses
"Withevents .... As ccvChannel", everything works. It's just with that
one project.

Robert



Tue, 31 Jan 2012 19:23:55 GMT  
 But...my object DOES source automation events!


Quote:

> BUT, I thought to search for ccvChannel in the registry while
> everything was unregistered, and voila! Dozens of references in the
> CLASSES_ROOT.

> Now, my understanding is that once a control is unregistered, all of
> it's interfaces should be gone from the registry?

Sounds like you are not using binary compatibility ... thus everytime you
compile, your going to get a new entry.

"How To Use Project and Binary Compatibility"
http://support.microsoft.com/kb/161137

"Binary Compatibility"
http://www.vbsight.com/BinaryComp.htm

-ralph



Tue, 31 Jan 2012 19:49:40 GMT  
 But...my object DOES source automation events!


Quote:
> Having manually removed around 1 MB(!) worth of orphaned references in
> CLASSES_ROOT, the error still occurs.

> Any further ideas?

> BTW, when I combine "Core" with a different project that uses
> "Withevents .... As ccvChannel", everything works. It's just with that
> one project.

Fresh out of anything new at the moment.

You might open the .vbp file and compare its entry for core against the
entry in projects that work. If different you might simply replace the
entry, but if it is just that one project, then I'd probably just destroy
the .vbp file and rebuild the project from scratch. It doesn't take long.

-ralph



Tue, 31 Jan 2012 20:13:40 GMT  
 But...my object DOES source automation events!
  I wonder if there might just be a quirk with
events in a non-creatable class. The structure
of your control sounds a bit odd. I don't see
why you'd put one custom control on top of
another, or why non-creatable classes would
have events. Typically a non-creatable class is
used to provide structured data, a group of
related objects, a collection, or something like
that. .... Just a thought, based on very little
knowledge of what your control is doing. :)

  If it is an issue of the class type, though, you
might be  able to test that by just trying a version
wherein the class is public creatable.

   Also, the Registry entries shouldn't matter as
long as the current version is registered, which VB
does when it runs. When the program runs, the
correct CLSID of a late-bound class will be found
under the ProgID key, and VB will have written
the right values under the latest CLSID key, to be
found in the case of an early-bound object. The
fact that there may be 100 invalid CLSID keys
doesn't make a difference, other than increasing
the size of the Registry, so long as nothing is
trying to access an object with those CLSID
numbers.
   If you have doubts you can look up the ProgID key,
CLSID keys for all public classes, and the Typelib
subkey, to make sure that they all hold the right data.



Tue, 31 Jan 2012 22:27:00 GMT  
 But...my object DOES source automation events!
See this article about how to remove duplicate entries, when you see
multiple of them in Project-->References.

PRB: DCOMCNFG Reports Multiple Copies of DCOM Server
http://support.microsoft.com/default.aspx?scid=kb;en-us;180525

You can also delete or rename the DLL/OCX, and run a registry cleaner. The
theory is that the registry cleaner will find that the DLL/OCX is missing,
and delete its entries from the registry. Here is one free registry cleaning
tool, download the "Slim" or "Portable" version because the standard version
is the same, but includes a toolbar(Yahoo or Google), otherwise it has no
spyware/malware.

http://www.ccleaner.com/download/builds
http://en.wikipedia.org/wiki/CCleaner



Tue, 31 Jan 2012 23:57:40 GMT  
 But...my object DOES source automation events!

Quote:
> ? I wonder if there might just be a quirk with
> events in a non-creatable class.

GOLD!
After I changed the class to Multi-Use, re-compiled and re-opened the
project, it worked!
I did that after creating a new VBP, BTW - that didn't help.

Quote:
> The structure
> of your control sounds a bit odd. I don't see
> why you'd put one custom control on top of
> another

Code re-use, and code structuring.
The "Core" control basically is a fast 2D-drawing surface,
specifically written for curves, and in general, vector-oriented
graphics, with some higher-level objects (e.g. Scales the user can
also position by mouse-dragging)
My main use of this control is in "Curve", but I use it elsewhere as
well. And for testing alone, it's been more than worth making a
separate control out of it (Often hard enough to determine whether the
input data or the processing is at fault).

Quote:
> or why non-creatable classes would
> have events.

"ccvChannel" represents one curve (e.g. a sine wave), and will fire
events when certain properties change. Still, I want a user of "Core"
to use a standardized interface for creating "ccvChannel", just as
well as its sister objects ("ccvPolygon", "ccvScale", etc.). This is
because I need a few parameters upon creating. If VB were to allow
parameters for constructors, life would be much easier - and better
structured.

In an ideal world, "ccvChannel" would have a constructor with the
required parameters, would be publicly creatable, and would take care
of all the administrative tasks related to creating in its
constructor.

Thanks all for your help!
Any ideas how I can keep the object "public not creatable", and still
avoid the error? Since I am currently the only user of "Core", I might
as well make the class publicly creatable, but it's not supposed to be
- it feels dirty.

Robert



Fri, 03 Feb 2012 19:03:32 GMT  
 But...my object DOES source automation events!
Any ideas how I can keep the object "public not creatable", and still
avoid the error? Since I am currently the only user of "Core", I might
as well make the class publicly creatable, but it's not supposed to be
- it feels dirty.

   Sorry, I don't know a solution. It seems
possible that it could work that way by design,
since a non-creatable class is dependent on
it's parent, creatable class. The event interfaces
might not work that way.

[  I know that wouldn't
work very well, if at all, in scripting, for instance.
One can attach an event variable to a call to
WScript.CreateObject and "sink" events for the
object:

 Set IE = WScript.CreateObject("InternetExplorer.Application", "_IE")

But I don't know how one could code for something
like this to work:

Set ObjChild = Obj.GetChildObject(par1, par2, EventInterface)

]

   From what you said it sounds
like the only solution is to either have some kind of
setup routine for each class, that runs
in Class_Initialize, or to have something like an
Init function, so that creating the class is step 1
but Init must be called before using the class. ...That
is a little bit awkward.

   I guess you could have all of your classes created
by the main class, which then calls Init and hands
off the class as though it were a non-creatable class,
but you'd still have creatable classes listed in the typelib,
and ProgIDs in the Registry. ... As you said, that feels dirty.



Fri, 03 Feb 2012 21:45:24 GMT  
 But...my object DOES source automation events!



Quote:
>> I wonder if there might just be a quirk with
>> events in a non-creatable class.
> GOLD!
> After I changed the class to Multi-Use, re-compiled and
> re-opened the project, it worked!
> I did that after creating a new VBP, BTW - that didn't help.

LOL (at myself)

Thanks for coming back with the solution. Though in this case it is somewhat
embarressing as the answer was contained within the first couple of
paragraphs in your original post. I didn't catch it because I thought
"ccvChannel" was "Core". (and thanks to mayayana for catching the real
issue.)

I subsquently focused on an {*filter*} problem and skipped the obvious. (I'm
getting too old. <grin>)

Quote:
>> The structure
>> of your control sounds a bit odd. I don't see
>> why you'd put one custom control on top of
>> another
> Code re-use, and code structuring.

This is normal. I abuse this ability quite often myself in building
composite controls. From my C/Unix days - create one simple tool that is
reusable in multiple contexts.

Quote:
> The "Core" control basically is a fast 2D-drawing surface,
> specifically written for curves, and in general, vector-oriented
> graphics, with some higher-level objects (e.g. Scales the user can
> also position by mouse-dragging)
> My main use of this control is in "Curve", but I use it elsewhere as
> well. And for testing alone, it's been more than worth making a
> separate control out of it (Often hard enough to determine whether the
> input data or the processing is at fault).
>> or why non-creatable classes would
>> have events.
> "ccvChannel" represents one curve (e.g. a sine wave), and will fire
> events when certain properties change. Still, I want a user of "Core"
> to use a standardized interface for creating "ccvChannel", just as
> well as its sister objects ("ccvPolygon", "ccvScale", etc.). This is
> because I need a few parameters upon creating. If VB were to allow
> parameters for constructors, life would be much easier - and better
> structured.

Yes life would be, but you can accomplish the same thing by defining your
own 'constructor' method. The only problem is you have to make sure you
always call the constructor before otherwise using the object...
    Dim A As ClsA: Set A = New ClsA
    ClsA.Init <parameters>

Quote:
> In an ideal world, "ccvChannel" would have a constructor with the
> required parameters, would be publicly creatable, and would take care
> of all the administrative tasks related to creating in its
> constructor.
> Thanks all for your help!

     With me excluded, as I took you around the barn and into the north
pasture for no good reason.

Quote:
> Any ideas how I can keep the object "public not creatable", and still
> avoid the error? Since I am currently the only user of "Core", I might
> as well make the class publicly creatable, but it's not supposed to be
> - it feels dirty.

First off, here is why WithEvents is failing. When you call WithEvents VB
creates an additional hidden object reference to the objects IConnection
interface. something like this .... (semicolons show hidden code)
     Private WithEvents objChannel As ccvChannel ' object reference
     ;  Private IConnectObjChannel As ccvChannel.IConnection
     ;  IConnectObjChannel = New ccvChannel
ccvChannel is non-Createable, thus the compiler blows up
(This also why 'Interfaces' can't have Events, but that is another story)

What you have to do is duplicate this by a bit of indirection. (Based on the
oldest maxim in programming - there is nothing that can't be solved by
another layer of indirection. <grin>)

[I'm assuming that Core is the main component and it is publishing a
createable default public interface which I'll call CCore for now.]
You can add ccvChannel events to CCore's Events and let CCore manage them.
You can create a 'master' event object to manage all events and let the
component expose it.
In conjunction with this you can let CCore create the ccvChannel object or
fetch a current one and pass it back to a client that needs it. This is
actually the real reason Public Non-Createable exists in the first place.
Clients can 'see it' they just can't create one on out of the context of the
parent object.

You might also 'expose' the ccvChannel stuff (Children) through Interfaces.
etc.

The key is to have a public object and let it manage the communication.

hth
-ralph



Fri, 03 Feb 2012 22:18:01 GMT  
 But...my object DOES source automation events!

Quote:
> ? ? ?With me excluded, as I took you around the barn and into the north
> pasture for no good reason.

...but at least I have a much smaller registry to show for it!

Quote:
> What you have to do is duplicate this by a bit of indirection. (Based on the
> oldest maxim in programming - there is nothing that can't be solved by
> another layer of indirection. <grin>)

It's possible, but runs counter to my code structure.
The idea is this:
I have one "Core" control in my "Curve" control. Naturally, "Core"
fires events, e.g. when a user clicks the mouse in it.
I have multiple "ccvChannel" objects, each representing one graphical
object displayed in "Core".
For each "ccvChannel", I have a corresponding class instance in
"Curve". Let's call it "ChannelData". It contains higher-level
information that doesn't belong in "ccvChannel", e.g. about the data
source that is used, user settings for that channel, and so on.
Using WithEvents with "ccvChannel", I can directly communicate between
"ChannelData" and "ccvChannel". Mostly, it will be "ChannelData"
telling "ccvChannel" what to display, but in some cases, there will be
changes to "ccvChannel" from other sources that "ChannelData" needs to
know about.
That's very neat - the two classes negotiate most things all by
themselves, and don't make the overall code structure more
complicated.

Were I to handle the communication over a central object, I would also
need message distribution code that would need to know which objects
are bound to each other. It would affect most of my class structure.
Frankly, I don't like code that's strewn all over my project (although
I admit it's unavoidable sometimes).

For now, I can live by keeping things as they are - it works just
fine, as long as "Core" runs in binary. Whenever I need to debug both
projects together, I simply change the class type, but revert back
once the debugging is finished.

With any luck, I'll be moving to a more modern platform rather soon.
Certainly with it's own range of bugs and oddities, but hopefully
still supported by the vendor.

Robert



Sat, 04 Feb 2012 21:24:46 GMT  
 But...my object DOES source automation events!



<snipped>

Quote:
> For now, I can live by keeping things as they are - it works just
> fine, as long as "Core" runs in binary. Whenever I need to debug both
> projects together, I simply change the class type, but revert back
> once the debugging is finished.

Often the most sensible solution.

Quote:
> With any luck, I'll be moving to a more modern platform rather soon.
> Certainly with it's own range of bugs and oddities, but hopefully
> still supported by the vendor.

It would take a whiteboard and more time and space than we have here, but
from what you described I believe there may be some other patterns that need
exploring. So no matter what OOPL you move on to, you might take some time,
and revisit Fowler's "Refactoring".

Success
-ralph



Sun, 05 Feb 2012 00:58:59 GMT  
 
 [ 14 post ] 

 Relevant Pages 

1. Object does not source Automation events error

2. IE Automation MSHTML - Document object - Missing events problem.

3. ? How trap event from IE with Automation Objects ?

4. Problems with callback reference to a COM object - which isn't a source of events

5. Common Dialog and Timer Events/MCI Done Event

6. VB event source and a ATL event sink

7. Need help doing a Subtotal through Excel automation in vb.net

8. Any one had problem doing 16 bits Automation Server under Win 3.11

9. OLE Automation/REmote source code

10. Source Safe Automation in asp anyone?

11. DoEvents not doing any events

12. Thread Done Event Handler never executed ?

 

 
Powered by phpBB® Forum Software