使用COM组件的几种方法

1

 

void CUse1Dlg::OnBnClickedButton1()
{
 ::CoInitialize( NULL );

 IUnknown * pUnk = NULL;
 IFun * pFun = NULL;
 HRESULT hr;

 try
 {
  hr = ::CoCreateInstance(
   CLSID_Fun,
   NULL,
   CLSCTX_INPROC_SERVER, // 以进程内组件 DLL 方式加载
   IID_IUnknown,   // 想要取得 IUnknown 接口指针
   (LPVOID *) &pUnk);
  if( FAILED( hr ) ) throw( _T("没注册吧?") );

  hr = pUnk->QueryInterface( // 从 IUnknown 得到其它接口指针
   IID_IFun,    // 想要取得 IFun 接口指针
   (LPVOID *)&pFun );
  if( FAILED( hr ) ) throw( _T("居然没有接口?") );

  long nSum;
  hr = pFun->Add( 1, 2, &nSum ); // IFun::Add()
  if( SUCCEEDED( hr ) )
  {
   CString sMsg;
   sMsg.Format( _T("1 + 2 = %d"), nSum );
   AfxMessageBox( sMsg );
  }

  BSTR s1 = ::SysAllocString( L"Hello" );
  BSTR s2 = ::SysAllocString( L" world" );
  BSTR s3 = NULL;

  hr = pFun->Cat( s1, s2, &s3 ); // IFun::Cat()
  if( SUCCEEDED( hr ) )
  {
   CString sMsg( s3 );
   AfxMessageBox( sMsg );
  }
  
  // IFun::Cat() 最后一个参数是 [out] 方向属性,因此需要调用者释放
  if( s3 ) ::SysFreeString( s3 );
 }
 catch( LPCTSTR lpErr )
 {
  AfxMessageBox( lpErr );
 }

 if( pUnk ) pUnk->Release();
 if( pFun ) pFun->Release();

 ::CoUninitialize();
}

// 包含使用 CComBSTR 需要的头文件
#include <atlbase.h>

void CUse1Dlg::OnBnClickedButton2()
{
 ::CoInitialize( NULL );

 IFun * pFun = NULL;
 HRESULT hr;

 try
 {
  hr = ::CoCreateInstance(
   CLSID_Fun,
   NULL,
   CLSCTX_INPROC_SERVER,
   IID_IFun,    // 不再经过 IUnknown, 直接得到 IFun 接口指针
   (LPVOID *) &pFun);
  if( FAILED( hr ) ) throw( _T("没注册吧 或 没有接口?") );

  long nSum;
  hr = pFun->Add( 1, 2, &nSum );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg;
   sMsg.Format( _T("1 + 2 = %d"), nSum );
   AfxMessageBox( sMsg );
  }

  CComBSTR s1( "Hello" );  // 不再使用 API 方式操作 BSTR
  CComBSTR s2( " world" ); // 使用 CComBSTR 比较简单,并且
  CComBSTR s3;    // 最大的好处是,不用咱们自己来释放

  hr = pFun->Cat( s1, s2, &s3 );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg( s3 );
   AfxMessageBox( sMsg );
  }
 }
 catch( LPCTSTR lpErr )
 {
  AfxMessageBox( lpErr );
 }

 if( pFun ) pFun->Release();

 ::CoUninitialize(); 
}

 

2

 

void CUse2Dlg::OnBnClickedButton3() // CComPtr 使用举例
{
 // COM 初始化 以 AfxOleInit() 函数调用,放在了 CUse2App::InitInstance() 中了。

 CComPtr < IUnknown > spUnk;  // 定义 IUnknown 智能指针
 CComPtr < IFun > spFun;   // 定义 IFun 智能指针
 HRESULT hr;

 try
 {
  // 可以用 CLSID 启动组件,也可以用 ProgID
  hr = spUnk.CoCreateInstance( CLSID_Fun );
  if( FAILED( hr ) ) throw( _T("没有注册组件吧?") );

  hr = spUnk.QueryInterface( &spFun );
  if( FAILED( hr ) ) throw( _T("居然没有接口?") );

  long nSum;
  hr = spFun->Add( 1, 2, &nSum );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg;
   sMsg.Format( _T("1 + 2 = %d"), nSum );
   AfxMessageBox( sMsg );
  }

  CComBSTR s1( "Hello" ), s2( " world" ), s3;
  hr = spFun->Cat( s1, s2, &s3 );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg( s3 );
   AfxMessageBox( sMsg );
  }
 }
 catch( LPCTSTR lpErr )
 {
  AfxMessageBox( lpErr );
 }

 // 智能接口指针的最大好处是,我们不用负责释放
}

