Greetings,
I appologize if this is in the wrong forum but this looks like the most applicable for my issue.
I've written in VS 2005 C++ COM visible classes and these work great from VB 6.0 applications. My only problem surrounds events/callbacks.
I've replaced a native ActiveX component with a .NET/COM visible one and everything works, except a simple event it needs. Under no circumstances have I been able to get VB 6.0 to reference a .NET class with the "WithEvents" keyword nor be able to install an event handler/callback.
I need a very simplistic event or callback, which is a simple single-argument "TimeOut" handler for asynchronously processing data in the .NET assembly. It simply needs to call a given VB6.0 function to be alerted for this condition and set a true/false value (which I can do with the callback itself or through API/disk or other methods if the whole STA/MTA thing gets hairy).
I've found numerous ways to accomplish this with VB.NET or C#, but zilch for C++. Hours of scouring have examples with old syntax (__event, etc.etc.) but nothing for new CLR syntax.
Are there any good sources specifically for VS2005 C++ with examples
I've create the public delegate (NOT COM visible outside my class) similar to:
[ComVisible(false)]
public delegate void TimedOut( Int32^ );
Then within my class, I create the event:
[ClassInterface(ClassInterfaceType::AutoDual)]
public ref class MyClass {
...
public:
event TimedOut ^TimedOut;
...
}
In VB60, I can see the add_ and remove_ methods for it, but cannot for the life of me bind, call or utilize this from within my C++ .NET dll. Any examples or insights would be greatly appreciated.
Also, unrelated, but what's the deal with C++ COM Interop and Boolean type In order for return values of Boolean, I've had to manually marshal these for VB6.0 to see them AS Booleans, example
[returnvalue:MarshalAs( UnmanagedType::VariantBool ) ]
Boolean myBooleanFunction( ... );
Not an issue but unsure if I'm just doing something wrong as all other CLR types automatically marshal beautifully and seamlessly (so far..).
Thanks in advance.

Events with COM Interop & VB6.0 for C++
Richard87
I found my issue- in C++, I need to refer to the ComSourceInterface in long name (namespaceDOTInterface), compared to everywhere else needing ::.
So, the sink to class to make this work is:
[ComSourceInterfaces("MyNamespace.ButtonEvents")]
In the above example.
Thanks again to all for the direction!
kubmg
PeteJM01
On the events issue- what I'm running into with C++ is there seems to be a cart-before-the-horse issue with the ComSourceInterfaces in C++ that I'm unable to figure out.
If we create a very simplistic/C# converted example such as:
-------------------------------------------------------------------------
#pragma once
#include "stdafx.h"
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime;
using namespace System::Runtime::InteropServices;
using namespace System::Runtime::CompilerServices;
using namespace System::ComponentModel;
using namespace System::Diagnostics;
using namespace System::Reflection;
using namespace System::Resources;
namespace MyNameSpace {
public delegate void ClickDelegate(int x, int y);
// Event sink interface (ButtonEvents)
[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ]
[InterfaceTypeAttribute(ComInterfaceType::InterfaceIsIDispatch)]
public interface class ButtonEvents
{
// Note, also tried a distinct ID such as: [DispIdAttribute(0x60020000)]
void Click(int x, int y);
};
// Connects event sink to class
// HERE is the problem:
// Tried:
// [ClassInterface(ClassInterfaceType::None),ComSourceInterfaces(__typeof(ButtonEvents))]
// [ComSourceInterfaces("ButtonEvents")]
// [ClassInterface(ClassInterfaceType::None), ComSourceInterfaces(Type::GetType(ButtonEvents))]
// [ClassInterface(ClassInterfaceType::None), ComSourceInterfaces("ButtonEvents")]
// [ComSourceInterfaces(Type::GetType("ButtonEvents"))]
// etc.etc.
// Cannot RegAsm correctly as C++ seems to want the interface instantiated before sinking
public ref class Button
{
public:
event ClickDelegate ^Click;
Button() {}
void CauseClickEvent(int x, int y)
{
Click(x, y);
}
}; // end class
} // end namespace
-------------------------------------------------------------------------
How can one in C++ connect the event to a class
Alvin Kuiper
Not for VS 2005 C++ but Adam Nathan's book .NET and COM: The Complte Interoperability Guide is always useful. http://www.samspublishing.com/title/067232170X
I think the problem is that you've got the .NET event model implemented (Delegate with add and remove methods) when what you want to implement is the COM event model (IConnectionPointContainer, IConnectionPoint, etc) which is what Visual Basic 6.0 WithEvents is expecting.
The COMSourceInterfacesAttribute class can be used to get COM Interop to implement IConnectionPointContainer et al. I can't find a C++ sample but perhaps the VB and C# sample here might help. http://msdn.microsoft.com/library/en-us/cpguide/html/cpconraisingeventshandledbycomsink.asp
It isn't really an Interop problem, pure COM suffers from the same difficulty. Visual Basic uses a variant of type boolean to represent true and false and uses -1 (all bits on) to represent true and 0 (all bits off) to represent false. But really (if memory serves) Visual Basic treats any value other than -1 as false. Most of the rest of the Win32 world uses 0 to mean false and any other value to mean true.
Thus, when writing the IDL description of a COM interface you have to specify if a parameter or return value is of type 'bool' or type VARIANT_BOOL. Interop just has to go along with that and so it also has two types: UnmanagedType.Bool and UnmanagedType.VariantBool.