ACE与MFC集成示例

本文尽量简洁的介绍ACE与MFC的集成方式,以回复网友的提问。

1. 编译ACE的MFC版本

从DOC ACE网方网站下载的版本,并没有提供编译从mfc的版本。下面给出用MPC工具生成mfc版本的方法

以VC9 (Visual Studio 2008)为例

config.h

// -*- C++ -*-
#ifndef ACE_CONFIG_H
#define ACE_CONFIG_H
#define ACE_DISABLE_WIN32_ERROR_WINDOWS
#define ACE_DISABLE_WIN32_INCREASE_PRIORITY

#define ACE_HAS_NONSTATIC_OBJECT_MANAGER 1
#include "ace/config-win32.h"
#if defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
#undef ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER

#endif

#endif /* ACE_CONFIG_H */
 
cd %ACE_ROOT%
cd ace

mwc.pl -type vc9 -value_template "configurations =  'MFC Release' 'MFC Debug'" -features mfc=1  -name_modifier "*_mfc_vc9"  ACE.mwc

我们可以得到ace_mfc_vc9.sln

用Visual Studio 2008打开编译,我们可以得到 ACEmfcd.lib,ACEmfcd.lib

2. 编写ACE的初始化

MFC程序入口并不是main函数,因此需要手工初始化(init)和结束化(fini)操作

通常可以在MFC的 App:InitInstance()和App:ExitInstance()中分别调用。

本例为了简化和代码可复用,编写了一个初始化的类,可以以全局或作为App的成员,用来确保有ACE的生命期比App类的生命期更长。

代码ACEInitor.h/cpp,分别如下

/*
file: ACEInitor.h
author: Stone Jiang <jiangtao>
blog:    http://www.tao-studio.net/blog
*/</jiangtao>

#ifndef ACEInitor_h__
#define ACEInitor_h__
//class ACEInitor
class ACEInitor_T
{
public:
   ACEInitor_T();
   ~ACEInitor_T();
};
#endif // ACEInitor_h__
//file: ACEInitor.cpp
#include "ACEInitor.h"
#include "ace/ACE.h"

ACEInitor_T::ACEInitor_T()
{
	ACE::init();
	TRACE("ACEInitor_T::ACEInitor_T()\n");
}

ACEInitor_T::~ACEInitor_T()
{
	ACE::fini();
	TRACE("ACEInitor_T::~ACEInitor_T()\n");

}

我们这里反ACEInitor类实例g_ACEInit作为全局函数,放在theApp之前,来保证它的生命期比theApp更长。

代码片如下 (ACEwithMFC.cpp Ln 38)

image

3. 编写运行Reactor事件循环的线程

3.1 编写线程代码

我们有多种方式开一个线程,本例采用从ACE_Task_Base派生子类的方式来创建线程

类名:ACEReactorThread_T (本站的编码风格采用ClassName_T表示类名,蛮多的公司采用呢,关于编码风格我们还不在这里讨论,总之,MFC的匈牙利风格有太多的缺点)

/*
file:  ACEReactorThread.h
author: Stone Jiang <jiangtao>
blog:    http://www.tao-studio.net/blog
*/</jiangtao>

#ifndef ACEReactorThread_h__
#define ACEReactorThread_h__
#include "ace/Task.h"
#include "ace/Reactor.h"
class ACEReactorThread_T : public ACE_Task_Base
{
public:
	ACEReactorThread_T(ACE_Reactor* r = ACE_Reactor::instance());
	virtual ~ACEReactorThread_T();

 
    virtual int open (void *args = 0);
	virtual int svc(void);
 
    ACE_Reactor*  reactor();
	void reactor(ACE_Reactor* r);

	void stop();

private:
   ACE_Reactor*  reactor_;
};

#endif // ACEReactorThread_h__

3.2 启动线程和结束线程

App::InitInstance()中

	this->aceThread_ = new ACEReactorThread_T();
	this->aceThread_->open();

App::ExintInstance()中

	this->aceThread_->stop();

	aceThread_->wait();
	delete aceThread_;
	aceThread_ = 0;

4. 编写ACE事件,并注册进Reactor中

4.1 编写事件

本例与定时器事件为例(这是比较简单的事件)

/*
   file:  MyTimerEventHandler.h
   author: Stone Jiang <jiangtao>
   blog:    http://www.tao-studio.net/blog
*/</jiangtao>

#ifndef MYTIMEREVENTHANDER_H__
#define MYTIMEREVENTHANDER_H__
#include "ace/Event_Handler.h"
class CACEwithMFCDlg;
class MyTimerEventHandler_T : public ACE_Event_Handler
{
public:
	MyTimerEventHandler_T(CACEwithMFCDlg* pMainWnd);
	~MyTimerEventHandler_T();
public:
	virtual int handle_timeout (const ACE_Time_Value &,
		const void *arg);

private:
	CACEwithMFCDlg* mainWnd_;
};
 
#endif // MYTIMEREVENTHANDER_H__
由于想把事件与主窗口进行交流,所以类MyTimerEventHandler与CACEwithMFCDlg

互相依赖。其中, MyTimerEventHandler与CACEwithMFCDlg是聚合(Aggregation)关系,用UML画出来如下图

image

4.2 注册事件到反应器

MFC在响应按钮事件的时候,创建事件,并注册到反应器中

void CACEwithMFCDlg::OnBnClickedButtonTimer()
{
	// TODO: Add your control notification handler code here
	if (this->hander_ == 0)
	{
		this->hander_ = new MyTimerEventHandler_T(this);
		ACE_Reactor* r = theApp.reactor();
		ACE_Time_Value tv(2,0);
		r->schedule_timer(this->hander_,0,tv,tv);
	}

	
}

注册事件成功后,MyTimerEventHandler::handle_timeout()将入约被Reactor框架回调

handle_timeout生成一个字符串,调用主窗口,将字符串显示在列表框中。

int MyTimerEventHandler_T::handle_timeout(const ACE_Time_Value &,
                                          const void *)
{
	static int x = 0;
	char msg[MAX_PATH] = {0};
	ACE_OS::sprintf(msg,"On My Timer Event %d",x++);
	this->mainWnd_->log(msg);
	return 0;
}

当窗口销毁时,我们将事件从反应器中拆除

void CACEwithMFCDlg::OnDestroy()
{
	if (this->hander_)
	{
        ACE_Reactor* r = theApp.reactor();
		r->cancel_timer(this->hander_);
		delete this->hander_;
		this->hander_ = 0;
	}
	CDialog::OnDestroy();

	// TODO: Add your message handler code here
}

5. 运行界面图

image

6. 下载源代码

请从本站bbs中下载源代码

http://www.tao-studio.net/bbs

如需要更多帮助,请致邮件 jiangtao@tao-studio.net.

Stone Jiang

2008-12-16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值