好吧,扯了这些大家也算是对为什么我们要在这里写一个基类有所理解了,如我们一开始所说,这个基类几乎不干什么有用的事,他只是提供了一个方便性而已,让MDx11Window和MWindow拥有一套相同的事件处理方式而已。
//==============================================================================
#pragma once
#include 'MReflection.h'
//----------------------------------------------
// 框架基础类
//----------------------------------------------
class MObject
{
DECLARE_CLASS(MObject) // 如果想要动态创建,就需要使用该宏
public:
MObject();
virtual ~MObject();
MObject(const MObject&) = delete;
MObject& operator=(const MObject&) = delete;
public:
std::shared_ptr std::shared_ptr void Clear(); //================================================= // 下面的都是虚函数 // 根据不同情况进行改写 //================================================= public: virtual const MDx11String& GetContexData() const; virtual void SetContexData(const MDx11String& contex); virtual MDx11String ToString() const; virtual void Show(); virtual void Update(); //================================================ // 只有子类才能够访问的信息 //================================================ protected: std::shared_ptr //=============================================== // 友员函数,对流输出的支持 //=============================================== friend std::ostream& operator<(std::ostream& os,const="" mobject&="">(std::ostream&> os<><><><> return os; } MDx11String mContexData; }; //=========================================================== 对于所有的MObject派生的对象,我们是禁止拷贝和复制,mClassFactory这是我们在动态创建对象的时候所以使用的,mContexData我们用来保存空间信息的对象,比如保存一个文本框的所有内容,一个按钮的名字,一个列表控件的信息等等,而MDx11String这是一个字符串类,以前我们曾经介绍过一个MString的字符串类,而这个Frame原本我们使用的就是MString,但是后来发现在我们自己处理输入的情况的时候显得无法满足于是在MString的基础上重新架构了MDx11String,MDx11String不仅对MString兼容还同时对unicode字符的支持,而且修改了一些核心函数的实现方式,使得MDx11String有更好的鲁棒性(测试到现在没有发生任何运行问题)。 //=========================================================== #include 'MObject.h' IMPLEMENT_CLASS(MObject) MObject::MObject() { mClassFactory = MClassFactory::Instance(); } MObject::~MObject() { } void MObject::RegistProperty() { } std::shared_ptr { return mClassFactory; } std::shared_ptr return mClassFactory; } const MDx11String& MObject::GetContexData() const{ return mContexData; } void MObject::SetContexData(const MDx11String& contex){ mContexData = contex; } void MObject::Clear() { mContexData.clear(); } MObject::operator MDx11String() const { return this->ToString(); } MDx11String MObject::ToString() const { return this->MObjectName; } void MObject::Show() { } void MObject::Update() { } //=============================================== 关于实现相当的简单,没啥可说,就是在构造函数中将我们的MClassFactory进行实例化即可。和MObject一样通用的是另一个类——事件处理类,在这个Frame中我们的事件管理使用的boost里面的signal,大家还记得吗?如果忘记的话可以回头去看看我们说的boost的信号槽。在这个事件管理类里面我们仅仅对四个参数一下的事件进行管理,当然还是可以扩展的,但是因为没有多少场合会是应用超过4个参数的事件回调函数,而传递的参数我们使用的是boost的any类型,any,顾名思义他可以是任意的类型,但是需要付出的代价是在我们写回调函数的时候需要对参数进行转换,而转换函数便是AnyTypeCast,如果转换成功我们就获取参数的指针,如果不成功就是一个未初始化的opional,这个是不能使用的。 //=============================================== #pragma once //========================================================= // 该类用来管理事件的处理状态 // 当然可以直接使用MKeyEvent 和 MMouseEvent进行处理事件 //========================================================= #include #include 'MReflection.h' #include #include #include #include class MObject; //---------------------------------------------- // 事件回掉函数 //---------------------------------------------- typedef const boost::any& AnyType; // 使用下面的转换函数可以转换到正确的类型 //--------------------------------------------------------- // 需要对返回结果进行判断是否转换成功 //--------------------------------------------------------- template boost::optional try{ return boost::optional } catch (boost::bad_any_cast e){ return boost::optional } } //--------------------------------------------------------------- // 定义几种事件驱动类型 //--------------------------------------------------------------- typedef boost::signals2::signal typedef boost::signals2::signal typedef boost::signals2::signal typedef boost::signals2::signal typedef boost::signals2::signal //----------------------------------------------------------------- // 能够被执行回调操作的函数类型 //----------------------------------------------------------------- typedef boost::function typedef boost::function typedef boost::function typedef boost::function typedef boost::function typedef boost::signals2::connection ConnectStatus; // 管理连接状态 typedef boost::signals2::shared_connection_block SharedConnectedBlock; // 阻塞连接 class MEventHandle { public: MEventHandle(); virtual ~MEventHandle(); ConnectStatus operator+=(const EventNoArgDelegation& fun); ConnectStatus operator+=(const Event1ArgDelegation& fun); ConnectStatus operator+=(const Event2ArgDelegation& fun); ConnectStatus operator+=(const Event3ArgDelegation& fun); ConnectStatus operator+=(const Event4ArgDelegation& fun); void EmitEvent(MObject* sender); void EmitEvent(MObject* sender, AnyType args); void EmitEvent(MObject* sender, AnyType arg1, AnyType arg2); void EmitEvent(MObject* sender, AnyType arg1, AnyType arg2, AnyType arg3); void EmitEvent(MObject* sender, AnyType arg1, AnyType arg2, AnyType arg3, AnyType arg4); private: std::shared_ptr std::shared_ptr std::shared_ptr std::shared_ptr std::shared_ptr std::vector<> std::vector<> std::vector<> std::vector<> std::vector<> }; //==================================================== 如果大家还记得我们以前说的boost的信号槽的话,那么实现也是相当简单,简单到完全没啥可说的: //====================================================#include 'MEventHandle.h' #include #include MEventHandle::MEventHandle() { mNoArgHandle = std::shared_ptr mOneHandle = std::shared_ptr mTwoHandle = std::shared_ptr mThreeHandle = std::shared_ptr mFourHandle = std::shared_ptr } MEventHandle::~MEventHandle() { } ConnectStatus MEventHandle::operator+=(const EventNoArgDelegation& fun){ boost::shared_ptr mNoArgsFuns.push_back(__F); return mNoArgHandle->connect(EventNoArgHandle::slot_type(*__F).track(__F)); } ConnectStatus MEventHandle::operator+=(const Event1ArgDelegation& fun){ boost::shared_ptr mOneArgsFuns.push_back(__F); return mOneHandle->connect(Event1ArgHandle::slot_type(*__F).track(__F)); } ConnectStatus MEventHandle::operator+=(const Event2ArgDelegation& fun){ boost::shared_ptr mTwoArgsFuns.push_back(__F); return mTwoHandle->connect(Event2ArgHandle::slot_type(*__F).track(__F)); } ConnectStatus MEventHandle::operator+=(const Event3ArgDelegation& fun){ boost::shared_ptr mThreeArgsFuns.push_back(__F); return mThreeHandle->connect(Event3ArgHandle::slot_type(*__F).track(__F)); } ConnectStatus MEventHandle::operator+=(const Event4ArgDelegation& fun){ boost::shared_ptr mFourArgsFuns.push_back(__F); return mFourHandle->connect(Event4ArgHandle::slot_type(*__F).track(__F)); } void MEventHandle::EmitEvent(MObject* sender){ std::async(std::launch::async, [=](){(*mNoArgHandle)(sender); }); } void MEventHandle::EmitEvent(MObject* sender, AnyType args){ std::async(std::launch::async, [=](){(*mOneHandle)(sender,args); }); } void MEventHandle::EmitEvent(MObject* sender, AnyType arg1, AnyType arg2){ std::async(std::launch::async, [=](){(*mTwoHandle)(sender, arg1, arg2); }); } void MEventHandle::EmitEvent(MObject* sender, AnyType arg1, AnyType arg2, AnyType arg3){ std::async(std::launch::async, [=](){(*mThreeHandle)(sender, arg1, arg2, arg3); }); } void MEventHandle::EmitEvent(MObject* sender, AnyType arg1, AnyType arg2, AnyType arg3, AnyType arg4){ std::async(std::launch::async, [=](){(*mFourHandle)(sender, arg1, arg2, arg3, arg4); }); } //============================================= operator+= 将信号和槽函数连接在一起,EmitEvent是执行回调函数,从我们的实现中所有的回调函数都是异步操作,也就是立即返回的,这样一来不会因为回调函数过大而导致主程序的卡顿了。 这一讲就到这里吧,因为下面我们就开始讲怎么构建一个窗口出来,这个内容会比较多,所以可能还会被分成几讲来说。 //============================================
联系客服