可以开发 MFC ActiveX 控件作为自动化服务器,用来以编程方式将控件嵌入其他应用程序,并从应用程序调用控件中的方法。这样的控件仍可以在 ActiveX 控件容器中被承载。
创建控件作为自动化服务器
以编程方式访问自动化服务器中的方法
- 创建应用程序,例如 MFC exe。
- 在 InitInstance 函数的开始处添加下列代码行: 复制 AfxOleInit();
- 在“类视图”中右击项目节点,并选择“从类型库添加类”以导入类型库。
此操作将文件扩展名为 .h 和 .cpp 的文件添加到项目。
- 在将要调用 ActiveX 控件中的一个或多个方法的类的头文件中添加此行:
#include filename.h
,其中的文件名为导入类型库时创建的头文件名。 - 在将要调用 ActiveX 控件中的方法的函数中,添加创建控件包装类的对象和创建 ActiveX 对象的代码。例如,下列 MFC 代码实例化
CtlTest
控件、调用 Multiply 方法并在单击对话框中的“确定”按钮时显示结果: void CMultiply::OnOK() {UpdateData(); // Get the current data from the dialog box. _DCtlTest test; // Create a wrapper class for the ActiveX object. COleException e; // In case of errors// Create the ActiveX object. // The name is the control's progid; look it up using OleViewif (test.CreateDispatch( "CTLTEST.CtlTestCtrl.1", &e )) {// call the Multiply method of your ActiveX object// get the result into m_product m_product = test.Multiply( m_a, m_b ); UpdateData( FALSE ); // Display the string in the dialog box. } else { // An error char buf[255]; e.GetErrorMessage( buf, sizeof( buf ) ); AfxMessageBox( buf ); // Display the error message. }}
如果在应用程序中使用 ActiveX 控件后将方法添加到 ActiveX 控件中,则可以通过删除在导入类型库时创建的文件,开始在应用程序中使用控件的最新版本。然后再次导入类型库。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+灾难性故障原因
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在其中一个 OLE 容器不支持控件的情况下包容,可能想要使用 OLE 控件作为自动化服务器来访问其属性和方法。这篇文
章解释了您需要 OLE 控件作为普通的自动化服务器以便进行必要的修改。
之前到 Visual c + + 4.0,OLE 控件可以用作自动化服务器而无需进行任何修改。然而,在 MFC 4.0,框架的实现的
IDispatch::Invoke 调用虚函数确定自动化服务器是否处于适当的状态来处理自动化 IsInvokeAllowed 调用。默认实现中
CCmdTarget::IsInvokeAllowed,返回真,暗服务器可以处理自动化呼叫。
在一个 OLE 控件的情况下 COleControl::IsInvokeAllowed 检查是否控件已被初始化或通过持久存储接口正确加载。如果该
控件中有适当的状态信息,则此函数返回 TRUE。创建 OLE 控件时为普通的自动化服务器,它不会创建为一个嵌入在客户
端中。因此的持久状态初始化任何会因此导致 IsInvokeAllowed 返回 FALSE 的地方。此操作的效果是自动化对象方法的调
用生成的 (8000ffff) 运行时错误:"灾难性失败"。
若要使用 OLE 控件只能作为自动化服务器,必须重写 COleControl::IsInvokeAllowed() 并返回 TRUE。如果任何控件的属
性和方法不应访问作为一个普通的自动化服务器调用时,然后该自动化函数可能会跳过并/或 COleControl::m_bInitialized
为 FALSE 时返回的错误代码。
BOOL CMyOleControl::IsInvokeAllowed (DISPID)
{
// You can check to see if COleControl::m_bInitialized is FALSE
// in your automation functions to limit access.
return TRUE;
}
VC MFC程序调用OCX的方法:
HRESULT hr = NULL;
IDispatch* pIDispatch = NULL;
wchar_t progid[] = L"MFCOCX.MfcocxCtrl.1"; //组件名
CLSID clsid;
hr = ::CLSIDFromProgID(progid, &clsid);
hr = ::CoInitialize(NULL);
_DMfc_ocx obj;
hr = obj.CreateDispatch("MFCOCX.MfcocxCtrl.1"); // 必需的
if(SUCCEEDED(hr))
{
int rv = obj.Add(1,2);
}