創建com全過程

 一:創建一個接口

       

  1. typedef  struct  Interface  
  2.   
  3. Interface ISimpleMsgBox : public IUnknown  
  4. {  
  5.     // IUnknown  
  6.     STDMETHOD_(ULONG, AddRef)() PURE;  
  7.     STDMETHOD_(ULONG, Release)() PURE;  
  8.     STDMETHOD(QueryInterface)(REFIID riid, void** ppv) PURE;  
  9.   
  10.     // ISimpleMsgBox  
  11.     STDMETHOD(DoSimpleMsgBox)(HWND hwndParent, BSTR bsMessageText) PURE;  
  12. };  
typedef  struct  Interface

Interface ISimpleMsgBox : public IUnknown
{
    // IUnknown
    STDMETHOD_(ULONG, AddRef)() PURE;
    STDMETHOD_(ULONG, Release)() PURE;
    STDMETHOD(QueryInterface)(REFIID riid, void** ppv) PURE;

    // ISimpleMsgBox
    STDMETHOD(DoSimpleMsgBox)(HWND hwndParent, BSTR bsMessageText) PURE;
};

替代方案:使用idl文件定義接口,其會生成相關頭文件,但可讀性很差

二.聲明一個C++類實現該接口

   

  1. class CSimpleMsgBoxImpl : public ISimpleMsgBox    
  2. {  
  3. public:  
  4.     CSimpleMsgBoxImpl();  
  5.     virtual ~CSimpleMsgBoxImpl();  
  6.   
  7.     // IUnknown  
  8.     STDMETHOD_(ULONG, AddRef)();  
  9.     STDMETHOD_(ULONG, Release)();  
  10.     STDMETHOD(QueryInterface)(REFIID riid, void** ppv);  
  11.   
  12.     // ISimpleMsgBox  
  13.     STDMETHOD(DoSimpleMsgBox)(HWND hwndParent, BSTR bsMessageText);  
  14.   
  15. protected:  
  16.     ULONG m_uRefCount;  
  17. };  
class CSimpleMsgBoxImpl : public ISimpleMsgBox  
{
public:
    CSimpleMsgBoxImpl();
    virtual ~CSimpleMsgBoxImpl();

    // IUnknown
    STDMETHOD_(ULONG, AddRef)();
    STDMETHOD_(ULONG, Release)();
    STDMETHOD(QueryInterface)(REFIID riid, void** ppv);

    // ISimpleMsgBox
    STDMETHOD(DoSimpleMsgBox)(HWND hwndParent, BSTR bsMessageText);

protected:
    ULONG m_uRefCount;
};

實現部分,只關注QueryInterface 和DoSimpleMsgBox 部分

  1. STDMETHODIMP CSimpleMsgBoxImpl::QueryInterface ( REFIID riid, void** ppv )  
  2. {  
  3. HRESULT hrRet = S_OK;  
  4.   
  5.     TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxImpl::QueryInterface()\n" );  
  6.   
  7.     // Check that ppv really points to a void*.  
  8.   
  9.     if ( IsBadWritePtr ( ppv, sizeof(void*) ))  
  10.         return E_POINTER;  
  11.   
  12.     // Standard QI initialization - set *ppv to NULL.  
  13.   
  14.     *ppv = NULL;  
  15.   
  16.     // If the client is requesting an interface we support, set *ppv.  
  17.   
  18.     if ( InlineIsEqualGUID ( riid, IID_IUnknown ))  
  19.         {  
  20.         *ppv = (IUnknown*) this;  
  21.         TRACE(">>> SimpleMsgBoxSvr: Client QIed for IUnknown\n" );  
  22.         }  
  23.     else if ( InlineIsEqualGUID ( riid, __uuidof(ISimpleMsgBox) ))  
  24.         {  
  25.         *ppv = (ISimpleMsgBox*) this;  
  26.         TRACE(">>> SimpleMsgBoxSvr: Client QIed for ISimpleMsgBox\n" );  
  27.         }  
  28.     else  
  29.         {  
  30.         hrRet = E_NOINTERFACE;  
  31.         TRACE(">>> SimpleMsgBoxSvr: Client QIed for unsupported interface\n" );  
  32.         }  
  33.   
  34.     // If we're returning an interface pointer, AddRef() it.  
  35.   
  36.     if ( S_OK == hrRet )  
  37.         {  
  38.         ((IUnknown*) *ppv)->AddRef();  
  39.         }  
  40.   
  41.     return hrRet;  
  42. }  
  43.   
  44. //////////////////////////////////////////////////////////////////////  
  45. // ISimpleMsgBox methods  
  46.   
  47. STDMETHODIMP CSimpleMsgBoxImpl::DoSimpleMsgBox ( HWND hwndParent, BSTR bsMessageText )  
  48. {  
  49. _bstr_t bsMsg = bsMessageText;  
  50. LPCTSTR szMsg = (TCHAR*) bsMsg;         // Use _bstr_t to convert the string to ANSI if necessary.  
  51.   
  52.     TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxImpl::DoSimpleMsgBox()\n" );  
  53.   
  54.     MessageBox ( hwndParent, szMsg, _T("Simple Message Box"), MB_OK );  
  55.   
  56.     return S_OK;  
  57. }  
