Using .Net (C#) ActiveX control within Builder 2009 (C++)

Hi,
We are moving one of our applications from Borland C++ Builder 4.5 to the latest builder 2009. There is also an activeX control in our application (Formule One spreadsheet) which is causing problems in this migration. As this control doesn't cover all our future needs, we are thinking about creating our own gridcontrol to use.
So I've been playing around and created an example control in .Net and exposed it as a COM object. When I try to add it to my C++ sample project, (Import component and create new package) and compile this package, I get the following error:
[BCC32 Error] GridControl_OCX.h(120): E2113 Virtual function '_fastcall TGridControl::GetHashCode()' conflicts with base class 'TObject'.
So made an even simplier activex control (copied from a website example), which is working fine when I use it in a C++ (MFC) project in Visual Studio, but I can't get it to work in CB2009. 
This is the code from the activex component:
using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32;
using System.Reflection;

namespace Tester
{
    [Guid("D6F88E95-8A27-4ae6-B6DE-0542A0FC7039")]
    public interface _Numbers
    {
        [DispId(1)]
        int GetDay();
        [DispId(2)]
        int GetMonth();
        [DispId(3)]
        int GetYear();
        [DispId(4)]
        int DayOfYear();
    }
    [Guid("13FE32AD-4BF8-495f-AB4D-6C61BD463EA4")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ProgId("Tester.Numbers")]
    public class Numbers : _Numbers
    {
        public Numbers()
        {
            
        }
        public int GetDay()
        {
            return (DateTime.Today.Day);
        }
        public int GetMonth()
        {
            return (DateTime.Today.Month);
        }
        public int GetYear()
        {
            return (DateTime.Today.Year);
        }
        public int DayOfYear()
        {
            return (DateTime.Now.DayOfYear);
        }
        ///     <summary>
        ///     Register the class as a control and     set     it's CodeBase entry
        ///     </summary>
        ///     <param name="key">The registry key of the control</param>
        [ComRegisterFunction()]
        public static void RegisterClass(string key)
        {
            // Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
            StringBuilder sb = new StringBuilder(key);
            sb.Replace(@"HKEY_CLASSES_ROOT\", "");
            // Open the CLSID\{guid} key for write access
            RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
            // And create       the     'Control' key - this allows     it to show up in
            // the ActiveX control container
            RegistryKey ctrl = k.CreateSubKey("Control");
            ctrl.Close();
            // Next create the CodeBase entry   - needed if     not     string named and GACced.
            RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
            inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);
            inprocServer32.Close();
            // Finally close the main   key
            k.Close();
        }
        ///     <summary>
        ///     Called to unregister the control
        ///     </summary>
        ///     <param name="key">Tke registry key</param>
        [ComUnregisterFunction()]
        public static void UnregisterClass(string key)
        {
            StringBuilder sb = new StringBuilder(key);
            sb.Replace(@"HKEY_CLASSES_ROOT\", "");
            // Open     HKCR\CLSID\{guid} for write     access
            RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
            // Delete the 'Control'     key, but don't throw an     exception if it does not exist
            k.DeleteSubKey("Control", false);
            // Next     open up InprocServer32
            RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
            // And delete the CodeBase key,     again not throwing if missing
            k.DeleteSubKey("CodeBase", false);
            // Finally close the main key
            k.Close();
        }
    }
}
Importing this in my 2009 project and build it, then I get the following error:
[BCC32 Error] Tester_OCX.h(120): E2113 Virtual function '_fastcall TNumbers::GetHashCode()' conflicts with base class 'TObject'
So... Isn't it possible to use an ActiveX control from .Net?? Or am I doing something wrong when inserting this control?
Thanks in advance,
Rutger
0
Rutger
3/26/2009 8:38:47 AM
📁 embarcadero.cppbuilder.activex
📃 257 articles.
⭐ 0 followers.

💬 5 Replies
👁️‍🗨️ 1579 Views


<Rutger Kars> wrote in message news:97159@forums.codegear.com...
> So I've been playing around and created an example control in .Net
> and exposed it as a COM object. When I try to add it to my C++
> sample project, (Import component and create new package) and
> compile this package, I get the following error:
> [BCC32 Error] GridControl_OCX.h(120): E2113 Virtual function
> '_fastcall TGridControl::GetHashCode()' conflicts with base class 
> 'TObject'.
..NET objects have Equals(), GetHashCode() and ToString() methods that are 
inherited from System.Object.  In 2009, the VCL's TObject class has new 
Equals(), GetHashCode() and ToString() methods that were introduced to 
mirror the .NET methods.  When you import an ActiveX control, a VCL wrapper 
is generated for it.  The TObject methods are conflicting with the .NET 
methods.  The importer has no way of knowing that the ActiveX control 
belongs to .NET so it can ignore the conflicting methods.
In your .NET class, you can try applying the ComVisible(false) attribute to 
those three methods so they are not exported to ActiveX.
-- 
Remy Lebeau (TeamB)
0
Remy
3/26/2009 5:34:53 PM
Thanks for your help! I already did found a way so those methods weren't in my exposed activeX. It's working now
0
Rutger
3/31/2009 8:56:01 AM
> {quote:title=Rutger Kars wrote:}{quote}
> Thanks for your help! I already did found a way so those methods weren't in my exposed activeX. It's working now
Could you explain how you did it?
0
Elena
5/6/2009 8:22:25 AM
> {quote:title=Elena Zamaraeva wrote:}{quote}
> > {quote:title=Rutger Kars wrote:}{quote}
> > Thanks for your help! I already did found a way so those methods weren't in my exposed activeX. It's working now
> 
> Could you explain how you did it?
Sorry for the late respone.
It can be achieved by adding [ClassInterface(ClassInterfaceType.None)] to your class definition, so only your explicit exposed methods are shown
0
Rutger
7/21/2009 9:30:39 AM
> {quote:title=Rutger Kars wrote:}{quote}
> > {quote:title=Elena Zamaraeva wrote:}{quote}
> > > {quote:title=Rutger Kars wrote:}{quote}
> > > Thanks for your help! I already did found a way so those methods weren't in my exposed activeX. It's working now
> > 
> > Could you explain how you did it?
> Sorry for the late respone.
> 
> It can be achieved by adding [ClassInterface(ClassInterfaceType.None)] to your class definition, so only your explicit exposed methods are shown
I compiled the code you submitted, registerd the dll by regasm, created a setup project (VS2005) to install the activex and all went fine; when I try to import the component in Delphi 2010 I can't see the activex in registered activex controls list. What I'm doing wrong? Thank you.
0
daniele
9/1/2009 8:35:20 AM
Reply: