5.MFC基础(五)视图、运行时类信息、动态创建

一、MFC的视图窗口

 1.相关问题

   视图窗口:提供了一个用于显示数据的窗口,并和用户进行交互操作

 2.相关的类

   CView及其子类 - 父类CWnd,封装了关于视图窗口的操作

 3.视图窗口的使用

  (1)从CView类派生一个自己的视图类(CMyView),并必须重写父类的纯虚函数OnDraw

     当CView类帮我们处理WM_PAINT消息时将调用OnDraw

  (2)在框架窗口的WM_CREATE消息处理中:new一个CMyVIew类对象(pView),并调用Create函数,完成视图窗口的创建

 4.命令消息(WM_COMMAND)处理顺序

   View  -->  Frame  -->  App

   CFrameWnd::OnCmdMsg函数内部代码执行的先后顺序决定的

 5.对象的关系图

   m_pMainWnd = pFrame;

   m_pViewActive = pView;

   theApp

      |------->m_pMainWnd(框架类对象地址pFrame)

                                     |------->m_pViewActive(视图类对象地址pView)

  相关代码:

#include "stdafx.h"


class CMyView :public CView
{
    DECLARE_MESSAGE_MAP()
public:
    virtual void OnDraw(CDC* pDC);
public:
    afx_msg void OnPaint();
    afx_msg void OnNew();
};
BEGIN_MESSAGE_MAP(CMyView, CView)
    ON_COMMAND(ID_NEW, OnNew)
    //ON_WM_PAINT()
END_MESSAGE_MAP()

void CMyView::OnNew()
{
    AfxMessageBox(L"视图类处理了新建被点击");
}
void CMyView::OnPaint()
{
    PAINTSTRUCT ps = { 0 };
    HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
    ::TextOut(hdc, 200, 200, L"CMyView::OnPaint", 16);
    ::EndPaint(this->m_hWnd, &ps);
}

void CMyView::OnDraw(CDC* pDC)
{
    pDC->TextOutW(100, 100, "CMyView::OnDraw");
}

class CMyFrameWnd :public CFrameWnd
{
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnPaint();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
    ON_WM_CREATE()
    ON_WM_PAINT()
END_MESSAGE_MAP()

int CMyFrameWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    CMyView *pView = new CMyView;
    this->m_pViewActive = pView;
    pView->Create(NULL, L"", WS_VISIBLE|WS_CHILD|WS_BORDER, CRect(0, 0, 100, 100), 
        this, AFX_IDW_PANE_FIRST);
    return CFrameWnd::OnCreate(lpCreateStruct);
}

void CMyFrameWnd::OnPaint()
{
    PAINTSTRUCT ps = { 0 };
    HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
    ::TextOut(hdc, 100, 100, L"我是框架窗口客户区", 9);
    ::EndPaint(this->m_hWnd, &ps);
}

class CMyWinApp :public CWinApp
{
public:
    virtual BOOL InitInstance();
};

CMyWinApp theApp;

BOOL CMyWinApp::InitInstance()
{
    CMyFrameWnd *pFrame = new CMyFrameWnd;
    m_pMainWnd = pFrame;
    pFrame->Create(NULL, L"MFC View", WS_OVERLAPPEDWINDOW, 
        CFrameWnd::rectDefault, NULL, MAKEINTRESOURCE(IDR_MENU1));
    pFrame->ShowWindow(SW_SHOW);
    pFrame->UpdateWindow();
    return TRUE;
}
View Code

  运行结果:

  

二、运行时类信息机制(MFC第四大机制)

 1.运行时类信息机制的作用

   在程序执行过程中,可以通过这个机制获知对象相关类的信息(获知一个对象是不是某个类的对象)

 2.运行时类信息机制的使用

  (1)类必须派生自CObject

  (2)类内必须添加声明宏 DECLARE_DYNAMIC

  (3)类外必须添加实现宏 IMPLEMENT_DYNAMIC

     CObject::IsKindOf( ) - 可以判断对象是不是属于某个类

 3.运行时类信息实现

  (1)数据结构

    struct  CRuntimeClass(宏展开静态变量的类型)
    {
      LPCSTR    m_lpszClassName;                       //类名称

      int           m_nObjectSize;                           //类的大小sizeof

      UINT        m_wSchema;                               //类的版本0xFFF

      CObject* (PASCAL* m_pfnCreateObject)( );  //用于动态创建机制,此处没用,为NULL

      CRuntimeClass*  m_pBaseClass;                  //父类静态变量地址(负责连接链表)

      CRuntimeClass*  m_pNextClass;                   //运行时类信息为NULL

    };

  (2)宏展开代码

     见代码

  (3)宏展开各部分的作用

     classCDog - 静态变量,保存了关于类的相关信息(类名、大小、版本...)

     GetRuntimeClass( ) - 虚函数,获取本类静态变量地址(获取链表头结点地址)

  (4)关系图

     GetRuntimeClass( )

                      |->类名/大小/版本

           |->&classCDog

                               |->类名/大小/版本

           |->&classCAnimal

                                         |->类名/大小/版本

                                         |->&classCObject

                                                     |->类名/大小/版本

                                                     |->NULL   

  (5)IsKindOf的实现

     利用类对象(yellowDog)调用宏展开的虚函数GetRumtimeClass获取本类静态变量地址(&classCDog链表头结点)

     利用&classCDog和目标(IsKindOf的参数)进行比对,如果相等,证明yellowDog属于该类;如果不相等,利用&classCDog

     第五个成员获取父类静态变量,和目标进行循环比对,只要又一次比对成功,也能证明yellowDog属于该类

     如果循环结束一次比对都不成功才证明yellowDog不属于这个类

    伪代码: 

    yellowDog.IsKindOf( RUNTIME_CLASS( CObject ) )

    {

      CRuntimeClass*  pClassThis  =  GetRuntimeClass( );  //获得链表头结点地址

      return  pClassThis->IsDerivedFrom( RUNTIME_CLASS( CObject ) )  //函数内部this为链表头结点,参数为链表尾节点

      {

        const CRuntimeClass*  pClassThis  =  this;  //获取链表头结点

        while ( pClassThis  !=  NULL )

        {        

          if  ( pClassThis  ==  RUNTIME_CLASS( CObject ) )
            return  TRUE;

          pClassThis  =  pClassThis->m_pBaseClass;

        }

        return  FALSE;

      }

    }   

  附:RUNTIME_CLASS( theClass )  ==>  &theClass::classtheClass

    括号中指明的类的静态变量地址

  相关代码: 