STDMETHODIMP CSimpleMsgBoxImpl::QueryInterface ( REFIID riid, void** ppv )
{
HRESULT hrRet = S_OK;

    TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxImpl::QueryInterface()\n" );

    // Check that ppv really points to a void*.

    if ( IsBadWritePtr ( ppv, sizeof(void*) ))
        return E_POINTER;

    // Standard QI initialization - set *ppv to NULL.

    *ppv = NULL;

    // If the client is requesting an interface we support, set *ppv.

    if ( InlineIsEqualGUID ( riid, IID_IUnknown ))
        {
        *ppv = (IUnknown*) this;
        TRACE(">>> SimpleMsgBoxSvr: Client QIed for IUnknown\n" );
        }
    else if ( InlineIsEqualGUID ( riid, __uuidof(ISimpleMsgBox) ))
        {
        *ppv = (ISimpleMsgBox*) this;
        TRACE(">>> SimpleMsgBoxSvr: Client QIed for ISimpleMsgBox\n" );
        }
    else
        {
        hrRet = E_NOINTERFACE;
        TRACE(">>> SimpleMsgBoxSvr: Client QIed for unsupported interface\n" );
        }

    // If we're returning an interface pointer, AddRef() it.

    if ( S_OK == hrRet )
        {
        ((IUnknown*) *ppv)->AddRef();
        }

    return hrRet;
}

//////////////////////////////////////////////////////////////////////
// ISimpleMsgBox methods

STDMETHODIMP CSimpleMsgBoxImpl::DoSimpleMsgBox ( HWND hwndParent, BSTR bsMessageText )
{
_bstr_t bsMsg = bsMessageText;
LPCTSTR szMsg = (TCHAR*) bsMsg;         // Use _bstr_t to convert the string to ANSI if necessary.

    TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxImpl::DoSimpleMsgBox()\n" );

    MessageBox ( hwndParent, szMsg, _T("Simple Message Box"), MB_OK );

    return S_OK;
}

三.爲接口和類指定各自指定一個GUID

 使用VC++擴展方法

  1. struct __declspec(uuid("{7D51904D-1645-4a8c-BDE0-0F4A44FC38C4}")) ISimpleMsgBox;  
  2. class  __declspec(uuid("{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}")) CSimpleMsgBoxImpl;  
struct __declspec(uuid("{7D51904D-1645-4a8c-BDE0-0F4A44FC38C4}")) ISimpleMsgBox;
class  __declspec(uuid("{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}")) CSimpleMsgBoxImpl;

這樣便可以使用__uuidof關鍵字了

__uuidof使用方法介紹

屬於VC++擴展語法

 

  1. class Demo  
  2. {  
  3. };  
  4. class __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BA")) Demo;   
  5.   
  6. int main( void )  
  7. {  
  8.     CLSID clsid = __uuidof(Demo);   
  9. }  
class Demo
{
};
class __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BA")) Demo; 

int main( void )
{
    CLSID clsid = __uuidof(Demo); 
}


 

四.創建類廠(必須創建)

  每個類必須配有一個類廠,關注CreateInstance 和LockServer 方法.
