MFC建立OCX控件
新建一个MFC ActiveX控件

一直点下一步,完成

在类视图可以看到系统创建了三个类CtestOcxApp、CtestOcxCtrl、CtestOcxPropPage、和一个接口testOcxLib

在控件的OnDraw函数里面,简单的绘制一个背景
void CtestOcxCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return;
// TODO: 用您自己的绘图代码替换下面的代码。
CRect rect;
GetClientRect(rect);
COLORREF clr = RGB(74, 65, 42);
pdc->FillSolidRect(1,1,300,300, clr);
}
添加WM_CREATE消息处理函数,在创建时添加一个按钮
int CtestOcxCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
CButton *MyBtn = new CButton();
MyBtn->Create(L"button11", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(50, 50, 180, 120), this, 10001);
return 0;
}
添加一个按钮消息响应函数
声明
实现
建立消息映射
// 消息映射
BEGIN_MESSAGE_MAP(CtestOcxCtrl, COleControl)
ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
ON_WM_CREATE()
ON_BN_CLICKED(10001, OnMyBtnClicked)//按钮ID与函数的消息映射
END_MESSAGE_MAP()
现在按F7生成解决方案。可能会有提示
error PRJ0050: 未能注册输出。请确保您有修改注册表的相应权限。
是因为没有管理员权限(UAC)导致,并不影响,之后手动注册ocx控件就行了
注册OCX控件与反注册
搜索cmd,右键管理员身份运行
输入下面的命令注册OCX控件
regsvr32.exe "D:\ProjectSpace\Visual Studio 2005\testOcx\debug\testOcx.ocx"
输入下面的命令反注册OCX控件
regsvr32.exe /u "D:\ProjectSpace\Visual Studio 2005\testOcx\debug\testOcx.ocx"
其中的路径根据ocx路径修改
使用Internet Explorer测试ocx控件
ocx控件web端使用只能在ie浏览器中运行,编写下面的代码,保存成html格式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ocx调用演示</title>
</head>
<body>
<OBJECT id="MyOcxDemo" classid="clsid:E981DEB8-00E9-4FC7-B565-FBCC9FFC264C" width="300" height="300"></OBJECT>
</body>
</html>
width="300" height="300"表示控件大小
其中的classid在testOcx.idl里面,类信息里面的uuid
// CtestOcxCtrl 的类信息
[ uuid(E981DEB8-00E9-4FC7-B565-FBCC9FFC264C),
helpstring("testOcx Control"), control ]
coclass testOcx
{
[default] dispinterface _DtestOcx;
[default, source] dispinterface _DtestOcxEvents;
};
使用ie浏览器打开,会提示Internet Explorer已限制Activex控件,点击允许阻止的内容。就会显示OCX控件了,点击按钮会有弹出提示

OCX控件添加方法
在testOcxLib下面的_DtestOcx,右键,添加,添加方法

设置返回值类型,方法名,添加两个double类型的参数

点完成

实现该方法
DOUBLE CtestOcxCtrl::add_two_double(DOUBLE arg0, DOUBLE arg1)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// TODO: 在此添加调度处理程序代码
CString str;
str.Format(L"%lf+%lf=%lf",arg0,arg1,arg0+arg1);
AfxMessageBox(L"你调用了add_two_double:"+str);
return arg0 + arg1;
}
OCX控件添加事件
类视图里面,对于控件类CtestOcxCtrl,右键,添加,添加事件

可以选择预定义的事件,完成

之后再添加一个MouseMove事件
在_DtestOcxEvents中可以看到自己添加的事件

Web使用OCX控件
编辑html文件,显示OCX和调用里面的函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ocx调用演示</title>
<script>
function testOCX()
{
var myOcx=document.getElementById("MyOcxDemo");
if(myOcx){
alert("add_two_double(1,2)="+myOcx.add_two_double(1,2));
}
}
</script>
</head>
<body>
<OBJECT id="MyOcxDemo" classid="clsid:E981DEB8-00E9-4FC7-B565-FBCC9FFC264C" width="300" height="300"></OBJECT>
<button onclick="testOCX()">调用方法</button>
</body>
</html>

MFC使用OCX控件
建立OCX控件
新建一个mfc项目testOcxUse