void CUse2Dlg::OnBnClickedButton4() // CComQIPtr 使用举例
{
 CComPtr < IUnknown > spUnk;  // 智能指针 IUnknown
 CComQIPtr < IFun > spFun;  // 智能指针 IFun
 HRESULT hr;

 try
 {
  // 使用 ProgID 启动组件
  hr = spUnk.CoCreateInstance( L"Simple2.fun.1" );
  if( FAILED( hr ) ) throw( _T("没有注册吧?") );

  spFun = spUnk; // CComQIPtr 会帮我们自动调用 QueryInterface
  if( !spFun ) throw( _T("居然没有接口?") ); // 成功与否可以判断 非NULL

  long nSum;
  hr = spFun->Add( 1, 2, &nSum );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg;
   sMsg.Format( _T("1 + 2 = %d"), nSum );
   AfxMessageBox( sMsg );
  }

  CComBSTR s1( "Hello" ), s2( " world" ), s3;
  hr = spFun->Cat( s1, s2, &s3 );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg( s3 );
   AfxMessageBox( sMsg );
  }
 }
 catch( LPCTSTR lpErr )
 {
  AfxMessageBox( lpErr );
 }

}

void CUse2Dlg::OnBnClickedButton5()  // 不再经过 IUnknown
{
 CComQIPtr < IFun, &IID_IFun > spFun;  // 定义 IFun 智能指针
 HRESULT hr;

 try
 {
  hr = spFun.CoCreateInstance( L"Simple2.fun.1" );
  if( FAILED( hr ) ) throw( _T("没有注册组件 或 没有找到接口") );

  long nSum;
  hr = spFun->Add( 1, 2, &nSum );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg;
   sMsg.Format( _T("1 + 2 = %d"), nSum );
   AfxMessageBox( sMsg );
  }

  CComBSTR s1( "Hello" ), s2( " world" ), s3;
  hr = spFun->Cat( s1, s2, &s3 );
  if( SUCCEEDED( hr ) )
  {
   CString sMsg( s3 );
   AfxMessageBox( sMsg );
  }
 }
 catch( LPCTSTR lpErr )
 {
  AfxMessageBox( lpErr );
 }
}

3

 

void CUse3Dlg::OnBnClickedButton6()  // 智能指针的释放
{
 //::CoInitialize( NULL );  // 如果在这里进行 COM 初始化,要注意智能指针的释放

 CComQIPtr < IFun, &IID_IFun > spFun;

 HRESULT hr = spFun.CoCreateInstance( CLSID_Fun );
 ASSERT( SUCCEEDED( hr ) );
 // 为了简单起见,不再使用 if 判断 HRESULT 了。IFun::Add() 也没有调用

 CComBSTR s1( "Hello" ), s2( " world" ), s3;
 hr = spFun->Cat( s1, s2, &s3 );
 ASSERT( SUCCEEDED( hr ) );
 CString sMsg( s3 );
 AfxMessageBox( sMsg );

// spFun->Release(); // 大错特错!!!
 //spFun.Release(); // 正解

 //::CoUninitialize();
}
 4

 

void CUse4Dlg::OnBnClickedButton7()  // #import 的使用
{
/**********************************************************
1. 在CUse4App::InitInstance() 中使用 AfxOleInit() 进行初始化
2. 打开 stdafx.h 文件,插入 #import ,后编译
   产生 .tlh 和 .tlh 的智能指针包装
3. #import 使用了 no_namespace 表示不使用命名空间
4. 智能指针的包装形式是:IxxxPtr,xxx 表示接口名
***********************************************************/
 IFunPtr spFun;
 HRESULT hr = spFun.CreateInstance( L"Simple2.fun.1" ); // 使用 ProgID
// HRESULT hr = spFun.CreateInstance( __uuidof( Fun ) ); // 使用 CLSID
 ASSERT( SUCCEEDED( hr ) );

 try
 {
  long nSum = spFun->Add( 1, 2 );

  CString sMsg;
  sMsg.Format( _T("1+2=%d"), nSum );
  AfxMessageBox( sMsg );

  _bstr_t sCat = spFun->Cat( _T("Hello"), _T(" world") );
  AfxMessageBox( sCat );
 }
 catch( _com_error &e )
 {
  // 在这里可以取得详细的错误信息
  // 以后在介绍 ISupportErrorInfo 接口时详细说明
//  e.Description();
//  e.ErrorMessage();
//  e.ErrorInfo();
//  ......
  e; // 由于没有使用 e, 加上这行只是为了取消编译警告
  AfxMessageBox( _T("Error") );
 }
}

 


 5

void CUse5Dlg::OnBnClickedButton8()
{
 // 由于在 stdafx.h 中 #import 的时候,没有使用 no_namespace 因此要使用命名空间
 // 命名空间叫 Simple2Lib ,这个名称是组件 IDL 文件 Library 指定的
 try
 {
  // 这次使用智能指针的构造函数启动组件,书写简单。
  // 但也有缺点,因为如果失败的话,不知道错误原因

//  Simple2Lib::IFunPtr spFun( L"Simple2.fun.1" );    // ProgID 方式
  Simple2Lib::IFunPtr spFun( __uuidof(Simple2Lib::Fun) );  // CLSID 方式

  long nSum = spFun->Add( 1, 2 );

  CString sMsg;
  sMsg.Format( _T("1+2=%d"), nSum );
  AfxMessageBox( sMsg );

  _bstr_t sCat = spFun->Cat( _T("Hello"), _T(" world") );
  AfxMessageBox( sCat );
 }
 catch( _com_error &e )
 {
  e;
  AfxMessageBox( _T("Error") );
 }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值