CoCreateInstance方法內部會生命週期依賴這個接口

  1. //////////////////////////////////////////////////////////////////////  
  2. // IClassFactory methods  
  3.   
  4. STDMETHODIMP CSimpleMsgBoxClassFactory::CreateInstance ( IUnknown* pUnkOuter,  
  5.                                                          REFIID    riid,  
  6.                                                          void**    ppv )  
  7. {  
  8. HRESULT hrRet;  
  9. CSimpleMsgBoxImpl* pMsgbox;  
  10.   
  11.     TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxClassFactory::CreateInstance()\n" );  
  12.   
  13.     // We don't support aggregation, so pUnkOuter must be NULL.  
  14.   
  15.     if ( NULL != pUnkOuter )  
  16.         return CLASS_E_NOAGGREGATION;  
  17.   
  18.     // Check that ppv really points to a void*.  
  19.   
  20.     if ( IsBadWritePtr ( ppv, sizeof(void*) ))  
  21.         return E_POINTER;  
  22.   
  23.     *ppv = NULL;  
  24.   
  25.     // Create a new COM object!  
  26.   
  27.     pMsgbox = new CSimpleMsgBoxImpl;  
  28.   
  29.     if ( NULL == pMsgbox )  
  30.         return E_OUTOFMEMORY;  
  31.   
  32.     // QI the object for the interface the client is requesting.  
  33.   
  34.     hrRet = pMsgbox->QueryInterface ( riid, ppv );  
  35.   
  36.     // If the QI failed, delete the COM object since the client isn't able  
  37.     // to use it (the client doesn't have any interface pointers on the object).  
  38.   
  39.     if ( FAILED(hrRet) )  
  40.         delete pMsgbox;  
  41.   
  42.     return hrRet;  
  43. }  
  44.   
  45. STDMETHODIMP CSimpleMsgBoxClassFactory::LockServer ( BOOL fLock )  
  46. {  
  47.     // Increase/decrease the DLL ref count, according to the fLock param.  
  48.   
  49.     fLock ? g_uDllLockCount++ : g_uDllLockCount--;  
  50.   
  51.     TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxClassFactory::LockServer(), new DLL ref count = %d\n", g_uDllLockCount );  
  52.       
  53.     return S_OK;  
  54. }  
//////////////////////////////////////////////////////////////////////
// IClassFactory methods

STDMETHODIMP CSimpleMsgBoxClassFactory::CreateInstance ( IUnknown* pUnkOuter,
                                                         REFIID    riid,
                                                         void**    ppv )
{
HRESULT hrRet;
CSimpleMsgBoxImpl* pMsgbox;

    TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxClassFactory::CreateInstance()\n" );

    // We don't support aggregation, so pUnkOuter must be NULL.

    if ( NULL != pUnkOuter )
        return CLASS_E_NOAGGREGATION;

    // Check that ppv really points to a void*.

    if ( IsBadWritePtr ( ppv, sizeof(void*) ))
        return E_POINTER;

    *ppv = NULL;

    // Create a new COM object!

    pMsgbox = new CSimpleMsgBoxImpl;

    if ( NULL == pMsgbox )
        return E_OUTOFMEMORY;

    // QI the object for the interface the client is requesting.

    hrRet = pMsgbox->QueryInterface ( riid, ppv );

    // If the QI failed, delete the COM object since the client isn't able
    // to use it (the client doesn't have any interface pointers on the object).

    if ( FAILED(hrRet) )
        delete pMsgbox;

    return hrRet;
}

STDMETHODIMP CSimpleMsgBoxClassFactory::LockServer ( BOOL fLock )
{
    // Increase/decrease the DLL ref count, according to the fLock param.

    fLock ? g_uDllLockCount++ : g_uDllLockCount--;

    TRACE(">>> SimpleMsgBoxSvr: In CSimpleMsgBoxClassFactory::LockServer(), new DLL ref count = %d\n", g_uDllLockCount );
    
    return S_OK;
}


 

五.註冊COM組件(手動註冊)

萬事俱備,現在要將其信息寫入註冊表,

