打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
第122讲 DirectX11Frame(2)

好吧,扯了这些大家也算是对为什么我们要在这里写一个基类有所理解了,如我们一开始所说,这个基类几乎不干什么有用的事,他只是提供了一个方便性而已,让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 GetObjFactory() const;

    std::shared_ptr GetObjFactory();

    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 mClassFactory;


    //===============================================

    // 友员函数,对流输出的支持

    //===============================================

    friend std::ostream& operator<(std::ostream& os,const="" mobject&="">

        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 MObject::GetObjFactory() const

{

    return mClassFactory;

}


std::shared_ptr MObject::GetObjFactory(){

    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 AnyTypeCast(AnyType any){

try{

return boost::optional(boost::any_cast(any));

}

catch (boost::bad_any_cast e){

return boost::optional();

}

}


//---------------------------------------------------------------

// 定义几种事件驱动类型

//---------------------------------------------------------------

typedef boost::signals2::signal EventNoArgHandle;

typedef boost::signals2::signal Event1ArgHandle;

typedef boost::signals2::signal Event2ArgHandle;

typedef boost::signals2::signal Event3ArgHandle;

typedef boost::signals2::signal Event4ArgHandle;



//-----------------------------------------------------------------

// 能够被执行回调操作的函数类型

//-----------------------------------------------------------------

typedef boost::function EventNoArgDelegation;

typedef boost::function Event1ArgDelegation;

typedef boost::function Event2ArgDelegation;

typedef boost::function Event3ArgDelegation;

typedef boost::function Event4ArgDelegation;


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  mNoArgHandle;

std::shared_ptr   mOneHandle;

std::shared_ptr   mTwoHandle;

std::shared_ptr   mThreeHandle;

std::shared_ptr   mFourHandle;


std::vector<>> mNoArgsFuns;

std::vector<>> mOneArgsFuns;

std::vector<>> mTwoArgsFuns;

std::vector<>> mThreeArgsFuns;

std::vector<>> mFourArgsFuns;

};



//====================================================


如果大家还记得我们以前说的boost的信号槽的话,那么实现也是相当简单,简单到完全没啥可说的:


//====================================================#include 'MEventHandle.h'

#include

#include

MEventHandle::MEventHandle()

{

mNoArgHandle = std::shared_ptr(new EventNoArgHandle);

mOneHandle = std::shared_ptr(new Event1ArgHandle);

mTwoHandle = std::shared_ptr(new Event2ArgHandle);

mThreeHandle = std::shared_ptr(new Event3ArgHandle);

mFourHandle = std::shared_ptr(new Event4ArgHandle);

}



MEventHandle::~MEventHandle()

{

}


ConnectStatus MEventHandle::operator+=(const EventNoArgDelegation& fun){

boost::shared_ptr __F(new EventNoArgDelegation(fun));

mNoArgsFuns.push_back(__F);

return mNoArgHandle->connect(EventNoArgHandle::slot_type(*__F).track(__F));

}


ConnectStatus MEventHandle::operator+=(const Event1ArgDelegation& fun){

boost::shared_ptr __F(new Event1ArgDelegation(fun));

mOneArgsFuns.push_back(__F);

return mOneHandle->connect(Event1ArgHandle::slot_type(*__F).track(__F));

}


ConnectStatus MEventHandle::operator+=(const Event2ArgDelegation& fun){

boost::shared_ptr __F(new Event2ArgDelegation(fun));

mTwoArgsFuns.push_back(__F);

return mTwoHandle->connect(Event2ArgHandle::slot_type(*__F).track(__F));

}


ConnectStatus MEventHandle::operator+=(const Event3ArgDelegation& fun){

boost::shared_ptr __F(new Event3ArgDelegation(fun));

mThreeArgsFuns.push_back(__F);

return mThreeHandle->connect(Event3ArgHandle::slot_type(*__F).track(__F));

}


ConnectStatus MEventHandle::operator+=(const Event4ArgDelegation& fun){

boost::shared_ptr __F(new Event4ArgDelegation(fun));

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是执行回调函数,从我们的实现中所有的回调函数都是异步操作,也就是立即返回的,这样一来不会因为回调函数过大而导致主程序的卡顿了。


这一讲就到这里吧,因为下面我们就开始讲怎么构建一个窗口出来,这个内容会比较多,所以可能还会被分成几讲来说。


//============================================

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
详解C++右值引用
enable_shared_from_this 实现
在Delphi中编写参数个数可变的函数
世界上最经典的程序Hello World
实现自己的printf函数
c++ vector删除元素
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服