Background:
Compiler: MSDEV10
Projects 64BIT
Target: WIN7/8
Language: C++
Fameworks: ATL

I have an existing code base which is all ATL which needs to use a third party C# Assembly component . We cannot use Common Language Runtime in the solution. The given assembly has not been designed for COM in mind, and therefore when you create a TLB for the assembly the GUIDS's are dynamic all the time and half of the methods don't exported because they have not been explictly declared as COMVisible in C#. We cannot disassemble this assembly and provide the hardcoded GUID's ourselves.

Assembly information:
This is a thrid party control which does some advanced grphaics manipulation - and we just need accesss to the HWND and some other business logic functions. However, the HWnd is the key one.

Current implmentation:
Create a C# library that is COM designed. Within this library we inherit from the third party control as well as our own interface which will essentially act as a wrapper around our component.
This library will then be made COMVisible from the assembly configuration of the project. RegAsm will then be used to create a TLB from this library and sibsequently register the TLB.
Our ATL component will then import this TLB, grab the handle of the from the interface then subclass it within the ATL component.

What ideally I would like to know:

1) Is the current implementation complelty wrong / going around the houses, etc. Please bare in mind that the consuming application code can only be in ATL C++. This cannot be changed.

2) The best way to display the Hwnd obtained from the C# component within an ATL COM control. The method I am using does not seem to be correct. I would like to know what is the best way to achieve this.

Sample Code:

User Control:

Code:
namespace CSharpControl
{
    public partial class CSharpControl : UserControl
    {
        public CSharpControl()
        {
            InitializeComponent();
        }
    }
}
User Control Wrapper:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using CSharpControl;

namespace CSharpControlWrapper
{
    [Guid("0AFABFC6-B85F-4874-968D-21C3391D3678")]
    public interface IControl
    {
        IntPtr GetHandle();
    }

    [Guid("CAE265D7-BA4D-4E04-9E93-7583C0B69261"), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IControl))]
    public class CSharpControlWrapper : CSharpControl.CSharpControl, IControl
    {
        public IntPtr GetHandle()
        {
            return this.Handle;
        }
    }
}
The ATL control is configured in the following:

Name:  ATL1.png
Views: 176
Size:  19.5 KB

I selected a windowed control based on a static control type:

Name:  ATL2.png
Views: 185
Size:  20.5 KB

The ATL COM class is quite large so will include the key bits - the #import of the library

Code:
#import "C:\Users\Documents\Visual Studio 2010\Projects\ControlSample\CSharpControlWrapper\bin\x64\Debug\CSharpControlWrapper.tlb"
struct __declspec(uuid("cae265d7-ba4d-4e04-9e93-7583c0b69261")) LIBID_CSharpControl;
Now the best way I thought to try and get the hwnd to paint itself correctly, would be to subclass the contained window that the ATL wizard generated for you. Here is the code:

Code:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	RECT rc;
	GetWindowRect(&rc);
	rc.right -= rc.left;
	rc.bottom -= rc.top;
	rc.top = rc.left = 0;

		
	m_ctrl.CreateInstance(__uuidof(LIBID_CSharpControl));
		
	//get our control handle and subclass it
	__int64 handle = m_ctrl->GetHandle();
	HWND hWnd = (HWND)handle;

	m_ctlStatic.Create(hWnd, rc);
	m_ctlStatic.SubclassWindow(hWnd);

	return 0;
}
However, when you run a basic MFC dialog application that consumes this ATL control it just looks like this:

Name:  MFC1.png
Views: 129
Size:  5.4 KB

I then changed the code, and did this:

Code:
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	RECT rc;
	GetWindowRect(&rc);
	rc.right -= rc.left;
	rc.bottom -= rc.top;
	rc.top = rc.left = 0;

	m_ctrl.CreateInstance(__uuidof(LIBID_CSharpControl));
		
	__int64 handle = m_ctrl->GetHandle();
	HWND hWnd = (HWND)handle;

	::SetParent(hWnd, m_hWnd);
	return 0;
}
It then displays the user control correctly:

Name:  MFC2.png
Views: 117
Size:  6.1 KB

The SetParent code is horrible, and can't be the best way of doing this. Please let me know your thoughts on this.

Thank you.