1.實現DllRegisterServer和DllUnregisterServer方法,並將方法聲明爲STDAPI,表明屬於導出函數

  1. // DllRegisterServer() creates the registy entries that tells COM where our   
  2. // server is located and its threading model.  
  3. STDAPI DllRegisterServer()  
  4. {  
  5. HKEY  hCLSIDKey = NULL, hInProcSvrKey = NULL;  
  6. LONG  lRet;  
  7. TCHAR szModulePath [MAX_PATH];  
  8. TCHAR szClassDescription[] = _T("SimpleMsgBox class");  
  9. TCHAR szThreadingModel[]   = _T("Apartment");  
  10.   
  11. __try  
  12.     {  
  13.     // Create a key under CLSID for our COM server.  
  14.   
  15.     lRet = RegCreateKeyEx ( HKEY_CLASSES_ROOT, _T("CLSID\\{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}"),  
  16.                             0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_CREATE_SUB_KEY,  
  17.                             NULL, &hCLSIDKey, NULL );  
  18.       
  19.     if ( ERROR_SUCCESS != lRet )   
  20.         return HRESULT_FROM_WIN32(lRet);  
  21.   
  22.     // The default value of the key is a human-readable description of the coclass.  
  23.   
  24.     lRet = RegSetValueEx ( hCLSIDKey, NULL, 0, REG_SZ, (const BYTE*) szClassDescription,  
  25.                            sizeof(szClassDescription) );  
  26.   
  27.     if ( ERROR_SUCCESS != lRet )  
  28.         return HRESULT_FROM_WIN32(lRet);  
  29.       
  30.     // Create the InProcServer32 key, which holds info about our coclass.  
  31.   
  32.     lRet = RegCreateKeyEx ( hCLSIDKey, _T("InProcServer32"), 0, NULL, REG_OPTION_NON_VOLATILE,  
  33.                             KEY_SET_VALUE, NULL, &hInProcSvrKey, NULL );  
  34.   
  35.     if ( ERROR_SUCCESS != lRet )  
  36.         return HRESULT_FROM_WIN32(lRet);  
  37.   
  38.     // The default value of the InProcServer32 key holds the full path to our DLL.  
  39.   
  40.     GetModuleFileName ( g_hinstThisDll, szModulePath, MAX_PATH );  
  41.   
  42.     lRet = RegSetValueEx ( hInProcSvrKey, NULL, 0, REG_SZ, (const BYTE*) szModulePath,   
  43.                            sizeof(TCHAR) * (lstrlen(szModulePath)+1) );  
  44.   
  45.     if ( ERROR_SUCCESS != lRet )  
  46.         return HRESULT_FROM_WIN32(lRet);  
  47.   
  48.     // The ThreadingModel value tells COM how it should handle threads in our DLL.  
  49.     // The concept of apartments is beyond the scope of this article, but for  
  50.     // simple, single-threaded DLLs, use Apartment.  
  51.   
  52.     lRet = RegSetValueEx ( hInProcSvrKey, _T("ThreadingModel"), 0, REG_SZ,  
  53.                            (const BYTE*) szThreadingModel,   
  54.                            sizeof(szThreadingModel) );  
  55.   
  56.     if ( ERROR_SUCCESS != lRet )  
  57.         return HRESULT_FROM_WIN32(lRet);  
  58.     }     
  59. __finally  
  60.     {  
  61.     if ( NULL != hCLSIDKey )  
  62.         RegCloseKey ( hCLSIDKey );  
  63.   
  64.     if ( NULL != hInProcSvrKey )  
  65.         RegCloseKey ( hInProcSvrKey );  
  66.     }  
  67.   
  68.     return S_OK;  
  69. }  
  70.   
  71. // DllUnregisterServer() deleted the registy entries that DllRegisterServer() created.  
  72. STDAPI DllUnregisterServer()  
  73. {  
  74.     // Delete our registry entries.  Note that you must delete from the deepest  
  75.     // key and work upwards, because on NT/2K, RegDeleteKey() doesn't delete   
  76.     // keys that have subkeys on NT/2K.  
  77.   
  78.     RegDeleteKey ( HKEY_CLASSES_ROOT, _T("CLSID\\{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}\\InProcServer32") );  
  79.     RegDeleteKey ( HKEY_CLASSES_ROOT, _T("CLSID\\{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}") );  
  80.   
  81.     return S_OK;  
  82. }  
