軟體架構師何志丹
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
};
};