#include "stdafx.h"

class CAnimal : public CObject
{
    DECLARE_DYNAMIC(CAnimal)

};
IMPLEMENT_DYNAMIC(CAnimal, CObject)

class CDog : public CAnimal
{
public:
    static const CRuntimeClass classCDog;
    virtual CRuntimeClass* GetRuntimeClass() const;
};

AFX_COMDAT const CRuntimeClass CDog::classCDog = {
    "CDog", 
    sizeof(class CDog), 
    0xFFFF, 
    NULL,
    ((CRuntimeClass*)(&CAnimal::classCAnimal)),
    NULL
}; 
CRuntimeClass* CDog::GetRuntimeClass() const
{ 
    return ((CRuntimeClass*)(&CDog::classCDog));
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    CDog yellowDog;
    if (yellowDog.IsKindOf(RUNTIME_CLASS(CObject)))
    {
        printf("yellowDog is CObject\n");
    }
    else
    {
        printf("yellowDog is not CObject\n");
    }
    return 0;
}
View Code

  运行结果:

  

 三、动态创建机制(MFC第五大机制)

  1.动态创建机制的作用

    在不知道类名的情况下,将类的对象创建出来

  2.动态创建机制的使用

   (1)类必须派生自CObject

   (2)类内必须添加声明宏 DECLARE_DYNCREATE

   (3)类外必须添加实现宏 IPLEMENT_DYNCREATE

      CRuntimeClass::CreateObject - 负责动态创建类的对象

  3.动态创建机制的实现

   (1)宏展开代码

      见代码

   (2)宏展开各部分的作用(和运行时类信息机制的区别)

      多了一个静态函数CDog::CreateObject(new了一个CDog类对象)

      静态变量的第四个成员不在为NULL,保存了新增加静态函数的地址(函数名称)

   (3)CRuntimeClass::CreateObject执行过程

      利用CDog类静态变量(&CDog::classCDog)的第四个成员获取新增加静态函数(CDog::CreateObject)

      调用这个静态函数(CDog::CreateObject),在这个静态函数内部new了一个CDog对象,并将对象地址返回

       伪代码:

      CObject *pObj = RUNTIME_CLASS(CDog)->CreateObject( )  //this为&classCDog,链表头结点

      {

        CObject*  pObject  =  ( *m_pfnCreateObject )( )  //CDog::CreateObject,pObject就是CDog

        {

          return  new  CDog;

        }

        return  pObject;  //把CDog返回

      }

  相关代码:

#include "stdafx.h"


class CAnimal :public CObject
{
    DECLARE_DYNCREATE(CAnimal)
};
IMPLEMENT_DYNCREATE(CAnimal, CObject)

class CDog :public CAnimal
{
public: 
    static const CRuntimeClass classCDog; 
    virtual CRuntimeClass* GetRuntimeClass() const; 
    static CObject* PASCAL CreateObject();
};

CObject* PASCAL CDog::CreateObject()
{
    return new CDog;
}

AFX_COMDAT const CRuntimeClass CDog::classCDog = { 
    "CDog",
    sizeof(class CDog),
    0xFFFF,
    CDog::CreateObject,
    ((CRuntimeClass*)(&CAnimal::classCAnimal)),
    NULL
}; 

CRuntimeClass* CDog::GetRuntimeClass() const 
{
    return ((CRuntimeClass*)(&CDog::classCDog));
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    CObject *pObj = RUNTIME_CLASS(CDog)->CreateObject();
    if (pObj->IsKindOf(RUNTIME_CLASS(CDog)))
    {
        printf("pObj is CDog\n");
    }
    else
    {
        printf("pObj is not CDog\n");
    }
    return 0;
}
View Code

  运行结果:

  

  

转载于:https://www.cnblogs.com/csqtech/p/5689175.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值