zoukankan      html  css  js  c++  java
  • MFC使用简单总结(便于以后查阅)

    一、资源

    共有三个和资源有关的文件:资源头文件resource.h、资源描述文件resource.rc和存放在res文件夹下的具体的资源如图片等。

    资源头文件中全部是宏定义,应用程序需要为每个资源都定义一个标识符用整数来表示的编号,这些编号就叫做资源标识符(提高了程序的可读性)。

    资源描述文件中,是为了描述资源的外观进行定义的一些语句,如菜单资源。

    res文件夹下是图片等外部资源。

    总之,简单的资源如控件,这类资源的外观和功能只取决于c++代码,所以不需要资源描述文件,更不需要res文件夹,只需要在资源头文件中定义标识符即可。

    对于复杂的资源如菜单资源,则需要在资源描述文件中定义好外观,在资源头文件中定义好标识符,但并不需要在res文件夹中有对于的图片等外部文件。

    对于位图、图标和鼠标光标等图形或其他的视频数据,需要外部单独文件的,则需要在资源头文件中定义标识符,需要在资源描述文件中说明资源的名称和外部文件的存储位置,需要在res文件夹中存放外部文件。

    最终这些定义的资源,包括res文件夹下存放的外部文件会被链接器连同obj文件链接成一个整体exe文件。

    二、运行时动态创建对象---利用类信息表CRuntimeClass结构体创建对象

    看到标题,大部分会说“运行时创建对象”那不是小儿科,就这样(vb.net语言描述):

    Dim newButton As Button = New Button()

    newButton.Name = "Button1"

    这的确是在运行时创建了一个按钮。不过若需按照用户要求创建按钮、复选框或者单选框怎么办,好像也好办:

    Dim newControl As Control

    Select Case userSelection     //userSelection 是个字符串

    Case "按钮"   newControl = New Button()

    Case "复选框"  newControl = New CheckBox()

    ....

    End Select

    如果用户需要的是Windows.Forms里面的数十种控件,那么你的Select语句也要写数十行吗?我当然不是想要做这种刁难的用户,但是需求总是多种多样的,若有一种方法能够在运行时任意指定对象的创建类型,甚至是用表示类型的名字的字符串创建所需的对象,该有多么方便。.net Framwork的反射机制给我们带来了解决问题的方法。MFC其实是更早的原型(虽然有缺陷),就是类信息表。

    二、动态创建对象:类信息表(或称类信息结构体)

    (1)MFC中CRuntimeClass结构体的定义大致如下:

    struct CRuntimeClass

    {

      LPCSTR m_LpszClassName;  //类名字

      CObject*(PASCAL *m_pfnCreateObject)();  //建立类的工厂函数的指针

      CObject* CreateObject();  //工厂函数原型的声明,这个无意义,暂时不要管他,因为工厂函数定义都是在这个结构体的外部,是全局的或其他类中的函数

      CRuntimeClass* m_pBaseClass;  //基类信息表(一个节点)指针

      CRuntimeClass* m_pNextClass;  //下一个类信息表(一个节点)指针

      ............  //其他的诸如,所描述的对象所占内存大小,版本号等信息

    实际上一个MFC应用程序有一个全局的总表,便于管理,结构图如下:

    这样,根据类名来创建一个对象时,就只需要遍历这个总表找到对应的创建对象的工厂函数即可。

    (2)使用时,实际上只需要用到三个宏即可(CRuntimeClass(一个参数),IMPLEMENT_DYNCREATE(两个参数)),RUNTIME_CLASS(一个参数)):

    其中,前两个宏需要我们在对于的头文件和cpp文件中添加,而最后一个宏不用管他,我们直接使用就行了。

    首先是类信息表(我叫类信息结构)的创建宏(用到两个宏),这个宏完成了类信息结构体的声明和相关成员数据的填充工作(说白了,这个宏给一个类加入了一个含有数据的类信息结构体的实例,并且这个实例是属于这个类的静态成员变量)。

    举例如下:

    //CMainFrame类的声明

    class CMainFrame:public CFrameWnd

    {

    protected:

      CMainFrame();

      DECLARE_DYNCREATE(CMainFrame)  //完成类信息结构体的声明

      ........................

    }

    //CMainFrame类的实现

    CMainFrame::CMainFrame(){.........}

    IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)  //完成类信息结构体数据成员的填充,需要本类和基类名称。 比如这个宏中会出现:return new CMainFrame;字样,所以创建了对象。

    在main函数中使用时,直接用获取“一个类信息结构体对象”的指针的全局宏RUNTIME_CLASS(一个参数)即可,实际上RUNTIME_CLASS内容就是获取类的静态成员变量“类信息结构”。形如下面:

    CRuntimeClass*(&CMainFrame::类信息结构成员)。只需要记住这个宏返回一个类信息表的指针(或者说一个元数据的指针)即可。

    举例如下:

    void main()

    {

      //动态创建对象,通过类型信息表的成员“建立类的工厂函数的指针”来调用工厂函数以便动态创建对象。

      CObject* m=RUNTIME_CLASS(CMainFrame)->m_pfnCreateObject();  //本质上是创建了一个CMainFrame对象

       CMainFrame objFrm=(CMainFrame*)m;

      //下面就可以调用objFrm对象的成员函数了。

    }

  • 相关阅读:
    Docker常用命令总结(不断更新)
    Docker容器简介-与虚拟机的区别及安装步骤
    ELK搭建—安装使用Kibana可视化
    使用CURL与ElasticSearch服务进行通信
    安装部署ElasticSearch单节点在Linux服务器上
    ElasticStack分布式引擎技术栈(ELK)介绍
    为Nginx服务器配置黑(白)名单的防火墙
    php大力力 [026节] php开发状态要随时做好整理工作
    php大力力 [025节] 来不及学习和分类的,大力力认为有价值的一些技术文章合集(大力力二叔公)(2015-08-27)
    php大力力 [024节]PHP中的字符串连接操作(2015-08-27)
  • 原文地址:https://www.cnblogs.com/hnfxs/p/3163501.html
Copyright © 2011-2022 走看看