您的位置:首页 > 其它

用ATL创建COM组件详细解说

2015-09-23 11:22 323 查看

用ATL创建COM组件详细解说

服务器interfacemicrosoftlibrarybasicobject
一、创建一个模型(工程) 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,其他七个编辑框的内容会自动生成。然后按确认按钮退出。

三、给组件增加方法(函数) MyF1、MyF2、MyF3、MyF4

在 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。

在对话框中放置四个按钮,分别为 MyF1、MyF2、MyF3和
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=8; char 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基础知识
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: