C++编写网页控件,遇到的问题总结

来源:互联网 发布:怎么装ubuntu系统 编辑:程序博客网 时间:2024/06/15 23:06

最近做一个溯源的系统,在里面就涉及到了制卡的过程,而我们又不想做成C/S的形式,只想在B/S上搞定这个问题,这样就不得不做成ActiveX的形式了!哪知在做这个的过程还真遇到一些问题,让人纠结了很久,网上也找不到解决方案,最后还是自己慢慢搞定!好,下面就开始来说制作这个控件的过程吧!
      开发环境:Win7 + VS 2010
      首先当然是建立工程咯,这个不用多说了吧,哦,新建一个MFC ActiveX工程,如图吧
image
确定,下一步到这里
image
下一步,下一步完成,这样就建立了一个ActiveX工程了!
下面开始做事吧,多的就不用了,我们就只用系统的AboxBox方法吧,毕竟主要不是说ActiveX的开发的!
 
但是我们还是要做一些事情的,那就是控件安全性的验证东东!找到代码文件ActiveXDemo.cpp
在开始处添加头文件
#include <ObjSafe.h>
然后我们在const WORD _wVerMinor = 0;下面开始添加一部分代码
/*这里开始就是为控件安全添加的东西哦*/
// 控件的CLSID,注册表用(一定要是实际使用的控件的)可以在ActiveXDemo.idl最下面找到
//  CActiveXDemoCtrl 的类信息
    [
        uuid(FDC2D72B-3B02-4AFD-B48F-7B99BF90C220), licensed
    ]
将uuid里面的值加入到CLSID_SafeItem 里面去就行了
const GUID CDECL CLSID_SafeItem = { 0xFDC2D72B, 0x3B02, 0x4AFD,{ 0xB4, 0x8F, 0x7B, 0x99, 0xBF, 0x90, 0xC2, 0x20 }};
/// 创建组件种类
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{  
    ICatRegister* pcr = NULL ;
    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;
}
// 卸载组件种类
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)

    ICatRegister* pcr = NULL ; 
    HRESULT hr = S_OK ; 
    hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);  
    if (SUCCEEDED(hr)) 
    {    
        // Unregister this category as being implemented by the class.   
        CATID rgcatid[1] ;    
        rgcatid[0] = catid;  
        hr = pcr->;UnRegisterClassImplCategories(clsid, 1, rgcatid);
    }   
    if (pcr != NULL)
        pcr->Release();  
    return hr;
}
然后这在下面找到
// DllRegisterServer - 将项添加到系统注册表
STDAPI DllRegisterServer(void)
修改代码为
STDAPI DllRegisterServer(void)
{
    HRESULT hr;
    AFX_MANAGE_STATE(_afxModuleAddrThis);
    if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
        return ResultFromScode(SELFREG_E_TYPELIB);
    if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
        return ResultFromScode(SELFREG_E_CLASS);
    ///////////////////////////////////
    // 标记控件初始化安全.
    // 创建初始化安全组件种类
    hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!");
    if (FAILED(hr))     
        return hr;   
    // 注册初始化安全  
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if (FAILED(hr))    
        return hr; 
    // 标记控件脚本安全 
    // 创建脚本安全组件种类  
    hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");
    if (FAILED(hr))      
        return hr;   
    // 注册脚本安全组件种类 
    hr = RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if (FAILED(hr))       
        return hr;
    return NOERROR;
}
 
