ocx添加方法
类视图 最后面的XXXXXlib 右键 添加 添加方法。
其它默认
添加事件
类视图 最后面的XXXXX 右键 添加 添加事件。
这样编译就ocx可以了。
#include <iostream>
#include <string>
#include <comutil.h>
CMFCActiveXControlSmartPosCtrl* pWnd;
BSTR ConvertUnicodeCharToBSTR(const char* input) {
// 计算字符串的长度(不包括终止空字符)
int inputLength = strlen(input);
// 计算需要的宽字符数目
int wideCharCount = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
// 使用SysAllocStringLen分配一个BSTR
BSTR bstr = SysAllocStringLen(NULL, wideCharCount);
// 将char*的Unicode内容复制到BSTR中
MultiByteToWideChar(CP_UTF8, 0, input, -1, bstr, wideCharCount);
return bstr;
}
// CMFCActiveXControlSmartPosCtrl 消息处理程序
BSTR CMFCActiveXControlSmartPosCtrl::OCX_GetDllVersion()
{
//AFX_MANAGE_STATE(AfxGetStaticModuleState());
PrintLog("OCX_GetDllVersion");
char version[10] = { 0 };
GetDllVersion(version);
PrintLog("GetDllVersion = %s", version);
return ConvertUnicodeCharToBSTR(version);
}
BSTR CMFCActiveXControlSmartPosCtrl::CommPosProcess(BSTR b)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString result = _T("Hello! OCX OK");
return result.AllocSysString();
}
void Callback(int code, const char* info) {
// 处理回调函数的逻辑
// 这里可以添加具体的回调处理代码
//do something
PrintLog("Callback code: %d, info: %s", code, info);
pWnd->OCX_Callback(code, ConvertUnicodeCharToBSTR(info));//回调html
}
HRESULT CMFCActiveXControlSmartPosCtrl::OCX_Purchase(long amount, BSTR orderNo) {
AFX_MANAGE_STATE(AfxGetStaticModuleState());
PrintLog("OCX_Purchase");
// 将BSTR转换为char*
_bstr_t bstr(orderNo);
const char* orderNoStr = static_cast<const char*>(bstr);
// 调用DLL接口
Purchase(amount, orderNoStr, Callback);//回调
PrintLog("OCX_Purchase OK");
return S_OK;
}
LONG CMFCActiveXControlSmartPosCtrl::OCX_DisConnectDevice()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此处添加分派处理程序代码
PrintLog("OCX_DisConnectDevice");
return DisConnectDevice();
}
LONG CMFCActiveXControlSmartPosCtrl::OCX_ListDevice(BSTR deviceNameList, VARIANT & deviceNameLen)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// 将BSTR转换为char*
_bstr_t bstr(deviceNameList);
char* deviceNameListStr = static_cast<char*>(bstr);
// 调用DLL接口
ListDevice(deviceNameListStr, &deviceNameLen.intVal);
PrintLog("OCX_ListDevice OK");
return 0;
}
HRESULT CMFCActiveXControlSmartPosCtrl::OCX_ConnectDevice(BSTR deviceName)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此处添加分派处理程序代码
// 将BSTR转换为char*
_bstr_t bstr(deviceName);
char* deviceNameStr = static_cast<char*>(bstr);
// 调用DLL接口
ConnectDevice(deviceNameStr, Callback);
PrintLog("OCX_ConnectDevice OK");
return S_OK;
}
HTML编写与调试
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <!-- gb2312 -->
<title>Test</title>
<body>
<!--clsid : 如果控件成功注册到本机后,这个值在本机注册表中可以找到,js获取控件对象就是通过这个来找的。
<script type="text/javascript">
var _app = navigator.appName;
if (_app == 'Netscape') {
document.write('<OBJECT name="ocxobject" ID="ocxobject" WIDTH="0" HEIGHT="0"',
'TYPE="application/x-itst-activex"',
'clsid="{D90F26D2-1FBC-4BC6-9722-393D338E6A68}"',
'> </OBJECT>');
} else if (_app == 'Microsoft Internet Explorer') {
document.write('<OBJECT name="ocxobject" ID="ocxobject" WIDTH="0" HEIGHT="0"',
'CLASSID="CLSID:D90F26D2-1FBC-4BC6-9722-393D338E6A68"',
'> </OBJECT>');
} else {
document.write('<p>Sorry, unsupported browser.</p>');
}
</script>-->
<p>
<input type="button" value="清空" onclick="clearBtn()" />
<input type="button" value="BankTrans" onclick="BankTrans()" />
</p>
<p><textarea id="S1" rows="3" cols="120" ></textarea></p>
<p><textarea id="S2" rows="3" cols="120" ></textarea></p>
<p><textarea id="S3" rows="3" cols="120" ></textarea></p>
<object id="myOCX" classid="clsid:D90F26D2-1FBC-4BC6-9722-393D338E6A68"> </object>
<script LANGUAGE=javascript FOR=myOCX EVENT=OCX_Callback(code,info)>
//alert(code+info); //回调响应
document.getElementById("S3").value="Code: " + code+" Info: " + info;
</script>
<script type="text/javascript" language="javascript">
function BankTrans() {
//测试ocx
var ocx = document.getElementById("myOCX");
try {
var result = ocx.CommPosProcess("123");
document.getElementById("S1").value = result;
} catch (error) {
document.getElementById("S1").value = error;
}
//测试ocx调用dll
try {
var result = ocx.OCX_GetDllVersion();
document.getElementById("S2").value = result;
} catch (error) {
document.getElementById("S2").value = error;
}
//测试回调
try {
var result = ocx.OCX_Purchase(1,"123456");
//document.getElementById("S3").value = result;
} catch (error) {
document.getElementById("S3").value = error;
}
}
</script>
</body>
</html>
已经都成功了。方法(html调用ocx方法),事件(ocx触发回调html方法) 。
中间要注意的一些问题。
ocx只支持IE。windows11要edge要切换到ie模式。
如果dll找不到,调试的时候发现的,具体看ocx的日志,比如Loadlibrary时报126就是没找到dll,报193是dll是平台不一致 比如win32。win11 dll的路径最好写能绝对路径。
注册dll时就报缺少dll模块时:这可能是dll用lib加载的,不是动态Loadlibrary加载的。把相关的dll放在当前目录并复制到system32下。最好用个windows demo先试下,ok后再用ocx来调用。
报 Internet Explorer 已经为了帮助保护你的计算机而关闭此网页 也是没找到dll.
注册输出 选否。用手工注册即可。
::注册32位ocx 请用管理员运行
cd /d "%~dp0"
regsvr32 MFCActiveXControl1.ocx
::pause
::::注册64位ocx 请用管理员运行 注册一个 64 位的 OCX 文件(ActiveX 控件)需要使用 regsvr32 的 64 位版本 regsvr32.exe 来进行注册。
::cd C:\Windows\System32
::
::SET ocxPath=%~dp0MFCActiveXControl1.ocx
::regsvr32.exe /u %ocxPath%
所有与c++类型相对应的ocx类型
OCX(ActiveX 控件)通常在 Windows 平台上使用 COM(Component Object Model)来定义接口和类型。以下是一些常见的 C++ 类型与它们在 COM/OCX 中的等效类型:
-
int
/long
: 在 COM 中,等效的类型是long
. -
float
: 在 COM 中,等效的类型是float
. -
double
: 在 COM 中,等效的类型是double
. -
char
/unsigned char
: 在 COM 中,等效的类型是BSTR
(宽字符字符串)。 -
const char*
/char*
: 在 COM 中,等效的类型是BSTR
(宽字符字符串),或者可以使用VARIANT
结构的VT_BSTR
类型。 -
bool
: 在 COM 中,等效的类型是VARIANT_BOOL
,其中VARIANT_TRUE
表示true
,VARIANT_FALSE
表示false
。 -
wchar_t
/LPCWSTR
: 在 COM 中,等效的类型是BSTR
(宽字符字符串)。 -
const wchar_t* / wchar_t*
: 在 COM 中,等效的类型是BSTR
(宽字符字符串)。 -
char[]
: 在 COM 中,等效的类型是BSTR
(宽字符字符串)。 -
std::string
: 在 COM 中,等效的类型是BSTR
(宽字符字符串),或者可以使用VARIANT
结构的VT_BSTR
类型。 -
std::wstring
: 在 COM 中,等效的类型是BSTR
(宽字符字符串)。 -
指针类型: 指针类型在 COM 中可能对应到
IDispatch*
(用于接口)、IUnknown*
(用于接口)等接口指针。 -
自定义结构体和类: 在 COM 中,通常需要为自定义数据结构创建 COM 接口,并使用接口中的属性和方法来传递数据。
需要注意的是,COM 是一种基于二进制标准的技术,因此涉及数据类型的互操作性时,数据通常需要进行序列化和反序列化。上述类型的映射通常是针对参数传递和交互的一般规则,具体规则可能因 COM 接口定义和编程语言而异。