mfc第五天

来源:互联网 发布:淘宝店铺装修自学 编辑:程序博客网 时间:2024/05/25 12:20
一MFC视图
    1,相关问题
    视图窗口    --一个数据的窗口,可以喝用户进行交互操作
    MFC视图类CView及其子类
    2.视图窗口的使用            框架窗口带标题栏,是父窗口,而视图窗口不带标题栏,是子窗口
    2.1将CView类派生自己的视图类(CMyView),并需要重写一个虚函数OnDraw
    在框架窗口的WM_CREATE消息中创建视图窗口

    处理WM_PAINT消息,则OnDraw()不执行
    一个框架窗口,可以包含多个视图窗口,但只有一个是活动窗口,具有焦点。鼠标点击可以获取焦点。

    
      theApp
    |->m_hMainWnd(保存框架类对象地址)
        |->m_pViewActive(保存视图类对象地址)
    
    3.命令消息处理。(WM_COMMAND)
    CFrameWnd::OnCmdMsg内部代码执行顺序
      1利用GetActiveView获取视图类对象地址,遍历视图类这个支脉链表查找消息的处理pView->OnCmdMsg
      2.利用隐含的this指针(pFrame)调用OnCmdMsg,遍历框架类这个支脉链表查找消息处理
      3.利用theApp对象四肢调用OnCmdMsg,遍历应用程序类这个支脉链表查找消息处理。
    View--->Frame--->App

二.运行时类信息机制
    1.运行时类信息机制的作用
        在程序运行过程中,可以判断类对象的相关类的信息以及继承派生关系
    2.使用
      2.1 类必须派生自CObject
      2.2 类内部必须添加声明宏 DECLARE_DYNAMIC(theClass)
      2.3 类外添加实现宏
        IMPLEMENT_DYNAMIC(theClass,baseClass)
        
    CObject::IsKindOf




struct CRuntimeClass
{
// Attributes
    LPCSTR m_lpszClassName;//类名称
    int m_nObjectSize;    //类的大小sizeof
    UINT m_wSchema; // schema number of the loaded class    //类的版本
    CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
    //动态创建机制使用(运行时类信息为NULL)
#ifdef _AFXDLL
    CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#else
    CRuntimeClass* m_pBaseClass;        //xxxxx
#endif

// Operations
    CObject* CreateObject();
    BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;

// Implementation
    void Store(CArchive& ar) const;
    static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);

    // CRuntimeClass objects linked together in simple list
    CRuntimeClass* m_pNextClass;       // linked list of registered classes  //NULL
};




4展开的各部分
    classCDog  --静态变量  保存了类的相关信息  类名/大小/版本....
    GeyRuntimeClass  虚函数
        获取CDog类的静态变量地址(&classCDog),(获取链表头结点)

    RUNTIME_CLASS(类名) -获取括号中指明的类的静态变量的地址



5 IsKindOf函数执行过程
    5.1获取对象所属类的静态变量地址(&classCDog)
    5.2拿着这个静态变量&classCDog和被判断类型&classCObject进行比较  如果相等证明对象属于该类
    5.3如果不相等 获取父类的静态变量地址与被判断类&classCObject循环进行比较,只要有相等情况证
    明对象属于该类
    5.4无相等情况证明对象不属于该类。

三动态创建机制
    1.动态创建机制的作用
        在不知道类名的情况下,将类的对象创建出来。
    2.动态创建的使用
      1.类必须派生自CObject
      2.类内部添加声明宏  DECLARE_DYNCREATE(theClass)
      3.类外添加实现宏    IMPLEMENT_DYNCREATE(theClass,baseClass)

    利用CRuntimeClass::CreateObject动态创建对象
    3.宏展开各部分作用
    3.1静态变量有变化
        AFX_COMDAT const AFX_DATADEF CRuntimeClass CDog::classCDog = {
        "CDog",            //
        sizeof(class CDog),
        0xFFFF,CDog::CreateObject, //
        RUNTIME_CLASS(CAnimal),    //
        NULL
    };
    3.2多了一个静态函数CreateObject
        new 一个对象,病将对象地址返回。
    4.执行过程
        4.1首先获取CDog类的静态变量地址(&CDog::classCDog)
        4.2利用这个函数地址调用CRuntimeClass::CreateObject函数
        4.3在这个函数内部调用CDog::classCDog静态变量的第四个成员(CDog::CreateObject)
        4.4在这个函数new了一个CDog类的对象,并返回对象地址。