如果说你不想添加这些东西的话,那么运行这个控件的时候,他都会提示是否运行!麻烦哇
OK生成工程.我们将控件放在网页里试试
<html>
<head>
<title>ActiveX</title>
<OBJECT classid="clsid:FDC2D72B-3B02-4AFD-B48F-7B99BF90C220" id="ActiveXDemo" > </OBJECT>
<script type="text/javascript">
function Open()
{ ActiveXDemo.AboutBox(); }
</script>
</head>
<body bgcolor="#ffffff" >
<form name=stuff>
<input type=button name=test value="Load"/>
</form>
</body>
</html>
这样就可以看有没有注册成功,点击这个按钮,如果弹出
image
那么就代表注册成功了,要么就没有成功!
如果没有添加上面的那些安全代码的话,会弹出另外一个窗口
image
这样的话很妨碍使用!所以还是加上这部分处理的代码的好!
OK这样就算了将一个ActiveX控件写完了,下面的工作就是在裸机上面注册的事情了!
其实这个裸机也不算是什么裸机,只是没有注册VC里面的一些文件的.那样的话是不能使用这个控件的!
先将生成的控件ActiveXDemo.ocx复制到测试机的D:\test目录下面,在命令提示行下面进行注册,注册语句为regsvr32 (/u 加上这个为卸载控件)ActiveXDemo.ocx
image
出现错误提示,找不到模块,我们用VC6.0的工具Depends来查看少哪些模块
image
看到如上的提示,有黄色问号提示的就是没有的文件,这样就好办了,到开发的机子上面去把这些文件找到,然后复制到test目录下面去再注册!
找到所有的模块,过后再次运行depends看看
image
这样模块就都找到了.运行命令进行注册看一下效果!
image
这样就算是注册成功了,运行看看效果吧!点击Load却是出现下面的脚本错误
image
看错误提示
image
不支持的对象方法,奇怪了,这样就说明注册是注册成功了,但是却没有初始化成功,是不是与我们刚才看到的mpr.dll那个呈红色有关呢,那我们到depends里去看看是什么原因
image
有一个方法是红色的,那么到底是不是这个原因呢!
经过在网上查找资料后,但是网上也没有好的解决方案,最后在http://www.dependencywalker.com/faq.html这上面看到一条信息

Why am I seeing a lot of applications where MPR.DLL shows up in red under SHLWAPI.DLL because it is missing a function named WNetRestoreConnectionA? I also get a "Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module" message.

Some versions of SHLWAPI.DLL (like the one on Windows XP) have a delay-load dependency on the function WNetRestoreConnectionA in MPR.DLL. Missing delay-load functions are not a problem as long as the calling DLL is prepared to handle the situation. Dependency Walker flags all potential problems as it cannot detect if an application intends to handle the issue. In the case of SHLWAPI.DLL, this is not an problem as it does not require WNetRestoreConnectionA to exist and handles the missing function at runtime. This warning can be ignored. See the "How to Interpret Warnings and Errors in Dependency Walker" section in help for more details.
大概意思就是说这个警告是可以忽略的,那么问题到底是在哪里呢!后来我偶然发现我将生成的文件,文件夹里的文件全部都放进去过后,注册就可以使用了,那就是说,在生成后,除了ocx文件以外应该还有另外的文件是必须的,经过反复的测试,才发现只有ActiveXDemo.lic这个文件有效.
这时才想起在ActiveXDemoCtrl.cpp文件代码中有这么一段代码
// 授权字符串
static const TCHAR _szLicFileName[] = _T("ActiveXDemo.lic");
static const WCHAR _szLicString[] = L"Copyright (c) 2010 ";
// CActiveXDemoCtrl::CActiveXDemoCtrlFactory::VerifyUserLicense -
// 检查是否存在用户许可证
BOOL CActiveXDemoCtrl::CActiveXDemoCtrlFactory::VerifyUserLicense()
{
    return AfxVerifyLicFile(AfxGetInstanceHandle(), _szLicFileName,
        _szLicString);
}
// CActiveXDemoCtrl::CActiveXDemoCtrlFactory::GetLicenseKey -
// 返回运行时授权密钥
BOOL CActiveXDemoCtrl::CActiveXDemoCtrlFactory::GetLicenseKey(DWORD dwReserved,
    BSTR *pbstrKey)
{
    if (pbstrKey == NULL)
        return FALSE;
    *pbstrKey = SysAllocString(_szLicString);
    return (*pbstrKey != NULL);
}
原来是没有运行许可证,才造成这样的错误,将lic文件复制到test目录下再次注册控件可以使用了
image
真的是一路走来都是泪啊!到此所有问题解决,终于可以使用了!
当然使用网页控件的时候会有证书的问题,那个问题大家自己去找解决方案吧,毕竟证书这种东西不好找啊!
OK,本文到此,如有不足之处,请大家请出意见,本人新手!希望高手们不要鄙视哈!

本文出自 “Laputaliya” 博客,请务必保留此出处http://laputaliya.blog.51cto.com/751941/426914

0 0
原创粉丝点击