用ATL创建COM组件详细解说

用ATL创建COM组件详细解说


一、创建一个模型 ( 工程 ) MyProj
二、给模型 ( 工程 ) 增加一个组件 MyCom
三、给组件增加方法 ( 函数 ) MyF1 MyF2 MyF3 MyF4


一、创建模型(工程) MyProj
VC++6.0工作平台中,点击菜单 File下的 New 菜单项,在出现的 New 对话框中选中 Projects 卡片,在列表框中选中 ATL COM  AppWizard(活动模板库组件导航)。  

Project Name 编辑框中输入项目名如 MyProj ,并选择合适的 Location 后,按确认按钮进入下一个对话框:ATL  COM  Appwizard  -  step 1 of  1,在 Server Type中选择 Dynamic  Link  Library [ DLL ],即进程内服务器,这是最快的组件。
选中 Support  MFC选择项。
在按下 Finish Ok 按钮后,一个组件的框架已经建立。


二、给模型增加组件MyCom
VC++ 菜单 Insert 中选中 New ATL  Object…菜单项,出现 ATL Object  Wizard对话框。
在左边的 Category中选择 Objects,右边的 Objects中选中 Simple  Object项。按 Next 按钮。

在出现的 ATL Object  Wizard属性对话框中 Names卡片中的八个编辑框中左上方的 Short Name编辑框中输入短名如 MyCom,其他七个编辑框的内容会自动生成。然后按确认按钮退出。


三、给组件增加方法(函数) MyF1MyF2MyF3MyF4
VC++工作平台的左边的 Workspace ClassView卡片中找到接口 IMyCom项,按右键,在出现的快捷菜单中选择 Add  Method …,出现 Add  Method  to Interface对话框,在对话框中输入要增加的函数的函数名、参数和返回值类型。然后,按确认按钮退出。

先增加函数 MyF1
  
函数名为: MyF1
  
参数:无

MyCom.cpp文件中插入代码:
STDMETHODIMP CMyCom::MyF1()
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())

 // TODO: Add your implementation code here
 AfxMessageBox("
欢迎使用我的组件");
 return S_OK;
}

用同样的方法给组件增加函数MyF2
函数名为: MyF2
参数为:
  [in] BSTR str,
  [out, retval] int* val

插入代码:
STDMETHODIMP CMyCom::MyF2(BSTR str, int *val)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())

 // TODO: Add your implementation code here
 CString  sStr(str);
 int  n = sStr.GetLength();
 *val = n;
 return S_OK;
}

用同样的方法给组件增加函数 MyF3
函数名为: MyF3
参数为:
  [in] BSTR str,
  [out, retval] BSTR* retstr

插入代码:
STDMETHODIMP CMyCom::MyF3(BSTR str, BSTR *retstr)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())

 // TODO: Add your implementation code here
 CString sStr(str);
 CString sRetstr = "
组件收到你的信息:<" + sStr + ">\n特此告之。";
 CComBSTR  temp(sRetstr);
 *retstr = temp;
 return S_OK;
}

用同样的方法给组件增加函数MyF4
函数名为: MyF4
参数为:
  [in] int x,
  [out, retval] int* val

插入代码:
STDMETHODIMP CMyCom::MyF4(int x, int *val)
{
 AFX_MANAGE_STATE(AfxGetStaticModuleState())

 // TODO: Add your implementation code here
 *val = x+1;
 return S_OK;
}

编绎工程,生成组件DLL。

如果是在 Win2k 或者 WinXp 的计算机上完成了上面的三步操作,就会在 debug子目录下生成组件的 DLL文件,并且完成自动注册。但是在 Win98的计算机上,注册要运行如下命令才能完成:
regsrv32  C:\MyProj\Debug\MyProj.dll



创建 COM 组件客户


1,创建一个基于对话框的客户程序。
2
,把服务器类型库导入客户工作平台。
3
,初始化 COM 库。
4
,获得服务器的 GLSID
5
,创建 COM 组件服务器组件的实例。
6
,使用 COM 对象。
7
,终止 COM 库。


