程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> CodeFx:一站式微軟開發技術解決方案

CodeFx:一站式微軟開發技術解決方案

編輯:關於C++

晚上在博客堂讀完VSTO寫的一篇文章,介紹了CodePlex上面的一個項目,叫做 “All-In-One Code Framework”,代號CodeFx,簡單的說,就是收集了幾乎所有 常見的微軟開發技術的示例項目,將其打包到這個框架裡,而且還使用各種不同的語言進行 實現。比如創建一個ActiveX控件和COM組件,CodeFx裡面使用ATL、MFC、VB、C#來實現同樣 的功能。

適合新手入門,也可以作為一份模板供經驗豐富的開發者使用,可節省大量的時間。官方 網站上給出了框架的基本結構,如下圖所示:

COM組件和ActiveX控件示例

數據訪問示例

庫示例

進程間通信示例

 

花了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));

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved