软件架构师何志丹
1、创建COM组件的框架。(组件已注册)
IUnknown *pUnk = NULL;
IObject *pObject = NULL;
CoInitialize(NULL);
CoCreateInstance(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IDD_Unknown, (void**)&pUnk);
pUnk->QueryInterface(IID_IObject, (void**)&pObject);
pUnk->Release();
pObject->Func();
pObject->Release();
CoUninitialize();
CoCreateInstance的内部:
CoCreateInstance(....)
{
.......
IClassFactory *pClassFactory=NULL; //先获得类工厂对象①
CoGetClassObject(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void **)&pClassFactory); //再通过类工厂对象创建组件并且得到IUnknown指针。②
pClassFactory->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
pClassFactory->Release();
........
}
//①-------------------
CoGetClassObject的内部:
CoGetClassObject(.....)
{
//通过查注册表CLSID_Object,得知组件DLL的位置、文件名
//使用LoadLibrary装入DLL库
//使用函数GetProcAddress( "DllGetClassObject" )得到DLL库中函数DllGetClassObject的函数指针。
//调用DllGetClassObject
}DllGetClassObject是用来获得类工厂对象的,只有先得到类工厂才能去创建组件。
DllGetClassObject代码:
HRESULT_export PASCAL DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID * ppvObj)
{
HRESULT hr = E_OUTOFMEMORY;
*ppvObj = NULL;
CClassFactory *pClassFactory = new CClassFactory(rclsid); //类工厂
if (pClassFactory != NULL) {
hr = pClassFactory->QueryInterface(riid, ppvObj);
pClassFactory->Release();
}
return hr;
}//②----------------
CFactory::CreateInstance(.....)
{
...........
CObject *pObject = new CObject; //组件对象
pObject->QueryInterface(IID_IUnknown, (void**)&pUnk);
pObject->Release();
...........
}
实例:
CComPtr<IAVIer> m_piAVIer;
m_piAVIer.CoCreateInstance(L"AVI.AVIer");
2、通过LoadLibrary和DllGetClassObject创建组件对象(组件未注册)
CComPtr<IAVIer> m_piAVIer;
typedef int (WINAPI *DllGetClassObjectPtr)(REFCLSID, REFIID, LPVOID*);
HMODULE hModule = LoadLibrary(dll文件路径);
//得到DllGetClassObject函数地址
DllGetClassObjectPtr ProcPtr = (DllGetClassObjectPtr)GetProcAddress(hModule, "DllGetClassObject");
CLSID rclsid;
IID riid;
::CLSIDFromString(A2W("{D5A365A3-44F8-47A0-8FCF-062372B1EB83}"), &rclsid);//类ID
::IIDFromString(A2W("{BE136856-CBEA-4079-A02B-BBC7A382BDB3}"), &riid);//接口IDIClassFactory *pICF = NULL;//类工厂接口指针
ProcPtr(rclsid, IID_IClassFactory, (void**)(&pICF));//获取类工厂接口指针
//以上相当于①
pICF->CreateInstance(NULL, riid, (void**)&m_piAVIer);//创建COM对象
//以上相当于②
pICF->Release();
备注:
HKCR
{
Avi.AVIer.1 = s 'AVIer Class'
{
CLSID = s '{D5A365A3-44F8-47A0-8FCF-062372B1EB83}'
}
Avi.AVIer = s 'AVIer Class'
{
CLSID = s '{D5A365A3-44F8-47A0-8FCF-062372B1EB83}'
CurVer = s 'Avi.AVIer.1'
}
NoRemove CLSID
{
ForceRemove {D5A365A3-44F8-47A0-8FCF-062372B1EB83} = s 'AVIer Class'
{
ProgID = s 'Avi.AVIer.1'
VersionIndependentProgID = s 'Avi.AVIer'
ForceRemove 'Programmable'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
'TypeLib' = s '{59AE79C3-3AC6-42E1-ABED-10B363EDAA4C}'
}
}
}
[
object,
uuid(BE136856-CBEA-4079-A02B-BBC7A382BDB3),//接口ID
dual,
helpstring("IAVIer Interface"),
pointer_default(unique)
]
library AVILib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");[
uuid(D5A365A3-44F8-47A0-8FCF-062372B1EB83),//类ID
helpstring("AVIer Class")
]
coclass AVIer
{
[default] interface IAVIer;//类ID
};
};