1,创建一个客户程序
MFC  AppWizard ( exe )创建一个基于对话框的应用程序 MyExe
在对话框中放置四个按钮,分别为 MyF1MyF2MyF3 MyF4
ClassWizard生成单击按钮的四个响应函数 OnMyF1()OnMyF2() OnMyF3() OnMyF4()


2
,把服务器类型库导入客户
2-1
StdAfx.h文件中加入代码:

#import  "..\MyProj\MyProj.tlb"

最后的StdAfx.h文件如下:
//  stdafx.h : include file for standard system include files,
//   or project specific include files that are used frequently, but
//       are changed infrequently
//

#if  !defined(AFX_STDAFX_H__2B646017_28AD_4CDE_9792_CB8F9A5C6B39__INCLUDED_)
#define  AFX_STDAFX_H__2B646017_28AD_4CDE_9792_CB8F9A5C6B39__INCLUDED_

#if  _MSC_VER > 1000
#pragma once
#endif   //  _MSC_VER > 1000

#define  VC_EXTRALEAN   //  Exclude rarely-used stuff from Windows headers

#include 
< afxwin.h >           //  MFC core and standard components
#include  < afxext.h >           //  MFC extensions
#include  < afxdisp.h >          //  MFC Automation classes
#include  < afxdtctl.h >    //  MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include 
< afxcmn.h >     //  MFC support for Windows Common Controls
#endif   //  _AFX_NO_AFXCMN_SUPPORT

#import  
" ..\MyProj\MyProj.tlb "

// {{AFX_INSERT_LOCATION}}
//  Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif   //  !defined(AFX_STDAFX_H__2B646017_28AD_4CDE_9792_CB8F9A5C6B39__INCLUDED_)


编译 StdAfx.cpp
这样在客户端的debug目录下生成组件的类型库头文件(.tlh)和类型库实现文件(.tli)

2-2在使用组件的源文件上方使用名字空间,最后的源文件上面部分代码如下

// MyExeDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MyExe.h"
#include "MyExeDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

using namespace MYPROJLib;

以下代码略

 

3,初始化 COM
HRESULT hr=CoInitialize(NULL);


4
,获得服务器组件的 CLSID
CLSID  clsid; 
hr=CLSIDFromProgID(OLESTR("MyProj.MyCom"),&clsid);

if(FAILED(hr))

{

         AfxMessageBox("COM Failed");

         return;

}


5
,创建 COM 服务器组件实例,获得组件接口指针
IMyCom  *ptr = NULL;
hr=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IMyCom),(LPVOID*)&ptr); 


6-1
,在OnMyF1()中使用 COM对象 MyF1()

ptr->MyF1();
ptr->Release(); //
释放实例


6-2
,在OnMyF2()中使用 COM对象 MyF2()
char str[32];

sprintf(str,"Len=%d",ptr->MyF2("abcdefg"));

AfxMessageBox(str);

ptr->Release();// 释放实例


6-3
,在OnMyF3()中使用 COM对象 MyF3()
AfxMessageBox(ptr->MyF3("abcdefg"));

ptr->Release(); // 释放实例


6-4
,在OnMyF4()中使用 COM对象 MyF4()

int x=8; char str[32];

sprintf(str,"x=%d,x+1=%d",x,ptr->MyF4(x));

AfxMessageBox(str);

ptr->Release();// 释放实例

7
,终止 COM
CoUninitialize();

 

下面为客户测试端四个函数的完整代码。

//  MyExeDlg.cpp : implementation file

//

 

#include 
" stdafx.h "

#include 
" MyExe.h "

#include 
" MyExeDlg.h "

 

#ifdef _DEBUG

#define  new DEBUG_NEW

#undef  THIS_FILE

static   char  THIS_FILE[]  =  __FILE__;

#endif

 

using   namespace  MYPROJLib;

/////

//  CAboutDlg dialog used for App About

 

class  CAboutDlg :  public  CDialog

{

public:

