Recently, I needed to make an ActiveX component in C++ to be used in my C# .NET program. However, I could not find any useful tutorial which could guide me through the dark world of C++ MFC. I started to do some investigation on how things work in C++/MFC and how C# reacts to importing an ActiveX component. If you like to know how to program in C++ or use the MFC library, then stop reading this tutorial. This tutorial is just a guide on how to create a decent ActiveX component that .NET environment can easily convert.
More information about ActiveX can be found here.
Prepare your ActiveX
The first step we need to do is create the C++ MFC project:
Give the project a name, and click on "OK", and later on "Finish". The funny thing about ActiveX is that you haven't yet coded anything, but the project is already filled with a lot of code. The ActiveX project uses MFC in a shared DLL. Change it into Static Library. Open the properties of the project, and change the "Use MFC" option into "Use MFC in a Static Library".
So, why is this step required? Registering the ActiveX component on a different machine where no Visual Studio has been installed will fail. The ActiveX component will miss the MFC DLLs. If this is not clear yet, just play around with the Depends.Exe located here: C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin.
The ActiveX project creates five header files and six source files. These header/source files are required for this part:
First, create a method in the CppActiveXCtrl.h file, just where the
AboutBox method is declared.
afx_msg void AboutBox();
afx_msg LONG TestMyMethod( LONG param1, LONG param2, BSTR param3 );
Create the method in the source file of this header. Return some value (it's just an example).
LONG CCppActiveXCtrl::TestMyMethod( LONG param1, LONG param2, BSTR param3 )
Every input method which could be used must have a unique identifier. So, create some unique identifiers. Be careful not to use Windows IDs which are declared in olectl.h.
const in the header files CppActiveXCtrl.h and CppActiveX.idl [Note: you can also make a global ID for this (just whatever you like)]:
static const int DISPID_TEST_METHOD = 1025314;
or (select any style you like):
#define DISPID_TEST_METHOD (1025314)
Go to CppActiveX.idl and implement the following code in the
dispinterface of the ActiveX. You can also find the
AboutBox method here. Use the ID for your method as declared before. Every method should have its unique identifier.
[id(DISPID_ABOUTBOX)] void AboutBox();
[id(DISPID_TEST_METHOD)] LONG TestMyMethod(LONG param1,
LONG param2, BSTR param3);
Go back to the CppActiveXCtrl.cpp file. Go to the Dispatch map part of this file. Add the following for your
TestMyMethod. See this example:
DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
VT_I4, VTS_I4 VTS_I4 VTS_BSTR)
Note: make sure you use the correct type of input. Otherwise, this could lead to some nasty exceptions.
OK, one method and one event should make it clear. Go to the Class View of Visual Studio, and select CCppActiveXCtrl. Hover on Add, and add this event:
Add the following event with some default parameters. Just pick some....
Now, compile the project.
Prepare your .NET project
Create a C# "Windows Application" project. I'm not going to explain how to create a C# .NET project here.
During the compilation of the ActiveX project, the ActiveX component "ocx" file will be registered automatically. If not, use the command line:
regsvr32 /i CppActiveX.ocx
Select the main form, and with the right mouse button, add an item.
Select the COM components, and find the CppActiveX control. Press "OK" to add it to the toolbox.
Drag the added ActiveX control to your form. Note: if you change the input methods for your ActiveX project, make sure you delete the obj directory as well as the bin directory.
Here is an example of the code when using the OCX file:
int k = axCppActiveX1.TestMyMthod(4,4,"Hi");
private void axCppActiveX1_EventHandlerTest( object sender,
_DCppActiveXEvents_EventHandlerTestEvent e )
int age = e.age;
string name = e.name;
string surname = e.surname;