编写程序有很长时间了,今天想做一下总结,主要是几个重要的技术。
一、 ActiveX相关
1.MFC中获得IE的接口指针
获得IE的接口指针包括获得浏览器的接口指针和文档的接口,可以通过接口操作web上的任何元素,可以在activex中调用web中的
JavaScript函数(单线程中),在多线程中通过发消息给activex控件,在消息处理函数中激发activex事件,把信息传递给web。
代码示例:
CManagerXCtrl.h文件
.........
public:
IWebBrowser2* m_browser;
IHTMLDocument2* m_spDoc;
protected:
void OnSetClientSite();
.................
CManagerXCtrl.cpp文件
void CManagerXCtrl::OnSetClientSite()
{
IOleClientSite* pClientSite = GetClientSite();
HRESULT hr = S_OK;
IServiceProvider *isp, *isp2 = NULL;//用于导航DHTML对象层次,作用就是提供服务
if (!pClientSite)
{
if(m_browser!=NULL)
{
m_browser->Release();
m_browser = NULL;
}
return;// !S_OK;
}
else
{
hr = pClientSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&isp));
if (FAILED(hr))
{
hr = S_OK;
goto cleanup;
}
hr = isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, reinterpret_cast<void **>(&isp2));
if (FAILED(hr))
{
hr = S_OK;
goto cleanup;
}
//获得浏览器
hr = isp->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, reinterpret_cast<void **>(&m_browser));
if (FAILED(hr))
{
hr = S_OK;
goto cleanup;
}
HRESULT hr = m_browser->get_Document((IDispatch**)&m_spDoc);
if(FAILED(hr))
throw("");
cleanup:
// Free resources.
if(isp!=NULL)
{
isp->Release();
isp = NULL;
}
if(isp2!=NULL)
{
isp2->Release();
isp2 = NULL;
}
return;// hr;
}
return;// hr
}
2.MFC activex去掉IE的安全警告对话框
CManagerXCtrl.h文件中添加:
#include "comcat.h"
#include <objsafe.h>
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid);
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription);
............
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(ProvideClassInfo, IProvideClassInfo)
STDMETHOD_(HRESULT, GetClassInfo) ( /*[out] */ITypeInfo** ppTI );
END_INTERFACE_PART(ProvideClassInfo);
CManagerXCtrl.cpp文件中添加:
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{
ICatRegister* pcr = NULL ; // interface pointer
HRESULT hr = S_OK ;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (FAILED(hr))
return hr;
// Make sure the HKCR/Component Categories/{..catid...}
// key is registered
CATEGORYINFO catinfo;
catinfo.catid = catid;
catinfo.lcid = 0x0409 ; // english
// Make sure the provided description is not too long.
// Only copy the first 127 characters if it is
int len = wcslen(catDescription);
if (len>127)
len = 127;
wcsncpy(catinfo.szDescription, catDescription, len);
// Make sure the description is null terminated
catinfo.szDescription[len] = '/0';
hr = pcr->RegisterCategories(1, &catinfo);
pcr->Release();
return hr;
}
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
// Register your component categories information.
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (SUCCEEDED(hr))
{
// Register this category as being "implemented" by
// the class.
CATID rgcatid[1] ;
rgcatid[0] = catid;
hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
}
if (pcr != NULL)
pcr->Release();
return hr;
}
BEGIN_INTERFACE_MAP( CManagerXCtrl, COleControl )
INTERFACE_PART(CManagerXCtrl, IID_IProvideClassInfo, ProvideClassInfo)
END_INTERFACE_MAP()
ULONG FAR EXPORT CManagerXCtrl::XProvideClassInfo::AddRef()
{
METHOD_PROLOGUE(CManagerXCtrl, ProvideClassInfo)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CManagerXCtrl::XProvideClassInfo::Release()
{
METHOD_PROLOGUE(CManagerXCtrl, ProvideClassInfo)
return pThis->ExternalRelease();
}
HRESULT STDMETHODCALLTYPE
CManagerXCtrl::XProvideClassInfo::QueryInterface (
REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CManagerXCtrl, ProvideClassInfo)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
HRESULT STDMETHODCALLTYPE
CManagerXCtrl::XProvideClassInfo::GetClassInfo (
/* [out] */ITypeInfo** ppTypeInfo
)
{
METHOD_PROLOGUE(CManagerXCtrl, ProvideClassInfo)
HRESULT hr;
CLSID clsid;
pThis->GetClassID(&clsid);
hr = pThis->GetTypeInfoOfGuid(GetUserDefaultLCID(), clsid, ppTypeInfo);
return hr;
}
修改BOOL CManagerXCtrl::CManagerXCtrlFactory::UpdateRegistry(BOOL bRegister)函数如下:
BOOL CManagerXCtrl::CManagerXCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: 验证您的控件是否符合单元模型线程处理规则。
// 有关更多信息,请参考 MFC 技术说明 64。
// 如果您的控件不符合单元模型规则,则
// 必须修改如下代码,将第六个参数从
// afxRegApartmentThreading 改为 0。
if (bRegister)
{
BOOL retval = AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_MANAGERX,
IDB_MANAGERX,
afxRegApartmentThreading,
_dwManagerXOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
// mark as safe for scripting--failure OK
HRESULT hr = CreateComponentCategory(CATID_SafeForScripting,
L"Controls that are safely scriptable");
if (SUCCEEDED(hr))
// only register if category exists
RegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting);
// don't care if this call fails
// mark as safe for data initialization
hr = CreateComponentCategory(CATID_SafeForInitializing,
L"Controls safely initializable from persistent data");
if (SUCCEEDED(hr))
// only register if category exists
RegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing);
// don't care if this call fails
return retval;
}
else
{
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
}
3.发布activeX
发布activex分为四个步骤.
首先制作inf文件,printerx.inf的示例如下
[Version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Add.Code]
PrinterX.ocx =PrinterX.ocx
msvcr80.dll=msvcr80.dll
mfc80.dll=mfc80.dll
msvcp80.dll=msvcp80.dll
[PrinterX.ocx]
file-win32-x86=thiscab
RegisterServer=yes
CLSID={F0046897-B136-4F3A-9F59-23FD9F8C7D69}
;DestDir=11
FileVersion=1,0,0,1
其次制作cab包使用cabarc.exe,示例如下
cabarc -s 6144 n evS1300.cab msvcr71.dll mfc71.dll msvcp71.dll evS1300.ocx evS1300.inf
再次使用<object>标签在网页中引入activex
最后为了使activeX能正常下载,更改ie的安全设置,允许下载运行未签名的activex,必要时要把cab的url加入到信任站点中,
当下载完后要还原IE的安全设置。
本随笔是为了总结,可能文中有些细处有不妥,请朋友们见谅。有个故事说诸葛亮和其他两个朋友一块读书,唯诸葛孔明独观其大略。 意义类之。