Hi. There.
I created a simple C ++ ocx file, and created an HTML file to validate ocx.
I confirmed that ocx was successfully registered in the registry and confirmed that ocx was normally invoked in the test HTML to launch the AfxMessageBox().
However, I wanted to call ocx directly in C #.
To implement the ocx call, I looked up the marshaling technique in Google and wrote C # code that calls ocx through marshaling.
As a result, ocx has not been called, and there is no way to determine if this is a C ++ ocx code problem or a C # code problem.
I found a way to solve this problem over two weeks, but I could not solve it.
I would like to get help to solve these problems.
What I have tried:
The process I followed to create ocx is as follows.
1. Create an "MFC ActiveX control" project in Visual Studio 2015.
2. I modified the Ctrl.cpp, Ctrl.h, and .idl files that are automatically generated.
- ActiveXTest4_NonCtrl.cpp
BEGIN_DISPATCH_MAP(CActiveXTest4_NonCtrl, COleControl)
DISP_FUNCTION_ID(CActiveXTest4_NonCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
DISP_FUNCTION_ID(CLinkCtrl, "TestFunction", dispidTestFunction,TestFunction, VT_I4, VTS_I4 VTS_I4)
END_DISPATCH_MAP()
.....
void CActiveXTest4_NonCtrl::AboutBox()
{
CDialogEx dlgAbout(IDD_ABOUTBOX_ACTIVEXTEST4_NON);
dlgAbout.DoModal();
}
int CActiveXTest4_NonCtrl::TestFunction(int Parameter1, int Parameter2){
CString str;
str.Format(_T("%d"), Parameter1 + Parameter2);
AfxMessageBox(str);
return 1;
}
- ActiveXTest4_Non.idl
importlib(STDOLE_TLB);
[
uuid(3C788A60-2A80-45E8-8845-FE460E779EC7)
]
dispinterface _DActiveXTest4_Non
{
properties:
methods:
[id(DISPID_ABOUTBOX)] void AboutBox();
[id(1)] int TestFunction(int Parameter1, int Parameter2);
};
- ActiveXTest4_NonCtrl.h
class CActiveXTest4_NonCtrl : public COleControl
{
DECLARE_DYNCREATE(CActiveXTest4_NonCtrl)
public:
CActiveXTest4_NonCtrl();
public:
virtual void OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid);
virtual void DoPropExchange(CPropExchange* pPX);
virtual void OnResetState();
protected:
~CActiveXTest4_NonCtrl();
DECLARE_OLECREATE_EX(CActiveXTest4_NonCtrl) DECLARE_OLETYPELIB(CActiveXTest4_NonCtrl) DECLARE_PROPPAGEIDS(CActiveXTest4_NonCtrl) DECLARE_OLECTLTYPE(CActiveXTest4_NonCtrl)
DECLARE_MESSAGE_MAP()
DECLARE_DISPATCH_MAP()
afx_msg void AboutBox();
afx_msg int TestFunction(int Parameter1, int Parameter2);
DECLARE_EVENT_MAP()
public:
enum {
dispidTestFunction = 1L,
};
};
3. I have built a modified file.
4. The ocx file has been created and has been successfully registered in the registry.
5. I wrote the test html file.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> Test Document </TITLE>
</HEAD>
<BODY>
TEST
<OBJECT ID="Test" CLASSID="clsid:5CDEAFC2-43EE-48BC-8052-3895514CD062" width="0" height="0"></OBJECT>
<script>
var str = document.Test.TestFunction(5, 2);
</script>
</BODY>
</HTML>
6. I confirmed that ocx is executed normally in html.
7. I created a C # console project to test it in C #.
8. I used marshaling to load ocx in C #, and the code that used marshaling is:
[ComVisible(true), ComImport,
Guid("5CDEAFC2-43EE-48BC-8052-3895514CD062"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMarshal
{
[DispId(1)]
int TestFunction(int param1, int param2);
}
private static void MarshalTest()
{
Type typeofMarshal = Type.GetTypeFromProgID("ACTIVEXTEST4_NON.ActiveXTest4_NonCtrl.1");
if (typeofMarshal == null) return;
var objMashal = Activator.CreateInstance(typeofMarshal);
IMarshal iMarshal = (IMarshal)objMashal;
if (iMarshal == null) return;
int retVal = iMarshal.TestFunction(1, 2);
}
My development environment is as follows.
ocx Project to create: VS2015 C ++
Project called ocx: VS2015, .NETFramework 4.5, C #
Generated ocx information
- clsId = "5CDEAFC2-43EE-48BC-8052-3895514CD062"
- progId = "ACTIVEXTEST4_NON.ActiveXTest4_NonCtrl.1"
How to call: Marshal