         CAboutDlg();

 

// Dialog Data

         
//{{AFX_DATA(CAboutDlg)

         
enum { IDD = IDD_ABOUTBOX };

         
//}}AFX_DATA

 

         
// ClassWizard generated virtual function overrides

         
//{{AFX_VIRTUAL(CAboutDlg)

         
protected:

         
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

         
//}}AFX_VIRTUAL

 

// Implementation

protected:

         
//{{AFX_MSG(CAboutDlg)

         
//}}AFX_MSG

         DECLARE_MESSAGE_MAP()

}
;

 

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

         
//{{AFX_DATA_INIT(CAboutDlg)

         
//}}AFX_DATA_INIT

}


 

void  CAboutDlg::DoDataExchange(CDataExchange *  pDX)

{

         CDialog::DoDataExchange(pDX);

         
//{{AFX_DATA_MAP(CAboutDlg)

         
//}}AFX_DATA_MAP

}


 

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

         
// {{AFX_MSG_MAP(CAboutDlg)

                   
//  No message handlers

         
// }}AFX_MSG_MAP

END_MESSAGE_MAP()

 

/////

//  CMyExeDlg dialog

 

CMyExeDlg::CMyExeDlg(CWnd
*  pParent  /*=NULL*/ )

         : CDialog(CMyExeDlg::IDD, pParent)

{

         
//{{AFX_DATA_INIT(CMyExeDlg)

                   
// NOTE: the ClassWizard will add member initialization here

         
//}}AFX_DATA_INIT

         
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32

         m_hIcon 
= AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}


 

void  CMyExeDlg::DoDataExchange(CDataExchange *  pDX)

{

         CDialog::DoDataExchange(pDX);

         
//{{AFX_DATA_MAP(CMyExeDlg)

                   
// NOTE: the ClassWizard will add DDX and DDV calls here

         
//}}AFX_DATA_MAP

}


 

BEGIN_MESSAGE_MAP(CMyExeDlg, CDialog)

         
// {{AFX_MSG_MAP(CMyExeDlg)

         ON_WM_SYSCOMMAND()

         ON_WM_PAINT()

         ON_WM_QUERYDRAGICON()

         ON_BN_CLICKED(IDC_BUTTON1, OnMyF1)

         ON_BN_CLICKED(IDC_BUTTON2, OnMyF2)

         ON_BN_CLICKED(IDC_BUTTON3, OnMyF3)

         ON_BN_CLICKED(IDC_BUTTON4, OnMyF4)

         
// }}AFX_MSG_MAP

END_MESSAGE_MAP()

 

/////

//  CMyExeDlg message handlers

 

BOOL CMyExeDlg::OnInitDialog()

{

         CDialog::OnInitDialog();

 

         
// Add "About" menu item to system menu.

 

         
// IDM_ABOUTBOX must be in the system command range.

         ASSERT((IDM_ABOUTBOX 
& 0xFFF0== IDM_ABOUTBOX);

         ASSERT(IDM_ABOUTBOX 
< 0xF000);

 

         CMenu
* pSysMenu = GetSystemMenu(FALSE);

         
if (pSysMenu != NULL)

         
{

                   CString strAboutMenu;

                   strAboutMenu.LoadString(IDS_ABOUTBOX);

                   
if (!strAboutMenu.IsEmpty())

                   
{

                            pSysMenu
->AppendMenu(MF_SEPARATOR);

                            pSysMenu
->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

                   }


         }


 

         
// Set the icon for this dialog.  The framework does this automatically

         
//  when the application's main window is not a dialog

         SetIcon(m_hIcon, TRUE);                            
// Set big icon

         SetIcon(m_hIcon, FALSE);                  
// Set small icon

         

         
// TODO: Add extra initialization here

         

         
return TRUE;  // return TRUE  unless you set the focus to a control

}


 

void  CMyExeDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

         
if ((nID & 0xFFF0== IDM_ABOUTBOX)

         
{

                   CAboutDlg dlgAbout;

                   dlgAbout.DoModal();

         }


         
else

         
{

                   CDialog::OnSysCommand(nID, lParam);

         }


}


 

//  If you add a minimize button to your dialog, you will need the code below

//   to draw the icon.  For MFC applications using the document/view model,

//   this is automatically done for you by the framework.

 

void  CMyExeDlg::OnPaint() 

{

         
if (IsIconic())

         
{

                   CPaintDC dc(
this); // device context for painting

 

                   SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 
0);

 

                   
// Center icon in client rectangle

                   
int cxIcon = GetSystemMetrics(SM_CXICON);

                   
int cyIcon = GetSystemMetrics(SM_CYICON);

                   CRect rect;

                   GetClientRect(
&rect);

                   
int x = (rect.Width() - cxIcon + 1/ 2;

                   
int y = (rect.Height() - cyIcon + 1/ 2;

 

                   
// Draw the icon

                   dc.DrawIcon(x, y, m_hIcon);

         }


         
else

         
{

                   CDialog::OnPaint();

         }


}


 

//  The system calls this to obtain the cursor to display while the user drags

//   the minimized window.

HCURSOR CMyExeDlg::OnQueryDragIcon()

{

         
return (HCURSOR) m_hIcon;

}


 

void  CMyExeDlg::OnMyF1() 

{

         
// TODO: Add your control notification handler code here

         HRESULT hr
=CoInitialize(NULL);

         CLSID  clsid; 

         hr
=CLSIDFromProgID(OLESTR("MyProj.MyCom"),&clsid);

         
if(FAILED(hr))

         
{

                   AfxMessageBox(
"COM Failed");

                   
return;

         }


         IMyCom  
*ptr = NULL;

         hr
=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IMyCom),(LPVOID*)&ptr); 

         ptr
->MyF1();

         ptr
->Release(); // 释放实例

         CoUninitialize();

}


 

void  CMyExeDlg::OnMyF2() 

{

         
// TODO: Add your control notification handler code here

         HRESULT hr
=CoInitialize(NULL);

         CLSID  clsid; 

         hr
=CLSIDFromProgID(OLESTR("MyProj.MyCom"),&clsid);

         
if(FAILED(hr))

         
{

                   AfxMessageBox(
"COM Failed");

                   
return;

         }


         IMyCom  
*ptr = NULL;

         hr
=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IMyCom),(LPVOID*)&ptr); 

         
char str[32];

         sprintf(str,
"Len=%d",ptr->MyF2("abcdefg"));

         AfxMessageBox(str);

         ptr
->Release();// 释放实例

         CoUninitialize();

}


 

void  CMyExeDlg::OnMyF3() 

{

         
// TODO: Add your control notification handler code here

         HRESULT hr
=CoInitialize(NULL);

         CLSID  clsid; 

         hr
=CLSIDFromProgID(OLESTR("MyProj.MyCom"),&clsid);

         
if(FAILED(hr))

         
{

                   AfxMessageBox(
"COM Failed");

                   
return;

         }


         IMyCom  
*ptr = NULL;

         hr
=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IMyCom),(LPVOID*)&ptr); 

         AfxMessageBox(ptr
->MyF3("abcdefg"));

         ptr
->Release(); // 释放实例

         CoUninitialize();

}


 

void  CMyExeDlg::OnMyF4() 

{

         
// TODO: Add your control notification handler code here

         HRESULT hr
=CoInitialize(NULL);

         CLSID  clsid; 

         hr
=CLSIDFromProgID(OLESTR("MyProj.MyCom"),&clsid);

         
if(FAILED(hr))

         
{

                   AfxMessageBox(
"COM Failed");

                   
return;

         }


         IMyCom  
*ptr = NULL;

         hr
=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,__uuidof(IMyCom),(LPVOID*)&ptr); 

         
int x=8char str[32];

         sprintf(str,
"x=%d,x+1=%d",x,ptr->MyF4(x));

         AfxMessageBox(str);

         ptr
->Release();// 释放实例

         CoUninitialize();

}


 

 

通过这个简单的例子,我们做了最简单的COM组件,及测试组件的客户端,在这里只是教大家如何用VC ATL做COM组件,在接下来这一篇里Developing COM Components using VC-ATL(2)将对COM的基本原理进行介绍,以及对这一例子的源代码进行剖析。
                                                                                                       COM
基础知识


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值