概述
对于初学com的,一个完整的示例还是挺麻烦的,最近笔者也在学习,通过自己的摸索了解了下基本原理。在此将一个简单string的示例一步一步的详解。
源代码下载
1.创建工程
首先使用vs2010(笔者使用的vs2010就拿此来讲)创建一个工程。选择空项目,笔者命名为MyCom。
2.创建接口类
#ifndef IString_h__
#define IString_h__
#include <Windows.h>
#include <Unknwn.h>
#include <ObjBase.h>
extern "C" const GUID IID_IString;
class IString : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetString(char*) = 0;
virtual HRESULT STDMETHODCALLTYPE GetString(char*, long) = 0;
virtual HRESULT STDMETHODCALLTYPE AboutMessage() = 0;
};
#endif // IString_h__
3.创建组件类
#ifndef String_h__
#define String_h__
#include "IString.h"
class String :public IString
{
public:
String();
~String();
public:
//IUkown Function
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,LPVOID *ppv);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
//IString Function
HRESULT STDMETHODCALLTYPE SetString(char* chBuf);
HRESULT STDMETHODCALLTYPE GetString(char* chBuf, long cLength);
HRESULT STDMETHODCALLTYPE AboutMessage();
protected:
ULONG m_Ref;
char buffer[80];
};
#endif // String_h__
3.定义类厂
#ifndef CFactory_h__
#define CFactory_h__
#include <Unknwn.h>
class CFactory : public IClassFactory
{
public:
CFactory();
~CFactory();
//IUnknown members
HRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid, void **ppv);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
//IClassFactory members
HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *, const IID& iid, void **ppv);
HRESULT STDMETHODCALLTYPE LockServer(BOOL bIsLocck);
protected:
ULONG m_Ref;
};
#endif // CFactory_h__
4.类厂实现
#include "CFactory.h"
#include "String.h"
extern ULONG g_LockNumber;
extern ULONG g_StringNumber;
CFactory::CFactory()
{
m_Ref = 0;
}
CFactory::~CFactory(){}
HRESULT CFactory::QueryInterface(const IID& iid, void **ppv)
{
if (iid == IID_IUnknown)
{
*ppv = (IUnknown*)this;
((IUnknown*)(*ppv))->AddRef();
}else if(iid == IID_IClassFactory)
{
*ppv = (IClassFactory*)this;
((IClassFactory*)(*ppv))->AddRef();
}else{
*ppv = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
ULONG CFactory::AddRef()
{
m_Ref++;
return m_Ref;
}
ULONG CFactory::Release()
{
m_Ref--;
if (m_Ref == 0)
{
delete this;
return 0;
}
return m_Ref;
}
HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, const IID& iid, void **ppv)
{
HRESULT hr;
String *pObj;
*ppv = NULL;
hr = E_OUTOFMEMORY;
if(NULL != pUnknownOuter)
return CLASS_E_NOAGGREGATION;
pObj = new String();
if(NULL == pObj)
return hr;
hr = pObj->QueryInterface(iid,ppv);
if (hr != S_OK)
{
g_StringNumber--;
delete pObj;
}
return S_OK;
}
HRESULT CFactory::LockServer(BOOL bIsLock)
{
if (bIsLock)
g_LockNumber++;
else
g_LockNumber--;
return S_OK;
}
5、引出函数def文件
LIBRARY "MyCom"
EXPORTS
; Explicit exports can go here
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllCanUnloadNow PRIVATE
6.组件注册
#ifndef __Registry_H__
#define __Registry_H__
//
// Registry.h
// - Helper functions registering and unregistering a component.
//
// - These helper functions were borrowed and modifed from
// Dale Rogerson's book Inside COM.
// This function will register a component in the Registry.
// DllRegisterServer function should call this function.
HRESULT RegisterServer(const CLSID& clsid,
const char *szFileName,
const char* szProgID,
const char* szDescription,
const char* szVerIndProgID) ;
// This function will unregister a component. Components
// DllUnregisterServer function should call this function.
HRESULT UnregisterServer(const CLSID& clsid,
const char* szProgID,
const char* szVerIndProgID) ;
#endif
7.组件注册实现
//
// Registry.cpp
//
#include <objbase.h>
#include <assert.h>
#include "Registry.h"
//
// Internal helper functions prototypes
//
// - These helper functions were borrowed and modifed from
// Dale Rogerson's book Inside COM.
// Set the given key and its value.
BOOL SetKeyAndValue(const char* pszPath,
const char* szSubkey,
const char* szValue) ;
// Convert a CLSID into a char string.
void CLSIDtoString(const CLSID& clsid,
char* szCLSID,
int length) ;
// Delete szKeyChild and all of its descendents.
LONG DeleteKey(HKEY hKeyParent, const char* szKeyString) ;
//
// Constants
//
// Size of a CLSID as a string
const int CLSID_STRING_SIZE = 39 ;
/
//
// Public function implementation
//
//
// Register the component in the registry.
//
HRESULT RegisterServer(const CLSID& clsid, // Class ID
const char *szFileName, // DLL module handle
const char* szProgID, // IDs
const char* szDescription, // Description String
const char* szVerIndProgID) // optional
{
// Convert the CLSID into a char.
char szCLSID[CLSID_STRING_SIZE] ;
CLSIDtoString(clsid, szCLSID, sizeof(szCLSID)) ;
// Build the key CLSID\{...}
char szKey[64] ;
strcpy_s(szKey, "CLSID\") ;
strcat_s(szKey, szCLSID) ;
// Add the CLSID to the registry.
SetKeyAndValue(szKey, NULL, szDescription) ;
// Add the server filename subkey under the CLSID key.
SetKeyAndValue(szKey, "InprocServer32", szFileName) ;
// Add the ProgID subkey under the CLSID key.
if (szProgID != NULL) {
SetKeyAndValue(szKey, "ProgID", szProgID) ;
SetKeyAndValue(szProgID, "CLSID", szCLSID) ;
}
if (szVerIndProgID) {
// Add the version-independent ProgID subkey under CLSID key.
SetKeyAndValue(szKey, "VersionIndependentProgID",
szVerIndProgID) ;
// Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
SetKeyAndValue(szVerIndProgID, NULL, szDescription) ;
SetKeyAndValue(szVerIndProgID, "CLSID", szCLSID) ;
SetKeyAndValue(szVerIndProgID, "CurVer", szProgID) ;
// Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
SetKeyAndValue(szProgID, NULL, szDescription) ;
SetKeyAndValue(szProgID, "CLSID", szCLSID) ;
}
return S_OK ;
}
//
// Remove the component from the registry.
//
HRESULT UnregisterServer(const CLSID& clsid, // Class ID
const char* szProgID, // IDs
const char* szVerIndProgID) // Programmatic
{
// Convert the CLSID into a char.
char szCLSID[CLSID_STRING_SIZE] ;
CLSIDtoString(clsid, szCLSID, sizeof(szCLSID)) ;
// Build the key CLSID\{...}
char szKey[64] ;
strcpy_s(szKey, "CLSID\") ;
strcat_s(szKey, szCLSID) ;
// Delete the CLSID Key - CLSID{...}
LONG lResult = DeleteKey(HKEY_CLASSES_ROOT, szKey) ;
// Delete the version-independent ProgID Key.
if (szVerIndProgID != NULL)
lResult = DeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;
// Delete the ProgID key.
if (szProgID != NULL)
lResult = DeleteKey(HKEY_CLASSES_ROOT, szProgID) ;
return S_OK ;
}
///
//
// Internal helper functions
//
// Convert a CLSID to a char string.
void CLSIDtoString(const CLSID& clsid,
char* szCLSID,
int length)
{
assert(length >= CLSID_STRING_SIZE) ;
// Get CLSID
LPOLESTR wszCLSID = NULL ;
HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
assert(SUCCEEDED(hr)) ;
// Covert from wide characters to non-wide.
wcstombs(szCLSID, wszCLSID, length) ;
// Free memory.
CoTaskMemFree(wszCLSID) ;
}
//
// Delete a key and all of its descendents.
//
LONG DeleteKey(HKEY hKeyParent, // Parent of key to delete
const char* lpszKeyChild) // Key to delete
{
// Open the child.
HKEY hKeyChild ;
LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
KEY_ALL_ACCESS, &hKeyChild) ;
if (lRes != ERROR_SUCCESS)
{
return lRes ;
}
// Enumerate all of the decendents of this child.
FILETIME time ;
char szBuffer[256] ;
DWORD dwSize = 256 ;
while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
NULL, NULL, &time) == S_OK)
{
// Delete the decendents of this child.
lRes = DeleteKey(hKeyChild, szBuffer) ;
if (lRes != ERROR_SUCCESS)
{
// Cleanup before exiting.
RegCloseKey(hKeyChild) ;
return lRes;
}
dwSize = 256 ;
}
// Close the child.
RegCloseKey(hKeyChild) ;
// Delete this child.
return RegDeleteKey(hKeyParent, lpszKeyChild) ;
}
//
// Create a key and set its value.
//
BOOL SetKeyAndValue(const char* szKey,
const char* szSubkey,
const char* szValue)
{
HKEY hKey;
char szKeyBuf[1024] ;
// Copy keyname into buffer.
strcpy(szKeyBuf, szKey) ;
// Add subkey name to buffer.
if (szSubkey != NULL)
{
strcat(szKeyBuf, "\") ;
strcat(szKeyBuf, szSubkey ) ;
}
// Create and open key and subkey.
long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,
szKeyBuf,
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL,
&hKey, NULL) ;
if (lResult != ERROR_SUCCESS)
{
return FALSE ;
}
// Set the Value.
if (szValue != NULL)
{
RegSetValueEx(hKey, NULL, 0, REG_SZ,
(BYTE *)szValue,
strlen(szValue)+1) ;
}
RegCloseKey(hKey) ;
return TRUE ;
}
8.引出函数及组件函数实现
#include "CFactory.h"
#include "Registry.h"
#include "String.h"
ULONG g_LockNumber = 0;
ULONG g_StringNumber = 0;
// {913AAE18-1D57-4868-AF2F-B47D32163E8F}
extern "C" const GUID CLSID_String =
{ 0x913aae18, 0x1d57, 0x4868, { 0xaf, 0x2f, 0xb4, 0x7d, 0x32, 0x16, 0x3e, 0x8f } };
// {416DC65F-48E2-436a-BA34-FC00AC3DA598}
extern "C" const GUID IID_IString =
{ 0x416dc65f, 0x48e2, 0x436a, { 0xba, 0x34, 0xfc, 0x0, 0xac, 0x3d, 0xa5, 0x98 } };
HMODULE g_hModule=0;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
g_hModule = hModule;
return TRUE;
}
extern "C" HRESULT STDMETHODCALLTYPE DllCanUnloadNow()
{
if((g_LockNumber == 0)&&(g_StringNumber))
return S_OK;
else
return S_FALSE;
}
extern "C" HRESULT STDMETHODCALLTYPE DllRegisterServer()
{
char szModule[1024];
DWORD dwResult = ::GetModuleFileName((HMODULE)g_hModule, szModule, 1024);
if (dwResult == 0)
return -1;
return RegisterServer(CLSID_String,
szModule,
"STRING.Object",
"MyCom String Component",
NULL);
}
extern "C" HRESULT STDMETHODCALLTYPE DllUnregisterServer()
{
return UnregisterServer(CLSID_String,
"STRING.Object",NULL);
}
extern "C" HRESULT STDMETHODCALLTYPE DllGetClassObject(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID FAR* ppv)
{
if (rclsid == CLSID_String)
{
CFactory *pFactory = new CFactory();
if(pFactory == NULL)
return E_OUTOFMEMORY;
HRESULT hr = pFactory->QueryInterface(riid,ppv);
return hr;
}else
{
return CLASS_E_CLASSNOTAVAILABLE;
}
}
HRESULT String::QueryInterface(REFIID iid,LPVOID *ppv)
{
if (iid == IID_IUnknown)
{
*ppv = (IUnknown*)this;
((IUnknown*)(*ppv))->AddRef();
}else if(iid == IID_IString)
{
*ppv = (IClassFactory*)this;
((IClassFactory*)(*ppv))->AddRef();
}else
{
*ppv = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
String::String()
{
m_Ref = 0;
}
String::~String()
{
}
ULONG String::AddRef()
{
m_Ref++;
return m_Ref;
}
ULONG String::Release()
{
m_Ref--;
if (m_Ref == 0)
{
delete this;
return 0;
}
return m_Ref;
}
HRESULT String::GetString(char*chBuf, long cLength)
{
long i;
// 拷贝IExample的buffer到传入的buffer中
i = lstrlen(buffer);
--cLength;
if (i > cLength) i = cLength;
CopyMemory(chBuf, buffer, i);
chBuf[i] = 0;
return(0);
}
HRESULT String::SetString(char* chBuf)
{
DWORD i;
// 把传入的str拷贝到IExample的buffer中
i = lstrlen(chBuf);
if (i > 79) i = 79;
CopyMemory(buffer, chBuf, i);
buffer[i] = 0;
return(0);
}
HRESULT String::AboutMessage()
{
MessageBox(NULL,"hello, i am a message box!","Message",MB_OK);
return S_OK;
}
9.测试文件编写(记得手工注册下dll)
#include "IString.h"
#include <Windows.h>
#include <iostream>
using namespace std;
// {913AAE18-1D57-4868-AF2F-B47D32163E8F}
extern "C" const GUID CLSID_String =
{ 0x913aae18, 0x1d57, 0x4868, { 0xaf, 0x2f, 0xb4, 0x7d, 0x32, 0x16, 0x3e, 0x8f } };
// {416DC65F-48E2-436a-BA34-FC00AC3DA598}
extern "C" const GUID IID_IString =
{ 0x416dc65f, 0x48e2, 0x436a, { 0xba, 0x34, 0xfc, 0x0, 0xac, 0x3d, 0xa5, 0x98 } };
int main()
{
IString *pIStr;
IUnknown *pIUk = NULL;
HRESULT hr;
char chGetChar[80];
CLSID rclsid;
if(CoInitialize(NULL) != S_OK)
{
cout<<"initialize Failed"<<endl;
return -1;
}
hr = CLSIDFromProgID(OLESTR("STRING.Object"),&rclsid);
if (hr != S_OK)
{
cout<<"Can't find the dictionary CLSID!"<<endl;
return -2;
}
hr = CoCreateInstance(rclsid,NULL,CLSCTX_INPROC_SERVER,IID_IUnknown,(LPVOID*)&pIUk);
if (hr != S_OK)
{
cout<<"Create object failed!"<<endl;
return -2;
}
hr = pIUk->QueryInterface(IID_IString,(LPVOID*)&pIStr);
if (hr != S_OK) {
pIUk->Release();
printf("QueryInterface IString failed!n");
return -3;
}
pIStr->SetString("wqlgregergerg");
pIStr->GetString(chGetChar,sizeof(chGetChar));
cout<<chGetChar<<endl;
pIStr->AboutMessage();
CoUninitialize();
return 0;
}
终于贴完了。一个完整的示例,亲测可以哈!一起学习。
最后
以上就是缥缈大白为你收集整理的一个完整的COM 示例Demo(C++语言描述)的全部内容,希望文章能够帮你解决一个完整的COM 示例Demo(C++语言描述)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复