四。窗口的切分
    窗口切分相关问题
    1.静态切分  窗口在创建时就完成切分,可以切分多个视图窗口 最多16*16
    2.动态切分  程序在运行过程中,根据用户需要实时切分  最多2*2 多个窗口,但是是统一类型的

    CSpiltterWnd  -父类为CWnd,一种框架类           CFrameWnd 口字型

    静态切分
        重写虚函数CFrameWnd::OnCreateClient
        在函数内部定义CSplitterWnd类对象
        利用对象调用CSplitterWnd::CreateStatic创建框架窗口
        调用CSplitterWnd::CreateView给各个部分添加视图窗口


*****************************************************************
运行时类信息伪代码
yellowDog.IsKindOf(RUNTIME_CLASS(CDog){//函数内部this指针为&yellowDog,参数&CObject::classCObject
    CRuntimeClass* pClassThis = GetRuntimeClass();//获取链表头结点
    return pClassThis->IsDerivedFrom(pClass);{   //pClass  尾节点
        //函数内部this指针为pClassThis链表头结点  ==&CDog::classCDog
        const CRuntimeClass* pClassThis = this;  //this==&CDog::classCDog
        while(pClassThis!-NULL){
            if(pClass==&CObject::classCDog){
                return TRUE;
            }
            pClassThis=pClassThis->m_pBaseClass;
        }
        return FALSE;
    }
}



***************************************************************
动态创建机制
    RUNTIME_CLASS(CDog)->CreateObject(){//this==&CDog::classCDog
        pObject=(*pfnCreateObject)();{
            return new CDog;//new 一个对象,并将地址返回.
        }
    }








*************************************************
BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const
{
    ASSERT(this != NULL);
    ASSERT(AfxIsValidAddress(this, sizeof(CRuntimeClass), FALSE));
    ASSERT(pBaseClass != NULL);
    ASSERT(AfxIsValidAddress(pBaseClass, sizeof(CRuntimeClass), FALSE));

    // simple SI case
    const CRuntimeClass* pClassThis = this;
    while (pClassThis != NULL)
    {
        if (pClassThis == pBaseClass)
            return TRUE;
#ifdef _AFXDLL
        pClassThis = (*pClassThis->m_pfnGetBaseClass)();
#else
        pClassThis = pClassThis->m_pBaseClass;
#endif
    }
    return FALSE;       // walked to the top, no match
}



BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
    ASSERT(this != NULL);
    // it better be in valid memory, at least for CObject size
    ASSERT(AfxIsValidAddress(this, sizeof(CObject)));

    // simple SI case
    CRuntimeClass* pClassThis = GetRuntimeClass();  yellowDog->GetRuntimeClass(); 返回头结点
    return pClassThis->IsDerivedFrom(pClass);
}



之前该过程与WM_CREATE一致
OnWndMsg(){
    OnCommand(){
        UINT nID = LOWORD(wParam);    //获取被点击菜单项的ID
        ...
        OnCmdMsg(nID...){
            CView* pView = GetActiveView(){;//this==pFrame 获取具有焦点的视图
                return m_pViewActive;
            }
            pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo){;//函数内部指针为pView
                
            }
        }
    }
}


BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    LRESULT lResult = 0;

    // special case for commands
    if (message == WM_COMMAND)    
    {                    //菜单挂在框架窗口上
        if (OnCommand(wParam, lParam))    //this==pFrame
        {
            lResult = 1;
            goto LReturnTrue;
        }
        return FALSE;
    }
    .....
}


void CView::OnPaint()
{
    // standard paint routine
    CPaintDC dc(this);
    OnPrepareDC(&dc);
    OnDraw(&dc);        //父类调用
}


CView* CFrameWnd::GetActiveView() const
{
    ASSERT(m_pViewActive == NULL ||
        m_pViewActive->IsKindOf(RUNTIME_CLASS(CView)));
    return m_pViewActive;
}

CMyView::OnDraw(CDC * 0x0018fa98 {CPaintDC hWnd=0x00060190}) line 16
CView::OnPaint() line 185
CWnd::OnWndMsg(unsigned int 15, unsigned int 0, long 0, long * 0x0018fc08) line 1836
CWnd::WindowProc(unsigned int 15, unsigned int 0, long 0) line 1596 + 30 bytes
AfxCallWndProc(CWnd * 0x028d1680 {CMyView hWnd=0x00060190}, HWND__ * 0x00060190, unsigned int 15, unsigned int 0, long 0) line 215 + 26 bytes
AfxWndProc(HWND__ * 0x00060190, unsigned int 15, unsigned int 0, long 0) line 379
USER32! 760162fa()
USER32! 76017316()
USER32! 76016de8()
USER32! 76016e44()
NTDLL! 776f011a()
CWnd::UpdateWindow() line 118 + 63 bytes
CMyWinApp::InitInstance() line 62
AfxWinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x006f588e, int 1) line 39 + 11 bytes
WinMain(HINSTANCE__ * 0x00400000, HINSTANCE__ * 0x00000000, char * 0x006f588e, int 1) line 30
WinMainCRTStartup() line 198 + 54 bytes
KERNEL32! 767b33ca()
NTDLL! 77719ed2()
NTDLL! 77719ea



