副标题#e#
晚上在博客厅读完VSTO写的一篇文章,先容了CodePlex上面的一个项目,叫做 “All-In-One Code Framework”,代号CodeFx,简朴的说,就是收集了险些所有 常见的微软开拓技能的示例项目,将其打包到这个框架里,并且还利用各类差异的语言举办 实现。好比建设一个ActiveX控件和COM组件,CodeFx内里利用ATL、MFC、VB、C#来实现同样 的成果。
适合新手入门,也可以作为一份模板供履历富厚的开拓者利用,可节减大量的时间。官方 网站上给出了框架的根基布局,如下图所示:
COM组件和ActiveX控件示例
数据会见示例
库示例
#p#副标题#e#
历程间通信示例
花了2 个小时大致阅读了代码,记录下进修心得:
1)先来说ActiveX这条线,它内里利用了 ATL(这里有2种实现,历程内和历程外),MFC,C#,VB四种技能来实现。成果就是四点:一个返 回字符串的HelloWorld要领,一个float范例的属性FloatProperty,一个返回历程号和线程 号的GetProcessThreadID要领,一个FloatPropertyChanging事件。
2)授权支持是 ActiveX 控件的一项可选成果,它使您得以节制能利用或分发该控件的人。(请拜见《MFC ActiveX 控件:授权 ActiveX 控件》)。
头文件的修改
“ActiveX 控件领导”将下列代码安排在控件头文件中。声明白 factory 工具的两个成员函数,个中一个成员函数验证控件 .LIC 文件是否存在,而另一个成员函数 则对包括该控件的应用措施中利用的许可证密钥举办检索:
BEGIN_OLEFACTORY(CMFCActiveXCtrl) // Class factory and guid
virtual BOOL VerifyUserLicense();
virtual BOOL GetLicenseKey(DWORD, BSTR FAR*);
END_OLEFACTORY(CMFCActiveXCtrl)
实现文件的修改
“ActiveX 控件领导”将下面两条语句安排在控件实现文件中,以声明许 可文件名和许可字符串:
static const TCHAR BASED_CODE _szLicFileName[] =
_T("License.lic");
static const WCHAR BASED_CODE _szLicString[] =
L"Copyright (c) 2000 ";
留意:假如以任何方法修改 szLicString,则必需也修改控件 .LIC 文件的第一行,不然授权将无法正确运行。
“ActiveX 控件领导”将下列代码安排在控件实现文件中,以界说控件类 的 VerifyUserLicense 函数和 GetLicenseKey 函数:
// CMFCActiveXCtrl::CMFCActiveXCtrlFactory::VerifyUserLicense -
// Checks for existence of a user license
BOOL CMFCActiveXCtrl::CMFCActiveXCtrlFactory::VerifyUserLicense()
{
return AfxVerifyLicFile(AfxGetInstanceHandle(), _szLicFileName,
_szLicString);
}
// CMFCActiveXCtrl::CMFCActiveXCtrlFactory::GetLicenseKey -
// Returns a runtime licensing key
BOOL CMFCActiveXCtrl::CMFCActiveXCtrlFactory::GetLicenseKey(DWORD dwReserved,
BSTR FAR* pbstrKey)
{
if (pbstrKey == NULL)
return FALSE;
*pbstrKey = SysAllocString(_szLicString);
return (*pbstrKey != NULL);
}
最后,“ActiveX 控件领导”修改控件项目 .IDL 文件。将要害 字 licensed 添加到控件的 coclass 声明中,如下例所示:
[ uuid (E389AD6C-4FB6-47AF-B03A-A5A5C6B2B820), licensed,
helpstring("MFCActiveX Control"), control ]
coclass MFCActiveX
3)作者封装了一个要领AutoWrap来挪用COM组件 果真出来的属性或要领。
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
LPOLESTR ptName, int cArgs)
{
// Begin variable-argument list
va_list marker;
va_start(marker, cArgs);
if (!pDisp)
{
_putts(_T("NULL IDispatch passed to AutoWrap()"));
_exit(0);
}
// Variables used
DISPPARAMS dp = { NULL, NULL, 0, 0 };
DISPID dispidNamed = DISPID_PROPERTYPUT;
DISPID dispID;
HRESULT hr;
char szName[200];
// Convert down to ANSI
WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
// Get DISPID for name passed
hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT,
&dispID);
if (FAILED(hr))
{
_tprintf(_T(
"IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx\n"
), szName, hr);
return hr;
}
// Allocate memory for arguments
VARIANT *pArgs = new VARIANT[cArgs+1];
// Extract arguments
for(int i=0; i<cArgs; i++)
{
pArgs[i] = va_arg(marker, VARIANT);
}
// Build DISPPARAMS
dp.cArgs = cArgs;
dp.rgvarg = pArgs;
// Handle special-case for property-puts
if (autoType & DISPATCH_PROPERTYPUT)
{
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = &dispidNamed;
}
// Make the call
hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
autoType, &dp, pvResult, NULL, NULL);
if (FAILED(hr))
{
_tprintf(_T(
"IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx\n"
), szName, dispID, hr);
return hr;
}
// End variable-argument section
va_end(marker);
delete[] pArgs;
return hr;
}
4)DLL的延迟加载使得我们不需要利用LoadLibrary和GetProcAddress。这 样的长处是直到措施挪用DLL中的函数时才加载此DLL。
#include <Delayimp.h>
卸载延迟加载的DLL的代码:
PCSTR pszDll = "CppDllExport.dll";
_tprintf(_T("__FUnloadDelayLoadedDLL2 => %d\n"),
__FUnloadDelayLoadedDLL2(pszDll));