天天看点

CodeFx:一站式微软开发技术解决方案 .

适合新手入门,也可以作为一份模板供经验丰富的开发者使用,可节省大量的时间。官方网站上给出了框架的基本结构,如下图所示:

COM组件和ActiveX控件示例

CodeFx:一站式微软开发技术解决方案 .

数据访问示例

CodeFx:一站式微软开发技术解决方案 .

库示例

CodeFx:一站式微软开发技术解决方案 .

进程间通信示例 

CodeFx:一站式微软开发技术解决方案 .

花了2个小时粗略阅读了代码,记录下学习心得:

1)先来说ActiveX这条线,它里面使用了ATL(这里有2种实现,进程内和进程外),MFC,C#,VB四种技术来实现。功能就是四点:一个返回字符串的HelloWorld方法,一个float类型的属性FloatProperty,一个返回进程号和线程号的GetProcessThreadID方法,一个FloatPropertyChanging事件。

头文件的修改     

“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

CodeFx:一站式微软开发技术解决方案 .

    // 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

CodeFx:一站式微软开发技术解决方案 .

    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)) 

            "IDispatch::Invoke(/"%s/"=%08lx) failed w/err 0x%08lx/n"

            ), szName, dispID, 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));