CObject* CRuntimeClass::CreateObject()
{
    if (m_pfnCreateObject == NULL)   //this->
    {
        TRACE(_T("Error: Trying to create object which is not ")
              _T("DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n"),
            m_lpszClassName);
        return NULL;
    }

    CObject* pObject = NULL;
    TRY
    {
        pObject = (*m_pfnCreateObject)();
    }
    END_TRY

    return pObject;

}


宏展开

#ifdef _AFXDLL#define DECLARE_DYNAMIC(class_name) \protected: \static CRuntimeClass* PASCAL _GetBaseClass(); \public: \static const AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#define _DECLARE_DYNAMIC(class_name) \protected: \static CRuntimeClass* PASCAL _GetBaseClass(); \public: \static AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#else#define DECLARE_DYNAMIC(class_name) \public: \static const AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#define _DECLARE_DYNAMIC(class_name) \public: \static AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#endifstruct CRuntimeClass{// AttributesLPCSTR m_lpszClassName;int m_nObjectSize;UINT m_wSchema; // schema number of the loaded classCObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class#ifdef _AFXDLLCRuntimeClass* (PASCAL* m_pfnGetBaseClass)();#elseCRuntimeClass* m_pBaseClass;#endif// OperationsCObject* CreateObject();BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;// Implementationvoid Store(CArchive& ar) const;static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);// CRuntimeClass objects linked together in simple listCRuntimeClass* m_pNextClass;       // linked list of registered classes};#ifdef _AFXDLL#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \CRuntimeClass* PASCAL class_name::_GetBaseClass() \{ return RUNTIME_CLASS(base_class_name); } \AFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \&class_name::_GetBaseClass, NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \CRuntimeClass* PASCAL class_name::_GetBaseClass() \{ return RUNTIME_CLASS(base_class_name); } \AFX_COMDAT AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \&class_name::_GetBaseClass, NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \#elseAFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \RUNTIME_CLASS(base_class_name), NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \RUNTIME_CLASS(base_class_name), NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \

#define DECLARE_DYNCREATE(class_name) \DECLARE_DYNAMIC(class_name) \static CObject* PASCAL CreateObject();protected: \static CRuntimeClass* PASCAL _GetBaseClass(); \public: \static AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#ifdef _AFXDLL#define DECLARE_DYNAMIC(class_name) \protected: \static CRuntimeClass* PASCAL _GetBaseClass(); \public: \static const AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#define _DECLARE_DYNAMIC(class_name) \protected: \static CRuntimeClass* PASCAL _GetBaseClass(); \public: \static AFX_DATA CRuntimeClass class##class_name; \virtual CRuntimeClass* GetRuntimeClass() const; \#else#define IMPLEMENT_DYNCREATE(class_name, base_class_name) \CObject* PASCAL class_name::CreateObject() \{ return new class_name; } \IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, \class_name::CreateObject)#ifdef _AFXDLL#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \CRuntimeClass* PASCAL class_name::_GetBaseClass() \{ return RUNTIME_CLASS(base_class_name); } \AFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \&class_name::_GetBaseClass, NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \CRuntimeClass* PASCAL class_name::_GetBaseClass() \{ return RUNTIME_CLASS(base_class_name); } \AFX_COMDAT AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \&class_name::_GetBaseClass, NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \#else#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \AFX_COMDAT const AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \RUNTIME_CLASS(base_class_name), NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) \AFX_DATADEF CRuntimeClass class_name::class##class_name = { \#class_name, sizeof(class class_name), wSchema, pfnNew, \RUNTIME_CLASS(base_class_name), NULL }; \CRuntimeClass* class_name::GetRuntimeClass() const \{ return RUNTIME_CLASS(class_name); } \#endif****************************CObject* CRuntimeClass::CreateObject(){if (m_pfnCreateObject == NULL){TRACE(_T("Error: Trying to create object which is not ")  _T("DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n"),m_lpszClassName);return NULL;}CObject* pObject = NULL;TRY{pObject = (*m_pfnCreateObject)();}END_TRYreturn pObject;}


0 0