在窗体上右键,添加ActiveX控件,可以看到注册后的ocx控件,选择自己建立的ocx控件

突然提示崩溃

因为只有在窗体创建完成后,才可以获得窗体句柄,而MFC控件要根据OnDraw显示窗体样式
之前的OnDraw函数
void CtestOcxCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return;
// TODO: 用您自己的绘图代码替换下面的代码。
CRect rect;
GetClientRect(rect);
COLORREF clr = RGB(74, 65, 42);
pdc->FillSolidRect(1,1,300,300, clr);
}
直接调用了OnDraw的GetClientRect函数,由于没有创建窗体,GetClientRect获取窗体空句柄崩溃。
直接改变OnDraw函数
void CtestOcxCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return;
// TODO: 用您自己的绘图代码替换下面的代码。
HWND hAppWnd = NULL;
if (m_pInPlaceSite != NULL){
m_pInPlaceSite->GetWindow(&hAppWnd);
}
CRect rect;
::GetClientRect(hAppWnd, rect);
COLORREF clr = RGB(74, 65, 42);
pdc->FillSolidRect(rect, clr);
}
之后添加控件就没有了崩溃问题,但是并不会显示填充的背景颜色,因为并没有获取到窗体客户区范围。也没有显示按钮,因为按钮是动态建立的。
后来我发现,系统自带的方法在OnDraw是
void CaaaaaaaaaaCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return;
// TODO: 用您自己的绘图代码替换下面的代码。
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
}
OnDraw它的第二个参数rcBounds代表窗体区域,直接改成
void CtestOcxCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return;
// TODO: 用您自己的绘图代码替换下面的代码。
COLORREF clr = RGB(74, 65, 42);
pdc->FillSolidRect(rcBounds, clr);
}
就行了,直接显示了控件的背景色

点击运行,就可以了,点击按钮弹出消息提示

ocx控件添加变量
为了调用ocx控件的功能,需要为控件添加一个类成员变量。有两种办法
方式一:
点击项目,添加类,选择MFC,ActiveX控件中的MFC类

从可用的Activex控件中选择测试的ocx控件,选择左侧的接口,点击中间的>箭头,移到右边生成的类,点击完成

系统会自动生成CDtestOcx类,对应的头文件CDtestOcx.h、源文件CDtestOcx.cpp
在使用OCX控件的窗体类头文件中包含头文件
在窗体类中定义OCX控件变量
在窗体的DoDataExchange函数中建立变量与控件资源的数据交换,IDC_TESTOCXCTRL1是窗体OCX控件资源ID,m_testOcx是添加的变量
void CtestOcxUseDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TESTOCXCTRL1, m_testOcx);
}
添加变量完成了
方式二:
对于ocx控件右键,添加变量,起名字,点完成,系统会自动生成一个CTestocxctrl1的类。它的头文件是testocxctrl1.h,源文件testocxctrl1.cpp。自动用这个类在窗体类内创建成员变量、建立和控件的数据交换。这种办法更加的快捷简单

调用ocx的功能函数
在界面上添加一个按钮,点击它调用ocx的add_two_double功能
void CtestOcxUseDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
m_testOcx.add_two_double(1.0f, 2.0f);
}
之后运行

对ocx的事件响应
右键ocx控件,添加事件处理程序,可以看到之前添加的两个事件

对click消息进行处理
运行程序

OCX控件调试工具tstcon32.exe
加载ocx控件
使用tstcon32.exe调试OCX控件,它在VS安装文件夹下:
C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\Tools
点击编辑,插入新控件,可以找到已经注册的ocx控件

鼠标在控件上移动和点击,可以看到对已经添加事件的监听,click和mousemove

点击控件,调用方法,可以调用控件方法

使用tstcon32.exe调试ocx
VS2005中点击项目,属性,配置属性,调试,命令,设置ActiveX控件测试容器的的路径

直接点击调试按钮,会提示无法找到tstcon32.exe的调试信息,询问是否继续,不用管。点击是。

之后会弹出tstcon32程序,按照之前的步骤,添加控件,然后触发控件设置断点的地方,会自动运行到断点然后停住
这里我在弹出提示框的地方设置断点,然后点击按钮,在断点处停住了。

提示:
注意生成的OCX控件Debug版本和Release版本、位数要和使用的程序保持一致