zoukankan      html  css  js  c++  java
  • MFC DAY03 04 05

    一 MFC的消息映射机制(3)
    1 消息映射机制的使用
    1.1 自己的类必须派生自 CCmdTarget
    1.2 自己的类内 必须添加声明宏 DECLARE_MESSAGE_MAP
    1.3 自己的类外 必须添加实现宏
    BEGIN_MESSAGE_MAP( theClass, baseClass )
    END_MESSAGE_MAP( )
    2 消息映射机制的实现
    2.1 数据结构
    struct AFX_MSGMAP_ENTRY (静态数组的每个元素)
    {
    UINT nMessage; // 消息ID
    UINT nCode; // 通知码
    UINT nID; // 命令ID、控件ID
    UINT nLastID; // 最后一个控件ID
    UINT nSig; // 消息处理函数的类型
    AFX_PMSG pfn; // 消息处理函数的指针(地址)
    };

    struct AFX_MSGMAP (静态变量)
    {
    const AFX_MSGMAP* pBaseMap;
    //保存的是父类的静态变量地址
    const AFX_MSGMAP_ENTRY* lpEntries;
    //本类的静态数组首地址
    };
    2.2 展开后的代码
    见代码
    2.3 宏展开各部分的作用
    _messageEntries[] - 静态数组
    数组中每个元素的类型AFX_MSGMAP_ENTRY
    数组中每个元素保存的是 消息ID 对应的 处理函数
    messageMap - 静态变量
    类型AFX_MSGMAP
    第一个成员保存的是父类的静态变量地址(用于连接链表)
    第二个成员保存的是本类的静态数组首地址。
    GetMessageMap - 虚函数
    返回本类静态变量地址(获取链表头节点)
    2.4 消息的处理过程
    2.4.1 利用本类的对象(pFrame)调用GetMessageMap成员
    虚函数,获取本类静态变量地址(pMessageMap)
    2.4.2 利用pMessageMap的第二个成员获取 相应的静态数组
    首地址,然后匹配数组中的每个元素,一旦找到执行
    2.4.4
    2.4.3 如果找不到,利用pMessageMap的第一个成员,获取
    父类静态变量地址,如果为NULL,结束查找,如果不为
    NULL执行2.4.2
    2.4.4 利用找到的 数组元素的第六个成员,并调用这个成员
    中保存的成员函数指针,完成消息的处理。
    2.4.5 如果遍历整个链表未找到 利用 DefWindowProc处理。
    二 MFC消息的分类
    1 windows的标准(键盘/鼠标/定时器消息等等...)
    ON_WM_XXX
    2 自定义消息
    #define WM_MYMESSAGE WM_USER+n
    ON_MESSAGE
    3 命令消息(WM_COMMAND)
    ON_COMMAND( ID, 处理函数)
    ON_COMMAND_RANGE( 起始ID, 终止ID, 处理函数 )
    4 通知消息
    ON_通知码

    -------------------------------

    一 MFC的菜单
    1 菜单相关
    WIN32 - HMENU(菜单句柄标识菜单)。
    MFC - CMenu类对象表示菜单。
    2 相关类
    CMenu - 封装了对菜单的各种操作,另外还封装了一个成员
    m_hMenu(保存了菜单句柄)。
    3 菜单的使用
    3.1 添加菜单资源
    3.2 设置菜单
    1)在CFrameWnd::Create可以设置菜单
    2)在框架窗口的WM_CREATE消息的处理中
    CMenu menu;
    menu.LoadMenu - 加载菜单资源
    CFrameWnd::SetMenu - 将菜单设置到窗口
    3.3 菜单项的消息处理
    ON_COMMAND( 菜单项ID, 处理函数 )
    3.4 设置菜单项的状态
    ON_WM_INITMENUPOPUP
    ::CheckMenuItem / ::EnableMenuItem
    3.5 菜单项消息的处理顺序(WM_COMMAND)
    Frame->App(CFrameWnd::OnCmdMsg内部执行顺序决定的)
    4 右键菜单
    ON_WM_CONTEXTMENU
    ::TrackPopupMenu
    CMenu::GetSubMenu - 获取某个顶层菜单项的下拉菜单
    二 工具栏
    1 相关类
    CToolBarCtrl - 父类CWnd,封装了工具栏控件的操作。
    CToolBar - 父类为CControlBar,封装了 工具栏 和 框架窗口
    之间的关系,还包括 工具栏的创建
    2 工具栏的使用
    2.1 添加工具栏资源
    2.2 创建工具栏 CToolBar::Create/CToolBar::CreateEx
    2.3 加载工具栏资源 CToolBar::LoadToolBar
    2.4 工具栏准备停靠的位置
    CToolBar::EnableDocking
    2.5 框架窗口允许停靠的位置
    CFrameWnd::EnableDocking
    2.6 设置 工具栏 可以停靠的位置
    CFrameWnd::DockControlBar
    2.7 工具栏的风格
    CBRS_GRIPPER - 把手,夹子风格
    CBRS_SIZE_DYNAMIC - 工具栏可以改变形状
    CBRS_TOOLTIPS - 工具栏按钮,有标签提示

    TBSTYLE_TRANSPARENT - 工具栏按钮突起
    2.8 设置工具栏的显示和隐藏
    CFrameWnd::ShowControlBar - 设置工具栏显示/隐藏
    CWnd::IsWindowVisible - 判断窗口是否处于显示状态 。

    练习:(不要出现标志量)
    工具栏 处于显示状态 菜单项 勾选
    工具栏 处于隐藏状态 菜单项 非勾选

    菜单项每点击一次 工具栏的 显示/隐藏 状态切换一次
    三 状态栏
    1 状态栏的相关类
    CStatusBarCtrl - 父类CWnd,封装了状态栏控件的操作。
    CStatusBar - 父类CControlBar,封装了 状态栏和框架窗口
    之间关系,还包括 状态栏的创建。
    2 状态栏的使用
    2.1 创建状态栏
    CStatusBar::CreateEx/Create
    2.2 设置状态栏指示器
    CStatusBar::SetIndicators
    BOOL SetIndicators(
    const UINT* lpIDArray,//指示器ID数组首地址
    int nIDCount //指示器的个数
    );
    2.3 设置状态栏指示器的 宽度 和 风格
    CStatusBar::SetPaneInfo
    2.4 设置指示器的文本内容
    CStatusBar::SetPaneText

    -----------------------------------------

    什么是MFC?
    编程框架,庞大的类库。基于框架,使用各种类(包括系统的和
    自定义的),添加各种消息,完成各种功能。
    生成基本的窗口,基于窗口添加菜单、工具栏、状态栏。
    菜单-通常创建窗口时,传入菜单资源ID添加菜单
    工具栏/状态栏-添加窗口的成员变量,在OnCreate函数中,
    创建、加载、设置停靠和停靠。
    一 MFC视图
    1 相关类
    CView类-专门用于显示数据的窗口,所有视图类的父类,继承自
    CWnd,本质上是一个窗口。
    CCtrlView类-继承自CView,在CView中内嵌了一个控件。根据
    嵌入的控件不同,派生了CEditView、CListView、
    CRichEditView、CTreeView等。
    CFormView类-拥有对话框资源窗口,可以方便的拖放控件。
    CHtmlView类-专门用来显示网页的视图窗口。我们可以使用这
    个类做简单的网页浏览器。
    CRecordView类-专门用于显示数据库中记录的视图。
    二 CView类的使用
    1 派生自CView类的子类重新OnDraw()这个虚函数,才能使用子类
    创建对象。
    2 由于在CView::PostNcDestroy()函数中,调用了delete this;
    所以,视图对象的创建放到堆中,即new 对象。
    3 创建时,视图铺满框架窗口的客户区,视图的ID使用MFC给定的
    AFX_IDW_PANE_FIRST
    4 视图类可以处理菜单等命令消息的前提是必须是框架窗口的活
    动视图,设置的方式有两种:
    4.1 调用函数:SetActiveView(m_pWndView);
    4.2 指针赋值:m_pViewActive=m_pWndView;
    5 处理菜单等命令消息的先后顺序(CFrameWnd::OnCmdMsg()):
    活动视图->框架窗口->应用程序
    6 OnPaint与OnDraw之间的关系?
    在CMyView不处理WM_PAINT消息时,当有消息产生时,系统的
    CView类处理了WM_PAINT消息,在CView::OnPaint中,调用了
    OnDraw函数,由于虚函数的机制,调用CMyView::OnDraw 。
    如果在CMyView中处理了WM_PAINT消息,父类的CView的OnPaint
    函数不会被调用,OnDraw也不会被调用。
    OnDraw函数的输出比OnPaint更简单,所以视图的信息显示,
    直接在OnDraw函数中。
    二 运行时类信息(4)
    1 概念
    程序在运行时,得到对象的类的信息以及所属类的继承层次关系。
    class CAnimal:public CObject{}
    class CDog:public CAnimal{}

    CDog dog;
    dog is a CDog? TRUE,还能得到类的大小,版本等信息
    dog is a CAnimal?TRUE,还能得到CAnimal类的信息
    dog is a CObject? TRUE, ...
    2 使用
    2.1 定义支持运行时类信息的类
    2.1.1 派生自CObject类
    2.1.2 添加运行时类信息的宏(包括声明宏和实现宏)
    DECLARE_DYNAMIC(CDog)
    IMPLEMENT_DYNAMIC(CDog,CAnimal)
    2.2 调用IsKindOf()函数判断对象是否属于某个类
    3 实现原理
    3.0 结构
    struct CRuntimeClass
    {
    LPCSTR m_lpszClassName;//类的名称
    int m_nObjectSize;//类的大小
    UINT m_wSchema; //类的版本
    CObject* (PASCAL* m_pfnCreateObject)(); //NULL
    CRuntimeClass* m_pBaseClass;//父类的运行时
    类信息变量的地址

    ...
    }

    3.1 成员以及其作用
    3.1.1 classCDog-类型是CRuntimeClass的变量,静态的成员。
    3.1.2 GetRuntimeClass-虚函数,作用是返回classCDog的地址

    3.2 关系,(类的信息链表)
    CDog::GetRuntimeClass()
    |->&classCDog
    |->类的名称,大小,版本等信息
    |->&classCAnimal
    |->CAnimal类的名称、大小、版本等信息
    |->&classCObject
    |->CObject类的名称、大小版本等
    |->NULL
    dog.IsKindOf(RUNTIME_CLASS(CObject)) TRUE
    &classCDog &classCObject
    &classCAnimal
    &classCObject
    3.3 IsKindOf函数的执行过程
    BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
    {
    //classCDog的地址
    CRuntimeClass* pClassThis = GetRuntimeClass();
    return pClassThis->IsDerivedFrom(pClass);
    pClassThis->IsDerivedFrom(pClass)
    {
    //classCDog的地址
    const CRuntimeClass* pClassThis = this;
    while (pClassThis != NULL)
    {
    //比较
    if (pClassThis == pBaseClass)
    return TRUE;
    //获取父类的变量的地址
    pClassThis = pClassThis->m_pBaseClass;
    }
    return FALSE;
    }

    }
    3.3.1 调用GetRuntimeClass获取&classCDog
    3.3.2 调用IsDerivedFrom()函数,在函数中,把&classCDog
    与参数的&classCWnd比较,如果相等,返回TRUE,表示
    对象属于该类,如果不相等,获取&classCAnimal,继续
    循环比较,直到&classCObject的父类的变量地址为空,
    最后,返回FALSE,表示对象不属于该类。

    三 动态创建(5)
    1 概念
    创建未知类型的对象。指的是,可以先写一个创建对象的函数,
    任何类的对象都可以使用该函数创建,包括后来定义的类。
    2 使用
    2.1 定义支持动态创建的类
    2.1.1 派生自CObject
    2.1.2 添加动态创建的声明宏和实现宏
    DECLARE_DYNCREATE(theClass)
    IMPLEMENT_DYNCREATE(theClass,baseClass)
    3 实现原理
    3.1 展开宏的代码
    3.1.1 CreateObject()-静态函数,创建该类的对象。
    3.1.2 classCDog-静态变量,在运行时类信息时,pfnNew为NULL;
    在动态创建时,它是CreateObject函数的地址。
    4 实现步骤
    4.1 调用CRuntimeClass::CreateObject()函数
    4.2 在函数中,首先判断,m_pfnCreateObject是否为空,
    如果不为空,通过它调用CDog::CreateObject函数,
    在函数中,return new CDog;
    四 动态创建的例子(动态切分窗口)
    OnCreateClient-创建窗口的客户区对象

  • 相关阅读:
    Hadoop 2.7 伪分布式环境搭建
    Linux 安装配置 Tomcat
    Hadoop hdfs完全分布式搭建教程
    Hadoop中ssh+IP、ssh+别名免秘钥登录配置
    VMware 克隆多台Linux机器并配置IP
    Linux 安装JDK
    连表更新数据
    设置让php能够以root权限来执行exec() 或者 shell_exec()
    Jsonp 关键字详解及json和jsonp的区别,ajax和jsonp的区别
    php7安装mongoDB扩展
  • 原文地址:https://www.cnblogs.com/Renekton/p/3864143.html
Copyright © 2011-2022 走看看