// DllRegisterServer() creates the registy entries that tells COM where our 
// server is located and its threading model.
STDAPI DllRegisterServer()
{
HKEY  hCLSIDKey = NULL, hInProcSvrKey = NULL;
LONG  lRet;
TCHAR szModulePath [MAX_PATH];
TCHAR szClassDescription[] = _T("SimpleMsgBox class");
TCHAR szThreadingModel[]   = _T("Apartment");

__try
    {
    // Create a key under CLSID for our COM server.

    lRet = RegCreateKeyEx ( HKEY_CLASSES_ROOT, _T("CLSID\\{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}"),
                            0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_CREATE_SUB_KEY,
                            NULL, &hCLSIDKey, NULL );
    
    if ( ERROR_SUCCESS != lRet ) 
        return HRESULT_FROM_WIN32(lRet);

    // The default value of the key is a human-readable description of the coclass.

    lRet = RegSetValueEx ( hCLSIDKey, NULL, 0, REG_SZ, (const BYTE*) szClassDescription,
                           sizeof(szClassDescription) );

    if ( ERROR_SUCCESS != lRet )
        return HRESULT_FROM_WIN32(lRet);
    
    // Create the InProcServer32 key, which holds info about our coclass.

    lRet = RegCreateKeyEx ( hCLSIDKey, _T("InProcServer32"), 0, NULL, REG_OPTION_NON_VOLATILE,
                            KEY_SET_VALUE, NULL, &hInProcSvrKey, NULL );

    if ( ERROR_SUCCESS != lRet )
        return HRESULT_FROM_WIN32(lRet);

    // The default value of the InProcServer32 key holds the full path to our DLL.

    GetModuleFileName ( g_hinstThisDll, szModulePath, MAX_PATH );

    lRet = RegSetValueEx ( hInProcSvrKey, NULL, 0, REG_SZ, (const BYTE*) szModulePath, 
                           sizeof(TCHAR) * (lstrlen(szModulePath)+1) );

    if ( ERROR_SUCCESS != lRet )
        return HRESULT_FROM_WIN32(lRet);

    // The ThreadingModel value tells COM how it should handle threads in our DLL.
    // The concept of apartments is beyond the scope of this article, but for
    // simple, single-threaded DLLs, use Apartment.

    lRet = RegSetValueEx ( hInProcSvrKey, _T("ThreadingModel"), 0, REG_SZ,
                           (const BYTE*) szThreadingModel, 
                           sizeof(szThreadingModel) );

    if ( ERROR_SUCCESS != lRet )
        return HRESULT_FROM_WIN32(lRet);
    }   
__finally
    {
    if ( NULL != hCLSIDKey )
        RegCloseKey ( hCLSIDKey );

    if ( NULL != hInProcSvrKey )
        RegCloseKey ( hInProcSvrKey );
    }

    return S_OK;
}

// DllUnregisterServer() deleted the registy entries that DllRegisterServer() created.
STDAPI DllUnregisterServer()
{
    // Delete our registry entries.  Note that you must delete from the deepest
    // key and work upwards, because on NT/2K, RegDeleteKey() doesn't delete 
    // keys that have subkeys on NT/2K.

    RegDeleteKey ( HKEY_CLASSES_ROOT, _T("CLSID\\{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}\\InProcServer32") );
    RegDeleteKey ( HKEY_CLASSES_ROOT, _T("CLSID\\{7D51904E-1645-4a8c-BDE0-0F4A44FC38C4}") );

    return S_OK;
}


 

2.定義def文件

  1. EXPORTS  
  2.     DllRegisterServer   PRIVATE  
  3.     DllUnregisterServer PRIVATE  
  4.     DllGetClassObject   PRIVATE  
  5.     DllCanUnloadNow     PRIVATE  
EXPORTS
    DllRegisterServer   PRIVATE
    DllUnregisterServer PRIVATE
    DllGetClassObject   PRIVATE
    DllCanUnloadNow     PRIVATE


 

3.編譯通過後使用regsvr32命令,註冊此dll組件

在調用此com組件之前,必須通過cmd命令註冊,很重要,DllRegisterServer將會成爲入口點,

 

六.編寫DllGetClassObject

只有通過全局函數DllGetClassObject,纔可以創建類廠,這個方法com類庫會去調用,其會根據CLSID返回一個類工廠(一個dll可能會有多個com類)

生命週期(非常重要):

