Click here to Skip to main content
15,887,683 members
Articles / Programming Languages / C#
Tip/Trick

Easy Way to Call a Native COM Method which has a Parameter of type: HWND from C# code

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
13 Jul 2014CPOL2 min read 10.1K   4  
Easy way to call a native COM method which has a parameter of type: HWND from C# code

Introduction

Recently I encountered an issue with calling a COM method, which has an in parameter of type HWND, from a managed code.

When I add a reference to the appropriate tlb file, in order to call the COM method, I’ve seen in the object browser that the parameters type is: ref MyComLib._RemotableHandle.

Searching for the RemotableHandle type in MSDN, I (eventually) came across this page: http://msdn.microsoft.com/en-us/library/accessibility._remotablehandle.aspx, where it says: “This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.”

This does make me wonder why this is the type we get in the tlb file.

After trying to search for a solution on how to use this structure, I came across many confusing posts.

That is why I decided to write this short tip, to show a quick and easy way to go around this issue.

Basically the solution I have found is to redefine the interface in your managed code, and instead of the RemotableHandle just pass IntPtr.

Code Example

The code example was created using Visual Studio 2012.

Start an ATL project and add a simple ATL object called: CwindowCloser and give it a progid: MyWindowCloser.

Add to it a method called CloseWindow with an input parameter of type HWND.

C++
[
       object,
       uuid(7B7E1B3D-4E0D-4DF9-B374-5FC5376CAF66),
       dual,
       nonextensible,
       pointer_default(unique)
]

interface IwindowCloser : IDispatch{
       [id(1)] HRESULT CloseWindow([in] HWND wndHandle);
};

Implement the method by calling DestroyWindow on the HWND.

C++
STDMETHODIMP CwindowCloser::CloseWindow(HWND wndHandle)
{      
       DestroyWindow(wndHandle);
       return S_OK;
}

Compile the project, which will create the tlb file and register the COM class.

Start a new WindowsForm project and add a reference to the tlb file.

Write the following code in the Program.cs:

C#
[STAThread]
static void Main()
{
    var myForm = new Form1();
    myForm.Show();

    var serverType = Type.GetTypeFromProgID("MyWindowCloser");
    var comServer = (IwindowCloser)Activator.CreateInstance(serverType);

    comServer.CloseWindow(

Check out the intellisense of the CloseWindow method and see that it expects <code>ref _RemotableHandler type.

Add the following code outside the Program class (note that the GUID matches the uuid of the interface):

C#
[Guid("7B7E1B3D-4E0D-4DF9-B374-5FC5376CAF66")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[ComImport]
public interface IwindowCloser
{
    void CloseWindow([In] IntPtr hwnd);
}

Now the CloseWindow method will accept an IntPtr type.

Pass the HWND of the Form1 to the CloseWindow:

C#
comServer.CloseWindow(myForm.Handle);

Now you can execute the code, the native method should be invoked and close the form.

And that's it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --