Here is the deal:

I have got quite old application which was written in VB 6 using some ActiveX Controls. My task is to perform some automatic test using Quick Test Pro, which doesn’t recognize those ActiveX controls, but it doesn’t matter.

What I want to attain is to get control over an another application ActiveX control using its window’s (control’s) handle. http://rotanes.pl/Project1.exe <- here is really simple application (requires VB 6 runtime) with a data grid (microsoft Data Grid Control 6.0, MSDATAGRID.OCX) and one button, which changes data grid height. I want to be able to do the same from, for example, .net application. Just pass the handle (I can take it from any spy software) and perform the action.

What I discovered:

This ActiveX grid implements some COM interfaces, which are defined in the same dll (ocx) file, just use OLE/COM Viewer and everything is visible. So I’ve spent more then one week trying (using .net and C#) grab this interface knowing only controls hwnd.

My attempts (I used to be a .net developer so I wrote everything in C#):

-> Implement interface _cGrid (which is the interface I would like to cast a COM as) by myself:

[ComImport, Guid("60E9A471-E4DF-4687-B419-15A644E8AD57]
public interface _cGrid
{…}

Or use the one generated by tlbimp.exe.

-> import some extern procedures:

[DllImport("oleacc.dll", PreserveSig = false)]
[return: MarshalAs(UnmanagedType.Interface)]
public static extern object AccessibleObjectFromWindow(IntPtr hwnd, uint dwId, ref Guid riid);

(I tried this import in several different manners, for example with UnmanagedType.IUnknonw, UnmanagedType.IDispatch, adding “out IntPtr ppvd“as the last parameter and changing returned value to int…)

[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

-> Dozens of tries to make everything working (unsuccessfully ):

_cGrid result = (_cGrid )InteropClass.AccessibleObjectFromWindow(handle, 0, ref ITypeInfoGuid); <- throws en exception “Invalid Cast”

InteropClass.AccessibleObjectFromWindow(handle, 0, ref ITypeInfoGuid, out _cGridPtr); <- after every statement execution _cGridPtr has different value and it is different from Marshal.GetIUnknownForObject(obj) (I had reference to the control for my learning purposes, but I won’t have). It sends single WM_GETOBJECT message to the control with 0xffffffff and 0x00000000 parameters (the second parameter referes to the second parameter of AccessibleObjectFromWindow procedure) which always returns different value (the subtraction of two sibling values equals 32, coincidence?)

Marshal.GetTypedObjectForIUnknown <- always throws “invalid cast exception” or something like this.

I would appreciate any (the simpler the better, prefereably c# by can be managed/unmanaged c++ or VB as well) example of code which works and can retrieve valid IUnknown pointer (or even cast pointer as interface) from ActiveX control knowing only its hwnd.

I found followiong links helpful:

[Some basis]
http://www.codeguru.com/csharp/cshar...cle.php/c9065/
http://www.clarionmag.com/cmag/v1/v1...ole_part1.html
http://www.codeproject.com/KB/COM/CO...scratch_1.aspx

[I think the same problem]
http://www.vbforums.com/archive/index.php/t-158336.html

[Hopeful links]
http://www.thescripts.com/forum/thread233284.html
http://msdn2.microsoft.com/en-us/lib...37(VS.85).aspx

Especially -> Clients call this function to retrieve the address of an object's IAccessible, IDispatch, IEnumVARIANT, IUnknown, or other supported interface pointer.

I originally posted this message on http://www.codeguru.com/forum/showthread.php?p=1700068
Thanks in advance.