CoCreateInstance->CoGetClassObject->DllGetClassObject->IClassFactory->CreateInstance

  1. STDAPI DllGetClassObject ( REFCLSID rclsid, REFIID riid, void** ppv )  
  2. {  
  3. HRESULT hrRet;  
  4. CSimpleMsgBoxClassFactory* pFactory;  
  5.   
  6.     TRACE(">>> SimpleMsgBoxSvr: In DllGetClassObject()\n");  
  7.   
  8.     // Check that the client is asking for the CSimpleMsgBoxImpl factory.  
  9.   
  10.     if ( !InlineIsEqualGUID ( rclsid, __uuidof(CSimpleMsgBoxImpl) ))  
  11.         return CLASS_E_CLASSNOTAVAILABLE;  
  12.   
  13.     // Check that ppv really points to a void*.  
  14.   
  15.     if ( IsBadWritePtr ( ppv, sizeof(void*) ))  
  16.         return E_POINTER;  
  17.   
  18.     *ppv = NULL;  
  19.   
  20.     // Construct a new class factory object.  
  21.   
  22.     pFactory = new CSimpleMsgBoxClassFactory;  
  23.   
  24.     if ( NULL == pFactory )  
  25.         return E_OUTOFMEMORY;  
  26.   
  27.     // AddRef() the factory since we're using it.  
  28.   
  29.     pFactory->AddRef();  
  30.   
  31.     // QI() the factory for the interface the client wants.  
  32.   
  33.     hrRet = pFactory->QueryInterface ( riid, ppv );  
  34.       
  35.     // We're done with the factory, so Release() it.  
  36.   
  37.     pFactory->Release();  
  38.   
  39.     return hrRet;  
  40. }  
STDAPI DllGetClassObject ( REFCLSID rclsid, REFIID riid, void** ppv )
{
HRESULT hrRet;
CSimpleMsgBoxClassFactory* pFactory;

    TRACE(">>> SimpleMsgBoxSvr: In DllGetClassObject()\n");

    // Check that the client is asking for the CSimpleMsgBoxImpl factory.

    if ( !InlineIsEqualGUID ( rclsid, __uuidof(CSimpleMsgBoxImpl) ))
        return CLASS_E_CLASSNOTAVAILABLE;

    // Check that ppv really points to a void*.

    if ( IsBadWritePtr ( ppv, sizeof(void*) ))
        return E_POINTER;

    *ppv = NULL;

    // Construct a new class factory object.

    pFactory = new CSimpleMsgBoxClassFactory;

    if ( NULL == pFactory )
        return E_OUTOFMEMORY;

    // AddRef() the factory since we're using it.

    pFactory->AddRef();

    // QI() the factory for the interface the client wants.

    hrRet = pFactory->QueryInterface ( riid, ppv );
    
    // We're done with the factory, so Release() it.

    pFactory->Release();

    return hrRet;
}

七.調用com組件

  1. void DoMsgBoxTest(HWND hMainWnd)  
  2. {  
  3. ISimpleMsgBox* pIMsgBox;  
  4. HRESULT hr;  
  5.     hr = CoCreateInstance ( __uuidof(CSimpleMsgBoxImpl), NULL, CLSCTX_INPROC_SERVER,  
  6.                             __uuidof(ISimpleMsgBox), (void**) &pIMsgBox );  
  7.   
  8.     if ( FAILED(hr) )  
  9.         return;  
  10.   
  11.     pIMsgBox->DoSimpleMsgBox ( hMainWnd, _bstr_t("Hello COM!") );  
  12.   
  13.     pIMsgBox->Release();  
  14. }  
void DoMsgBoxTest(HWND hMainWnd)
{
ISimpleMsgBox* pIMsgBox;
HRESULT hr;
    hr = CoCreateInstance ( __uuidof(CSimpleMsgBoxImpl), NULL, CLSCTX_INPROC_SERVER,
                            __uuidof(ISimpleMsgBox), (void**) &pIMsgBox );

    if ( FAILED(hr) )
        return;

    pIMsgBox->DoSimpleMsgBox ( hMainWnd, _bstr_t("Hello COM!") );

    pIMsgBox->Release();
}

以上步驟不可以省略,可以看到創建一個com組件是比較麻煩的一個流程,很容易出錯

或者先常見一個類工廠

  1. HRESULT hr;  
  2. IClassFactory *pc=NULL;  
  3. hr=::CoGetClassObject(__uuidof(CSimpleMsgBoxImpl), CLSCTX_INPROC_SERVER,NULL,   
  4.     IID_IClassFactory, (void**) &pc );  
HRESULT hr;
IClassFactory *pc=NULL;
hr=::CoGetClassObject(__uuidof(CSimpleMsgBoxImpl), CLSCTX_INPROC_SERVER,NULL, 
    IID_IClassFactory, (void**) &pc );


 


 


 

 

 

 


 



 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章