MFC 学习笔记

乎语百科 241 0

MFC 学习笔记

一.MFC编程基础:

概述:

MFC 学习笔记

常用头文件:

MFC 学习笔记

MFC控制台程序:

MFC 学习笔记

MFC库程序:

MFC 学习笔记

规则库可以被各种程序所调用,扩展库只能被MFC程序调用。

MFC窗口程序:

MFC 学习笔记

示例:

MFC 学习笔记

MFC库中类的简介:

MFC 学习笔记

MFC 学习笔记

具体详细细节可以参考离线文档

第一个MFC程序:

1.创建一个win32程序

2.设置使用MFC

3.添加类

#include <afxwin.h>
class CMyFrameWnd : public CFrameWnd{
};
class CMyWinApp : public CWinApp{
public:
	CMyWinApp()
	{
	}
	virtual BOOL InitInstance(){//此函数内部的this为&theApp
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, "MFCBase");
		this->m_pMainWnd = pFrame;
		pFrame->ShowWindow(SW_SHOW);
		pFrame->UpdateWindow();
		return TRUE;
	}
};
CMyWinApp theApp;//爆破点

4.效果:

MFC 学习笔记

MFC程序启动:

MFC 学习笔记

MFC 学习笔记

AFX_MODULE_STATE aaa;//当前程序模块状态信息
AFX_MODULE_THREAD_STATE bbb; //当前程序线程状态信息

CWinApp::CWinApp()//构造全局对象CMyWinApp theApp
{
  AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
               //获取全局变量&aaa
  AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
               //获取全局变量&bbb
  pThreadState->m_pCurrentWinThread = this;//将&theApp保存到bbb的一个成员中

  AfxGetThread()
  {
     AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb
     CWinThread* pThread = pState->m_pCurrentWinThread;
     return pThread;//返回的为&theApp
  }
  pModuleState->m_pCurrentWinApp = this;//将&theApp保存到aaa的一个成员中
  AfxGetApp()
  {
    return AfxGetModuleState()->m_pCurrentWinApp;//返回&theApp
  }
}

通过将断点打在InitInstance()这个方法,在调用堆栈里可以看到MFC里封装的WinMain方法。

MFC 学习笔记

WinMain(...)//程序流程是不是theApp对象指导向哪走
{
  AfxWinMain(...)
  {
    CWinThread* pThread = AfxGetThread();
    CWinApp* pApp = AfxGetApp();//这两代码都是获取&theApp

    pApp->InitApplication();//利用theApp对象调用应用程序类成员虚函数 初始化
    pThread->InitInstance();//利用theApp对象调用应用程序类成员虚函数 创建并显示窗口
    pThread->Run()//利用theApp对象调用应用程序类成员虚函数 消息循环
    {
      	for (;;)
	{
          while(没有消息时)
              OnIdle(..);//利用theApp对象调用应用程序类成员虚函数 空闲处理
          do{
              if(GetMessage抓到WM_QUIT)
                return ExitInstance();
                 //程序结束前,利用theApp对象调用应用程序类成员虚函数 善后处理。

          }while(...)
        }
    }
  }
}

二.MFC窗口和消息:

钩子简介:

MFC 学习笔记

MFC 学习笔记

#include <afxwin.h>
class CMyFrameWnd : public CFrameWnd{
public:
	virtual LRESULT WindowProc( UINT msgID, WPARAM wParam, LPARAM );
};
LRESULT CMyFrameWnd::WindowProc( UINT msgID, WPARAM wParam, LPARAM lParam ){
	//此函数内部的this为pFrame
	switch( msgID ){
	case WM_CREATE:
		AfxMessageBox( "WM_CREATE消息被处理" );
		break;
	case WM_PAINT:
		{
			PAINTSTRUCT ps = { 0 };
			HDC hdc = ::BeginPaint( this->m_hWnd, &ps );
			::TextOut( hdc, 100, 100, "hello", 5 );
			::EndPaint( m_hWnd, &ps );
		}
		break;
	}
	return CFrameWnd::WindowProc(msgID, wParam, lParam);
}
class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};

CMyWinApp theApp;//爆破点

BOOL CMyWinApp::InitInstance( ){
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, "MFCCreate");
		m_pMainWnd = pFrame;
		pFrame->ShowWindow( SW_SHOW );
		pFrame->UpdateWindow( );
		return TRUE;
}
MFC窗口创建过程:

MFC 学习笔记

MFC 学习笔记

CMyFrameWnd* pFrame = new CMyFrameWnd;
pFrame->Create(NULL, "MFCCreate")//函数内部this为pFrame(自己new框架类对象地址)
{
  //加载菜单
  CreateEx(..., NULL,...)//函数内部this为pFrame
  {
    CREATESTRUCT cs;
    ....
    cs.lpszClass = NULL;//下面将更改
    ...
    cs.hInstance = AfxGetInstanceHandle(); //MFC里获取winMain的第一个参数
    PreCreateWindow(cs)
    {
      AfxDeferRegisterClass(...)
      {
	//注册窗口类
        WNDCLASS wndcls;
	...
	wndcls.lpfnWndProc = DefWindowProc;//消息处理存在问题,下面将进行修改
        ...
        _AfxRegisterWithIcon(&wndcls, "AfxFrameOrView100sd"..)
        {
          &wndcls->lpszClassName = "AfxFrameOrView100sd";
          ::RegisterClass(&wndcls)   //在这里执行窗口注册
        }
      }
      cs.lpszClass = _afxWndFrameOrView; //"AfxFrameOrView100sd"
    }
    AfxHookWindowCreate(pFrame)
    {
      _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
                       //获取全局变量&ccc(当前程序线程信息)
       ::SetWindowsHookEx(WH_CBT,_AfxCbtFilterHook,...);
                       //利用Win32的API函数,埋下一个类型为WH_CBT的钩子
       pThreadState->m_pWndInit = pFrame;
                       //将自己new的框架类对象pFrame保存到全局变量ccc的一个成员中。
    }
    ::CreateWindowEx(...);//此函数一旦执行成功,立即转到钩子处理函数。
  }
}

钩子处理函数
_AfxCbtFilterHook(.wParam.)
{
  _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();//获取&ccc
  CWnd* pWndInit = pThreadState->m_pWndInit;//获取pFrame===pWndInit
  HWND hWnd = (HWND)wParam;//刚刚创建成功的框架窗口句柄
  pWndInit->Attach(hWnd)//函数内部this为pFrame,参数为窗口句柄
  {
    CHandleMap* pMap = afxMapHWND(TRUE)
    {
      AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb
      pState->m_pmapHWND = new CHandleMap(..);
                 //new了一个映射类对象,并将对象地址保存到bbb的一个成员中
      return pState->m_pmapHWND;
                 //返回映射类对象地址
    }
    pMap->SetPermanent(m_hWnd = hWnd, pFrame)//函数内部this为pMap
    {
      m_permanentMap[hWnd] = pFrame;
    }
  }
  (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,AfxWndProc);
               //将窗口处理函数更改为AfxWndProc(才是真正的窗口处理函数)
}
处理消息:

MFC 学习笔记

//以WM_CREATE消息为例,捎带想着点WM_PAINT消息
AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
  CWnd* pWnd = CWnd::FromHandlePermanent(hWnd)
  {
    CHandleMap* pMap = afxMapHWND()
    {
      AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();//获取&bbb
      return pState->m_pmapHWND;//返回就是之前保存在bbb中的映射类对象地址
    }
    pWnd = pMap->LookupPermanent(hWnd)//函数内部this为pMap
    {
      return m_permanentMap[hWnd];//返回的为pFrame
    }
  }
  AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam)//参数pWnd===pFrame
  {
    pWnd->WindowProc(nMsg, wParam, lParam);//回到自己的代码
  }
}
消息映射机制:

在不重写WindowProc虚函数的大前提下,仍然可以处理消息。

MFC 学习笔记

具体实现:

MFC 学习笔记

#include <afxwin.h>
class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP()
protected:
	static const AFX_MSGMAP* PASCAL GetThisMessageMap();
	virtual const AFX_MSGMAP* GetMessageMap() const;
public:
	LRESULT OnCreate( WPARAM wParam, LPARAM lParam );
};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
	ON_MESSAGE( WM_CREATE, OnCreate )
END_MESSAGE_MAP()							  

LRESULT CMyFrameWnd::OnCreate( WPARAM wParam, LPARAM lParam ){
	AfxMessageBox( "WM_CREATE" );
	return 0;
}

class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};
CMyWinApp theApp;//爆破点
BOOL CMyWinApp::InitInstance( ){
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, "MFCCreate");
		m_pMainWnd = pFrame;
		pFrame->ShowWindow( SW_SHOW );
		pFrame->UpdateWindow( );
		return TRUE;
}

将这几个宏替换:

#include <afxwin.h>
class CMyFrameWnd : public CFrameWnd{
//	DECLARE_MESSAGE_MAP()
protected:
	static const AFX_MSGMAP* PASCAL GetThisMessageMap();
	virtual const AFX_MSGMAP* GetMessageMap() const;
public:
	LRESULT OnCreate( WPARAM wParam, LPARAM lParam );
};
//BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
//	ON_MESSAGE( WM_CREATE, OnCreate )
//END_MESSAGE_MAP()

const AFX_MSGMAP* CMyFrameWnd::GetMessageMap() const
{
	return GetThisMessageMap();
}
const AFX_MSGMAP* PASCAL CMyFrameWnd::GetThisMessageMap()
{
		static const AFX_MSGMAP_ENTRY _messageEntries[] =
		{
			{ WM_CREATE, 0, 0, 0, AfxSig_lwl, (AFX_PMSG)(AFX_PMSGW)
				(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > (&OnCreate)) },

			{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
		};
		static const AFX_MSGMAP messageMap = { &CFrameWnd::GetThisMessageMap, &_messageEntries[0] };
		return &messageMap;
}								  

LRESULT CMyFrameWnd::OnCreate( WPARAM wParam, LPARAM lParam ){
	AfxMessageBox( "WM_CREATE" );
	return 0;
}

class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};
CMyWinApp theApp;//爆破点
BOOL CMyWinApp::InitInstance( ){
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, "MFCCreate");
		m_pMainWnd = pFrame;
		pFrame->ShowWindow( SW_SHOW );
		pFrame->UpdateWindow( );
		return TRUE;
}

AFX_MSGMAP_ENTRY结构体的解释:

MFC 学习笔记

AFX_MSGMAP结构体的解释:

MFC 学习笔记

展开各部分作用介绍:

MFC 学习笔记

创建窗口的原理:

MFC 学习笔记

代码:

//以WM_CREATE消息为例,捎带想着点WM_PAINT,WM_COMMAND(到了CWnd::OnWndMsg函数路线不一样)
AfxWndProc(...)
{
  CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
             //获取和hWnd绑定在一起的框架类对象地址(pFrame===pWnd)
  AfxCallWndProc(pWnd...)//参数pWnd===pFrame
  {
    pWnd->WindowProc(...)//函数内部this为pFrame===pWnd *************
    {
      OnWndMsg(...)//函数内部this为pFrame===pWnd
      {
        const AFX_MSGMAP* pMessageMap = GetMessageMap();
                       //获取本类宏站开的静态变量的地址(链表头结点)
        const AFX_MSGMAP_ENTRY* lpEntry;

        for (; pMessageMap->pfnGetBaseMap != NULL;//此for就是在遍历链表
			pMessageMap = (*pMessageMap->pfnGetBaseMap)())
        {
           lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,message, 0, 0));
                           //如果找到返回找到的数组元素的地址,如果没找到返回NULL
           if(lpEntry != NULL )
           {
             goto LDispatch;
           }

        }
        LDispatch:
            lpEntry->pfn; //CMyFrameWnd::OnCreate
            调用CMyFrameWnd::OnCreate函数完成消息的处理

      }
    }
  }
}

三.MFC消息:

消息的分类:

MFC 学习笔记

示例:

#include <afxwin.h>
#define WM_MYMESSAGE WM_USER+1001
class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP()
public:
	int OnCreate( LPCREATESTRUCT pcs);
	void OnPaint( );
	void OnMouseMove( UINT nKey, CPoint pt );
	LRESULT OnMyMessage( WPARAM wParam, LPARAM lParam );
	int m_x;
	int m_y;
};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
	ON_WM_CREATE()
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE( WM_MYMESSAGE,  OnMyMessage)
END_MESSAGE_MAP()

LRESULT CMyFrameWnd::OnMyMessage( WPARAM wParam, LPARAM lParam ){
	CString str;
	str.Format( "wParam=%d,lParam=%d", wParam, lParam );
	AfxMessageBox( str );
	return 0;
}
void CMyFrameWnd::OnMouseMove( UINT nKey, CPoint pt){
	m_x = pt.x;
	m_y = pt.y;
	::InvalidateRect( this->m_hWnd, NULL, TRUE );
}
void CMyFrameWnd::OnPaint( ){
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint( this->m_hWnd, &ps );
	::TextOut( hdc, m_x, m_y, "hello", 5);
	::EndPaint( m_hWnd, &ps );
}
int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){
	AfxMessageBox("WM_CREATE消息被处理");
	::PostMessage( this->m_hWnd, WM_MYMESSAGE, 1, 2 );
	return CFrameWnd::OnCreate( pcs );
}
class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};
CMyWinApp theApp;//爆破点
BOOL CMyWinApp::InitInstance( ){
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, "MFCCreate");
		m_pMainWnd = pFrame;
		pFrame->ShowWindow( SW_SHOW );
		pFrame->UpdateWindow( );
		return TRUE;
}
MFC菜单:

MFC 学习笔记

菜单的使用:

MFC 学习笔记

方法一:

MFC 学习笔记

方法二:

#include <afxwin.h>
#include "resource.h"
class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP( )
public:
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
	afx_msg void OnNew( );
public:
	CMenu menu;
};
BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd )
	ON_COMMAND( ID_NEW, OnNew )
	ON_WM_CREATE( )
END_MESSAGE_MAP( )

void CMyFrameWnd::OnNew( ){
	AfxMessageBox( "框架类处理了新建菜单项被点击" );
}
int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){
	//调用api(win32)的loadmenu方法拿到句柄,将菜单句柄和menu对象建立一对一的关系。
	menu.LoadMenu( IDR_MENU1 );
//	this->SetMenu( &menu );
	::SetMenu( this->m_hWnd, menu.m_hMenu);
	return CFrameWnd::OnCreate( pcs );
}
class CMyWinApp : public CWinApp{
	DECLARE_MESSAGE_MAP()
public:
	virtual BOOL InitInstance( );
	afx_msg void OnNew( );
};
BEGIN_MESSAGE_MAP(CMyWinApp, CWinApp)
	ON_COMMAND( ID_NEW , OnNew )
END_MESSAGE_MAP( )
void CMyWinApp::OnNew( ){
	AfxMessageBox( "应用程序类处理了新建被点击" );
}
BOOL CMyWinApp::InitInstance( ){
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, "MFCCreate");
		m_pMainWnd = pFrame;
		pFrame->ShowWindow( SW_SHOW );
		pFrame->UpdateWindow( );
		return TRUE;
}
CMyWinApp theApp;

菜单项没有对应的消息处理,就会默认灰显。

命令消息处理顺序:

(仅针对command消息类,其他类只有框架类处理一条路径)

框架类 ——> 应用程序处理类

设置菜单项状态:

MFC 学习笔记

设置右键菜单(上下文菜单):

MFC 学习笔记

代码:

#include <afxwin.h>
#include "resource.h"
class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP( )
public:
    //afx_msg  占位符 标识这个方法是处理消息的
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
	afx_msg void OnNew( );
	afx_msg void OnInitMenuPopup( CMenu *pPopup, UINT nPos, BOOL i );
	afx_msg void OnContextMenu( CWnd* pWnd, CPoint pt );
public:
	CMenu menu;
};
BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd )
//	ON_COMMAND( ID_NEW, OnNew )
	ON_WM_CREATE( )
	ON_WM_INITMENUPOPUP()
	ON_WM_CONTEXTMENU( )
END_MESSAGE_MAP( )
void CMyFrameWnd::OnContextMenu( CWnd* pWnd, CPoint pt ){
    //获取整个大菜单顶层为0的子菜单
//	HMENU hPopup = ::GetSubMenu(menu.m_hMenu,0);
//	::TrackPopupMenu( hPopup, TPM_LEFTALIGN|TPM_TOPALIGN, pt.x, pt.y,
//										0, this->m_hWnd, NULL );
	CMenu* pPopup = menu.GetSubMenu(0);
	pPopup->TrackPopupMenu( TPM_LEFTALIGN|TPM_TOPALIGN, pt.x, pt.y, this );
}
void CMyFrameWnd::OnInitMenuPopup( CMenu* pPopup, UINT nPos, BOOL i){
//	pPopup->CheckMenuItem( ID_NEW, MF_CHECKED );
	::CheckMenuItem( pPopup->m_hMenu, ID_NEW, MF_CHECKED );
}

class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};
BOOL CMyWinApp::InitInstance( ){
		CMyFrameWnd* pFrame = new CMyFrameWnd;
		pFrame->Create(NULL, "MFCCreate");
		m_pMainWnd = pFrame;
		pFrame->ShowWindow( SW_SHOW );
		pFrame->UpdateWindow( );
		return TRUE;
}
CMyWinApp theApp;

效果:

MFC 学习笔记

四.MFC工具栏以及两大机制:

工具栏:

相关类:

MFC 学习笔记

工具栏的使用:

MFC 学习笔记

代码:

  #include <afxwin.h>
#include "resource.h"
#include <afxext.h>
class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP( )
public:
	afx_msg void OnNew( );
	afx_msg void OnSet( );
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
public:
	CToolBar toolbar;
};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd )
	ON_COMMAND( ID_SET, OnSet)
	ON_COMMAND( ID_NEW, OnNew )
	ON_WM_CREATE()
END_MESSAGE_MAP()
void CMyFrameWnd::OnSet( ){
	AfxMessageBox( "绿色工具按钮被点击" );
}
int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){
	toolbar.CreateEx( this, TBSTYLE_FLAT, WS_CHILD|WS_VISIBLE|CBRS_ALIGN_TOP|CBRS_GRIPPER);
	toolbar.LoadToolBar( IDR_TOOLBAR1 );
	//想停哪儿
	toolbar.EnableDocking( CBRS_ALIGN_ANY  );
	//允许停哪儿
	this->EnableDocking( CBRS_ALIGN_ANY );
	//临时停哪儿
	this->DockControlBar( &toolbar, AFX_IDW_DOCKBAR_BOTTOM );
	return CFrameWnd::OnCreate( pcs );
}
void CMyFrameWnd::OnNew(){
	AfxMessageBox( "新建菜单项被点击" );
}
class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};
BOOL CMyWinApp::InitInstance(){
	CMyFrameWnd* pFrame = new CMyFrameWnd;
	pFrame->Create( NULL, "MFCToolBar", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault,
									NULL, (CHAR*)IDR_MENU1);
	m_pMainWnd = pFrame;
	pFrame->ShowWindow( SW_SHOW );
	pFrame->UpdateWindow( );
	return TRUE;
}
CMyWinApp theApp;
运行时类信息机制:

在程序运行过程中可以获知对象的类的相关信息(例如:对象是否属于某个类)

使用:

MFC 学习笔记

代码:

#include <afxwin.h>
#include <iostream>
using namespace std;
class CAnimal : public CObject{
	DECLARE_DYNAMIC( CAnimal )
};
IMPLEMENT_DYNAMIC( CAnimal, CObject )

class CDog : public CAnimal{
//	DECLARE_DYNAMIC( CDog )
public:
	static const CRuntimeClass classCDog;
	virtual CRuntimeClass* GetRuntimeClass() const;
};
//IMPLEMENT_DYNAMIC( CDog, CAnimal )
//IMPLEMENT_RUNTIMECLASS(CDog, CAnimal, 0xFFFF, NULL, NULL)
AFX_COMDAT const CRuntimeClass CDog::classCDog = {
		"CDog",
		sizeof(class CDog),
		0xFFFF,
		NULL,
//		RUNTIME_CLASS(CAnimal),
		 ((CRuntimeClass*)(&CAnimal::classCAnimal)),
		NULL,
		NULL
};
CRuntimeClass* CDog::GetRuntimeClass() const
{
//	return RUNTIME_CLASS(CDog);
	return ((CRuntimeClass*)(&CDog::classCDog));
}

int main(){
	CDog yellowdog;
	if( yellowdog.IsKindOf( RUNTIME_CLASS(CWnd) ) ){
		cout << "yellowdog is CWnd" << endl;
	}else{
		cout << "yellowdog isnot CWnd" << endl;
	}
	return 0;
}

CRuntimeClass的数据结构:

MFC 学习笔记

宏展开各部分:

MFC 学习笔记

MFC 学习笔记

执行过程:

关注这个宏 RUNTIME_CLASS(CDog)

MFC 学习笔记

伪代码:

yellowdog.IsKindOf( RUNTIME_CLASS(CDog))//函数内部this为&yellowdog,参数为链表头
{
  CRuntimeClass* pClassThis = GetRuntimeClass();
                     //利用&yellowdog调用宏展开虚函数,获取链表头结点

  return pClassThis->IsDerivedFrom(RUNTIME_CLASS(CDog))
				//函数内部this为链表头,参数也为链表头
  {
    const CRuntimeClass* pClassThis = this;//获取链表头
    while (pClassThis != NULL)
    {
      	if (pClassThis == RUNTIME_CLASS(CDog))
	    return TRUE;
        pClassThis = pClassThis->m_pBaseClass;
    }
    return FALSE;
  }
}
动态创建机制:

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

使用:

MFC 学习笔记

#include <afxwin.h>
#include <iostream>
using namespace std;
class CAnimal : public CObject{
	DECLARE_DYNAMIC( CAnimal )
};
IMPLEMENT_DYNAMIC( CAnimal, CObject )
class CDog : public CAnimal{
//	DECLARE_DYNCREATE( CDog )
public:
	static const CRuntimeClass classCDog;
	virtual CRuntimeClass* GetRuntimeClass() const;
	static CObject* PASCAL CreateObject();
};
//IMPLEMENT_DYNCREATE( CDog, CAnimal )
CObject* PASCAL CDog::CreateObject()
{
	return new CDog;
}
AFX_COMDAT const CRuntimeClass CDog::classCDog = {
		"CDog",
		sizeof(class CDog),
		0xFFFF,
		CDog::CreateObject,
		RUNTIME_CLASS(CAnimal),
		NULL,
		NULL
};
CRuntimeClass* CDog::GetRuntimeClass() const
{
	return RUNTIME_CLASS(CDog);
}

int main(){
	CObject* pob = RUNTIME_CLASS(CDog)->CreateObject( );//对象加工厂
	if( pob ){
		cout << pob << endl;
	}else{
		cout << "对象创建失败" << endl;
	}
	return 0;
}

与运行时类信息机制区别:

MFC 学习笔记

MFC 学习笔记

代码:

RUNTIME_CLASS(CDog)->CreateObject()//函数内部this为本类(CDog)的静态变量地址(链表头
{
  CObject* pObject = (*m_pfnCreateObject)() //CDog::CreateObject
  {
    return new CDog;
  }
  return pObject;
}

五.MFC视图和文档

视图窗口:

提供了一个用于显示数据的窗口

相关类:

CView及其子类,父类为CWnd类,封装了关于视图窗口的各种操作,以及和文档类的数据交互。

使用:

MFC 学习笔记

命令消息处理顺序:

视图类 -> 框架类 ->应用程序类

对象关系图:

MFC 学习笔记

MFC 学习笔记

代码:

#include <afxwin.h>
#include "resource.h"
class CMyView : public CView{
	DECLARE_MESSAGE_MAP( )
public:
	void OnDraw(CDC* pDC);
	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( "视图类处理了WM_COMMAND消息" );
}
void CMyView::OnPaint( ){
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint( this->m_hWnd, &ps );
	::TextOut( hdc, 200, 200, "CMyView::OnPaint", strlen("CMyView::OnPaint") );
	::EndPaint( this->m_hWnd, &ps );
}
void CMyView::OnDraw( CDC* pDC ){
	pDC->TextOut( 100, 100, "CMyView::OnDraw" );
}
class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnPaint( );
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
	afx_msg void OnNew( );
};
BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd )
	ON_WM_PAINT( )
//	ON_COMMAND( ID_NEW, OnNew )
	ON_WM_CREATE( )
END_MESSAGE_MAP( )
void CMyFrameWnd::OnNew( ){
	AfxMessageBox( "框架类处理了WM_COMMAND消息" );
}
int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){
	CMyView* pView = new CMyView;
	pView->Create( NULL, "MFCView", WS_CHILD|WS_VISIBLE|WS_BORDER, CRect(0,0,200,200), this,
									AFX_IDW_PANE_FIRST );
	this->m_pViewActive = pView; //视图类对象地址
	return CFrameWnd::OnCreate( pcs );
}
void CMyFrameWnd::OnPaint( ){
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint( this->m_hWnd, &ps );
	::TextOut( hdc, 100, 100, "我是框架窗口客户区", strlen("我是框架窗口客户区"));
	::EndPaint( this->m_hWnd, &ps );
}
class CMyWinApp : public CWinApp{
	DECLARE_MESSAGE_MAP( )
public:
	virtual BOOL InitInstance( );
	afx_msg void OnNew( );
};
BEGIN_MESSAGE_MAP(CMyWinApp,CWinApp)
	ON_COMMAND( ID_NEW, OnNew )
END_MESSAGE_MAP( )
void CMyWinApp::OnNew( ){
	AfxMessageBox( "应用程序类处理了WM_COMMAND消息" );
}
BOOL CMyWinApp::InitInstance( ){
	CMyFrameWnd* pFrame = new CMyFrameWnd;
	pFrame->Create( NULL, "MFCView", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault,
										NULL, (CHAR*)IDR_MENU1);
	this->m_pMainWnd = pFrame;
	pFrame->ShowWindow( SW_SHOW );
	pFrame->UpdateWindow( );
	return TRUE;
}
CMyWinApp theApp;
文档类:

MFC 学习笔记

程序的创建过程:

MFC 学习笔记

MFC 学习笔记

代码:

CMyFrameWnd* pFrame = new CMyFrameWnd;
CMyDoc* pDoc = new CMyDoc;

CCreateContext cct;
cct.m_pCurrentDoc = pDoc;//文档类对象地址
cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView

pFrame->LoadFrame(... &cct)//函数内部this为pFrame
{
  Create(...,&cct)//函数内部this为pFrame
  {
    CreateEx(...&cct)//函数内部this为pFrame
    {
      CREATESTRUCT cs;
      ....
      cs.lpCreateParams = &cct;
      ::CreateWindowEx(...,&cct);//创建主框架窗口
    }
  }
}
//处理框架窗口的WM_CREATE消息
CFrameWnd::OnCreate( pcs )//函数内部this为pFrame,参数可以获取::CreateWindowEx的12个参数
{
  CCreateContext* pContext = (CCreateContext*)pcs->lpCreateParams;//获取&cct
  OnCreateHelper(pcs, pContext)//函数内部this为pFrame,pContext===&cct
  {
    OnCreateClient(pcs, pContext)//函数内部this为pFrame,pContext===&cct
    {
      CreateView(pContext..)//函数内部this为pFrame,pContext===&cct
      {
        CWnd* pView = pContext->m_pNewViewClass->CreateObject();
                            //动态创建视图类对象,并返回对象地址
        pView->Create(..,pContext)//函数内部this为pView,pContext===&cct
        {
          CreateEx(..,pContext)//函数内部this为pView,pContext===&cct
          {
            CREATESTRUCT cs;
            ....
            cs.lpCreateParams = pContext;//pContext===&cct
            ::CreateWindowEx(...,pContext);//创建视图窗口
          }
        }
      }
    }
  }
}

//处理视图窗口的WM_CREATE消息
CView::OnCreate( pcs )//函数内部this为pView,参数可以获取::CreateWindowEx函数的12个参数
{
  CCreateContext* pContext = (CCreateContext*)lpcs->lpCreateParams;//获取&cct
  pContext->m_pCurrentDoc->AddView(pView)//函数内部this为pDoc,参数为视图类对象地址
  {
    m_viewList.AddTail(pView);//文档类对象用一个链表成员变量,保存视图类对象地址
    pView->m_pDocument = this;//视图类对象用一个普通成员变量,保存文档类对象地址
  }
}

对象关系图:

MFC 学习笔记

MFC 学习笔记

MFC 学习笔记

窗口切分:

MFC 学习笔记

代码:

#include <afxwin.h>
#include <afxext.h>
#include "resource.h"
class CMyDoc : public CDocument{
};

class CMyView : public CView{
	DECLARE_DYNCREATE( CMyView ) //动态创建机制
	DECLARE_MESSAGE_MAP( )
public:
	virtual void OnDraw(CDC* pDC);
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
};
IMPLEMENT_DYNCREATE( CMyView, CView )
BEGIN_MESSAGE_MAP( CMyView, CView)
	ON_WM_CREATE( )
END_MESSAGE_MAP()
int CMyView::OnCreate( LPCREATESTRUCT pcs ){
	return CView::OnCreate( pcs ); //将文档类对象和视图类对象建立关联关系。
}
void CMyView::OnDraw( CDC* pDC ){
	pDC->TextOut( 100, 100, "我是视图窗口" );
}

class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP( )
public:
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
	afx_msg void OnPaint( );
	virtual BOOL OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext);
	CSplitterWnd split;//不规则框架窗口
};
BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd )
	ON_WM_PAINT( )
	ON_WM_CREATE( )
END_MESSAGE_MAP( )
BOOL CMyFrameWnd::OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext ){
	//创建两个视图窗口
	split.CreateStatic( this, 1, 2 );//创建倒日型框架
	split.CreateView( 0, 0, RUNTIME_CLASS(CMyView), CSize(100,100), pContext );
	split.CreateView( 0, 1, pContext->m_pNewViewClass, CSize(100,100), pContext );
	return TRUE;
}
void CMyFrameWnd::OnPaint( ){
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint( this->m_hWnd, &ps );
	::TextOut( hdc, 200, 200, "我是框架窗口客户区", strlen("我是框架窗口客户区"));
	::EndPaint( this->m_hWnd, &ps );
}
int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){
	return CFrameWnd::OnCreate( pcs );//动态创建视图类对象,并创建视图窗口
}
class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};
BOOL CMyWinApp::InitInstance( ){
	CMyFrameWnd* pFrame = new CMyFrameWnd;
	CMyDoc* pDoc = new CMyDoc;

	CCreateContext cct;
	cct.m_pCurrentDoc = pDoc;//文档类对象地址
	cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView

	pFrame->LoadFrame( IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL,  &cct);
	m_pMainWnd = pFrame;
	pFrame->ShowWindow( SW_SHOW );
	pFrame->UpdateWindow( );
	return TRUE;
}
CMyWinApp theApp;

命令消息处理顺序:

MFC 学习笔记

MFC 学习笔记

代码:

//WM_COMMAND消息的路线
OnCommand(wParam, lParam)//函数内部this为pFrame
{
  CWnd::OnCommand(..)//函数内部this为pFrame
  {
    OnCmdMsg(...)//函数内部this为pFrame   *****CFrameWnd::OnCmdMsg 起点
    {
      CView* pView = GetActiveView()//函数内部this为pFrame
      {
        return this->m_pViewActive;//活动视图窗口对象地址
      }对象
      pView->OnCmdMsg(..) ===>终点 CCmdTarget::OnCmdMsg 此函数内部this为pView
      m_pDocument->OnCmdMsg(.)==>终点CCmdTarget::OnCmdMsg 此函数内部this为文档类对象
      CWnd::OnCmdMsg(..)==>终点 CCmdTarget::OnCmdMsg 此函数内部this为pFrame

      CWinApp* pApp = AfxGetApp();//获取&theApp
      pApp->OnCmdMsg(..)==>终点 CCmdTarget::OnCmdMsg 此函数内部this为&theApp

    }
  }
}

文档类和视图类关系:

MFC 学习笔记

MFC 学习笔记

代码:

#include <afxwin.h>
#include <afxext.h>
#include "resource.h"
class CMyDoc : public CDocument{
	DECLARE_MESSAGE_MAP( )
public:
	afx_msg void OnNew( );
	CString str;
};
BEGIN_MESSAGE_MAP( CMyDoc, CDocument )
	ON_COMMAND( ID_NEW, OnNew )
END_MESSAGE_MAP( )
void CMyDoc::OnNew( ){
	this->str = "hello world"; //接受到的数据。
//	this->UpdateAllViews( NULL );//刷新和这个文档类对象(this)关联的所有视图窗口
	//this->m_viewList;
	POSITION pos = this->GetFirstViewPosition(); //GetFirstXXXPosition
	CView* pView = this->GetNextView(pos);   //GetNextXXX
	this->UpdateAllViews( pView );//刷新和这个文档类对象(this)关联的除了pView指向的视图窗口
}
class CMyView : public CView{
	DECLARE_DYNCREATE( CMyView ) //动态创建机制
	DECLARE_MESSAGE_MAP( )
public:
	virtual void OnDraw(CDC* pDC);
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
	afx_msg void OnNew( );
};
IMPLEMENT_DYNCREATE( CMyView, CView )
BEGIN_MESSAGE_MAP( CMyView, CView)
//	ON_COMMAND( ID_NEW, OnNew )
	ON_WM_CREATE( )
END_MESSAGE_MAP()
void CMyView::OnNew( ){
	AfxMessageBox( "视图类处理的WM_COMMAND消息" );
}
int CMyView::OnCreate( LPCREATESTRUCT pcs ){
	return CView::OnCreate( pcs ); //将文档类对象和视图类对象建立关联关系。
}
void CMyView::OnDraw( CDC* pDC ){
//	CMyDoc* pDoc = (CMyDoc*)this->m_pDocument;
	CMyDoc* pDoc = (CMyDoc*)this->GetDocument( );
	pDC->TextOut( 100, 100, pDoc->str );
}

class CMyFrameWnd : public CFrameWnd{
	DECLARE_MESSAGE_MAP( )
public:
	afx_msg int OnCreate( LPCREATESTRUCT pcs );
	afx_msg void OnPaint( );
	virtual BOOL OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext);
	CSplitterWnd split;//不规则框架窗口
	afx_msg void OnNew( );
};
BEGIN_MESSAGE_MAP( CMyFrameWnd, CFrameWnd )
//	ON_COMMAND( ID_NEW, OnNew)
	ON_WM_PAINT( )
	ON_WM_CREATE( )
END_MESSAGE_MAP( )
void CMyFrameWnd::OnNew( ){
	AfxMessageBox( "框架类处理了新建被点击" );
}
BOOL CMyFrameWnd::OnCreateClient( LPCREATESTRUCT pcs, CCreateContext* pContext ){
	//创建两个视图窗口
	split.CreateStatic( this, 1, 2 );
	split.CreateView( 0, 0, RUNTIME_CLASS(CMyView), CSize(100,100), pContext );
	split.CreateView( 0, 1, pContext->m_pNewViewClass, CSize(100,100), pContext );
	m_pViewActive = (CView*)split.GetPane(0,0);
	return TRUE;
}
void CMyFrameWnd::OnPaint( ){
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint( this->m_hWnd, &ps );
	::TextOut( hdc, 200, 200, "我是框架窗口客户区", strlen("我是框架窗口客户区"));
	::EndPaint( this->m_hWnd, &ps );
}
int CMyFrameWnd::OnCreate( LPCREATESTRUCT pcs ){
	return CFrameWnd::OnCreate( pcs );//动态创建视图类对象,并创建视图窗口
}
class CMyWinApp : public CWinApp{
	DECLARE_MESSAGE_MAP( )
public:
	virtual BOOL InitInstance( );
	afx_msg void OnNew( );
};
BEGIN_MESSAGE_MAP( CMyWinApp, CWinApp )
//	ON_COMMAND( ID_NEW, OnNew )
END_MESSAGE_MAP( )
void CMyWinApp::OnNew( ){
	AfxMessageBox( "应用程序类处理了WM_COMMAND消息" );
}
BOOL CMyWinApp::InitInstance( ){
	CMyFrameWnd* pFrame = new CMyFrameWnd;
	CMyDoc* pDoc = new CMyDoc;

	CCreateContext cct;
	cct.m_pCurrentDoc = pDoc;//文档类对象地址
	cct.m_pNewViewClass = RUNTIME_CLASS(CMyView);//&CMyView::classCMyView

	pFrame->LoadFrame( IDR_MENU1, WS_OVERLAPPEDWINDOW, NULL,  &cct);
	m_pMainWnd = pFrame;
	pFrame->ShowWindow( SW_SHOW );
	pFrame->UpdateWindow( );
	return TRUE;
}
CMyWinApp theApp;

六.MFC架构程序

单文档视图架构:

单文档视图架构特点:

只能管理一个文档(只有一个文档类对象)

单文档视图架构使用:

MFC 学习笔记

实现:

#include <afxwin.h>
#include "resource.h"
class CMyDoc : public CDocument{
	DECLARE_DYNCREATE( CMyDoc )
};
IMPLEMENT_DYNCREATE( CMyDoc, CDocument )

class CMyView : public CView{
	DECLARE_DYNCREATE( CMyView )
public:
	virtual void OnDraw( CDC* pDC );
};
IMPLEMENT_DYNCREATE( CMyView, CView )
void CMyView::OnDraw( CDC* pDC ){
	pDC->TextOut( 100, 100, "我是视图窗口" );
}

class CMyFrameWnd : public CFrameWnd{
	DECLARE_DYNCREATE( CMyFrameWnd )
};
IMPLEMENT_DYNCREATE( CMyFrameWnd, CFrameWnd )

class CMyWinApp : public CWinApp{
public:
	virtual BOOL InitInstance( );
};
BOOL CMyWinApp::InitInstance( ){
	CSingleDocTemplate* pTemplate = new CSingleDocTemplate( IDR_MENU1,
																										RUNTIME_CLASS(CMyDoc),
																										RUNTIME_CLASS(CMyFrameWnd),
																										RUNTIME_CLASS(CMyView) );
	AddDocTemplate( pTemplate );
	OnFileNew( );
	m_pMainWnd->ShowWindow( SW_SHOW );
	m_pMainWnd->UpdateWindow( );
	return TRUE;
}
CMyWinApp theApp;

执行过程:

MFC 学习笔记

MFC 学习笔记

伪代码:

OnFileNew( )//函数内部this为&theApp
{
  m_pDocManager->OnFileNew()//函数内部this为文档管理类对象地址
  {
    CDocTemplate* pTemplate = m_templateList.GetHead();//取出单文档模板类对象地址
    pTemplate->OpenDocumentFile()//函数内部this为单文档模板类对象地址
    {
      OpenDocumentFile(..)//函数内部this为单文档模板类对象地址
      {
        pDocument = CreateNewDocument()//函数内部this为单文档模板类对象地址
        {
          CDocument* pDocument = m_pDocClass->CreateObject();
                               //动态创建文档类对象,并返回对象地址
          AddDocument(pDocument)//函数内部this为单文档模板类对象地址
          {
            m_pOnlyDoc = pDocument;
          }
        }
        pFrame = CreateNewFrame(pDocument..)//函数内部this为单文档模板类对象地址
        {
          CCreateContext context;
	  ...
	  context.m_pCurrentDoc = pDocument;//文档类对象地址
	  context.m_pNewViewClass = m_pViewClass;//RUNTIME_CLASS(CMyView)
          CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
                               //动态创建框架类对象,并返回对象地址
          pFrame->LoadFrame(...., &context);//创建框架窗口
                      //后续过程看前一天的伪代码
        }
      }
    }
  }
}

关于类向导的使用:

类向导可以帮助我们在已有的框架创建基础上再进一步帮我们生成代码。

选择: 位置 ->类向导

MFC 学习笔记

再这个里面可以选择要添加的项目,添加到的文件,添加的内容,框架会帮我们生成规范化的内容,我们只需要实现具体细节。

多文档视图架构:

特点:

可以管理多个文档 (可以有多个文档类对象)

多文档视图架构使用:

MFC 学习笔记

执行过程:

MFC 学习笔记

MFC 学习笔记

代码:

#include <afxwin.h>
#include "resource.h"
class CMyDoc : public CDocument{
	DECLARE_DYNCREATE( CMyDoc )
};
IMPLEMENT_DYNCREATE( CMyDoc, CDocument )
class CMyView : public CView{
	DECLARE_DYNCREATE( CMyView )
public:
	virtual void OnDraw( CDC* pDC );
};
IMPLEMENT_DYNCREATE( CMyView, CView )
void CMyView::OnDraw( CDC* pDC ){
	pDC->TextOut( 100, 100, "我是视图窗口" );
}
class CMyChild : public CMDIChildWnd{
	DECLARE_DYNCREATE( CMyChild )
};
IMPLEMENT_DYNCREATE( CMyChild, CMDIChildWnd )
class CMyFrameWnd : public CMDIFrameWnd{ //自己造主框架窗口类的对象
};
class CMyWinApp : public CWinApp{//自己造应用程序类的对象
public:
	virtual BOOL InitInstance( );
};
BOOL CMyWinApp::InitInstance( ){
	CMyFrameWnd* pFrame = new CMyFrameWnd;
	pFrame->LoadFrame( IDR_MENU1 );
	m_pMainWnd = pFrame;
	pFrame->ShowWindow( SW_SHOW );
	pFrame->UpdateWindow( );

	CMultiDocTemplate* pTemplate = new CMultiDocTemplate( IDR_MENU2,
																										RUNTIME_CLASS(CMyDoc),
																										RUNTIME_CLASS(CMyChild),
																										RUNTIME_CLASS(CMyView));
	AddDocTemplate( pTemplate );

	OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联
	OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联
	OnFileNew( );//创建文档类对象,创建子框架类对象,创建子框架窗口,创建视图类对象,创建视图窗口,文档类对象和视图类对象关联

	return TRUE;
}
CMyWinApp theApp;
MFC绘图:

MFC 学习笔记

绘图相关类:

MFC 学习笔记

MFC 学习笔记

伪代码:

绘图相关的
***********************************************
CPaintDC dc(pView) === CPaintDC::CPaintDC(...)//函数内部this为&dc
{
  Attach(::BeginPaint(pView->m_hWnd, &m_ps))//函数内部this为&dc
  {
    m_hDC = hDC;//将BeginPaint获取的绘图设备句柄  保存到dc对象的一个成员变量中
    SetAttribDC(m_hDC)//函数内部this为&dc
    {
      m_hAttribDC = m_hDC;//dc对象的另一个成员变量也保存了绘图设备句柄
    }
  }
}

CPen pen(PS_SOLID, 2, RGB(255,0,0)) === CPen::CPen(PS_SOLID, 2, RGB(255,0,0))
//函数内部this &pen
{
  Attach(::CreatePen(PS_SOLID, 2, RGB(255,0,0)))//函数内部this &pen
  {
    m_hObject = hObject;//将::CreatePen获取的画笔句柄,保存到pen对象的一个成员变量中
  }
}

view类:


// MFCDrawView.cpp : implementation of the CMFCDrawView class
//

#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "MFCDraw.h"
#endif

#include "MFCDrawDoc.h"
#include "MFCDrawView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CMFCDrawView

IMPLEMENT_DYNCREATE(CMFCDrawView, CView)

BEGIN_MESSAGE_MAP(CMFCDrawView, CView)
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_WM_PAINT()
	ON_COMMAND(ID_CLIENT, &CMFCDrawView::OnClient)
	ON_COMMAND(ID_PEN, &CMFCDrawView::OnPen)
	ON_COMMAND(ID_BRUSH, &CMFCDrawView::OnBrush)
	ON_COMMAND(ID_FONT, &CMFCDrawView::OnFont)
	ON_COMMAND(ID_BMP, &CMFCDrawView::OnBmp)
END_MESSAGE_MAP()

// CMFCDrawView construction/destruction

CMFCDrawView::CMFCDrawView()
{
	// TODO: add construction code here

}

CMFCDrawView::~CMFCDrawView()
{
}

BOOL CMFCDrawView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

// CMFCDrawView drawing

void CMFCDrawView::OnDraw(CDC* /*pDC*/)
{
	CMFCDrawDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: add draw code for native data here
}

// CMFCDrawView printing

BOOL CMFCDrawView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMFCDrawView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMFCDrawView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

// CMFCDrawView diagnostics

#ifdef _DEBUG
void CMFCDrawView::AssertValid() const
{
	CView::AssertValid();
}

void CMFCDrawView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMFCDrawDoc* CMFCDrawView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMFCDrawDoc)));
	return (CMFCDrawDoc*)m_pDocument;
}
#endif //_DEBUG

// CMFCDrawView message handlers

void CMFCDrawView::OnPaint()
{
	CPaintDC dc(this); //::BeginPaint
//	dc.Rectangle( 100, 100, 300, 300 );//::Rectangle(...)
//	::Rectangle( dc.m_hDC, 100, 100, 300, 300 );
}

void CMFCDrawView::OnClient()
{
	CClientDC dc(this);
	dc.Ellipse( 300, 300, 500, 500 );
}

void CMFCDrawView::OnPen()
{
	CClientDC dc( this );
	CPen pen(PS_SOLID, 2, RGB(255,0,0));

//	CPen* oldpen = dc.SelectObject( &pen );
	HGDIOBJ nOldPen = ::SelectObject( dc.m_hDC, pen.m_hObject );

//	dc.Rectangle( 100, 100, 300, 300 );
	::Rectangle( dc.m_hDC, 100, 100, 300, 300 );

//	dc.SelectObject( oldpen );
	::SelectObject( dc.m_hDC, nOldPen );

//	pen.DeleteObject( );
	::DeleteObject( pen.m_hObject );
}

void CMFCDrawView::OnBrush()
{
	CClientDC dc(this);
	CBrush brush(RGB(0,255,0));
	CBrush* oldbrush = dc.SelectObject( &brush );
	dc.Rectangle( 100, 100, 300, 300 );
	dc.SelectObject( oldbrush );
	brush.DeleteObject( );
}

void CMFCDrawView::OnFont()
{
	CClientDC dc( this );
	CFont font;
	font.CreatePointFont(300, "黑体");//::CreateFont(..............)
	CFont* oldfont = dc.SelectObject( &font );
	dc.TextOut( 100, 100, "hello");
	dc.SelectObject( oldfont );
	font.DeleteObject();
}

void CMFCDrawView::OnBmp()
{
	//添加位图资源(操作资源无需写代码)

	//创建一个和当前DC,相匹配的内存DC
	CClientDC dc( this );
	CDC memdc;
	memdc.CreateCompatibleDC( &dc ); //::CreateCompatibleDC
	//将位图的数据送给内存DC
	CBitmap bmp;
	bmp.LoadBitmap( IDB_BITMAP1 ); //::LoadBitmap

	CBitmap* oldbmp = memdc.SelectObject( &bmp );//::SelectObject
	//成像
	dc.BitBlt( 100, 100, 48, 48, &memdc, 0, 0, SRCCOPY );//::BitBlt
	//将位图数据要回来
	memdc.SelectObject( oldbmp );//::SelectObject
	//销毁位图
	bmp.DeleteObject( );//::DeleteObject
	//销毁内存DC
	memdc.DeleteDC( );//::DeleteDC
}

七、序列化机制:

文件序列化与反序列化:

文件操作相关类:

MFC 学习笔记

代码 :

#include <afxwin.h>
#include <iostream>
using namespace std;
void File( ){
	CFile file;
	file.Open( "E:/MFC/Day07/file.txt", CFile::modeCreate|CFile::modeReadWrite );
	char str[] = "hello file";
	file.Write( str, strlen(str) );
	file.SeekToBegin( );
	char buf[256] = { 0 };
	long nLen = file.Read( buf, 255 );
	cout << buf << ' ' << nLen << endl;
	file.Close( );
}
int main(){
	File( );
	return 0;
}

MFC 学习笔记

序列化机制使用:

MFC 学习笔记

反序列化机制使用:

MFC 学习笔记

代码:

#include <afxwin.h>
#include <iostream>
using namespace std;
void Store( ){//序列化(存储、写)数据
	CFile file;
	file.Open( "E:/MFC/Day07/serial.txt", CFile::modeCreate | CFile::modeWrite );
	CArchive ar(&file, CArchive::store, 4096);//归档类对象,维护缓冲区。
	long age = 18;
	ar << age;//将18保存当前指向的位置,并向后移动当前指向,相应字节数。
	float score = 88.5;
	ar << score;//将88.5保存当前指向的位置,并向后移动当前指向,相应字节数。
	CString name = "zhangsan";
	ar << name;
	ar.Close( );
	file.Close( );
}
void Load( ){//反序列化(加载/读)
	CFile file;
	file.Open( "E:/MFC/day07/serial.txt", CFile::modeRead );
	CArchive ar( &file, CArchive::load, 4096 );//维护一个buff,大小4096字节
	long age;
	ar >> age;//当反序列化第一个数据时候,内部将文件中所有数据读入ar维护的buff中
	float score;
	ar >> score;//当反序列化后续数据时候,不需要到硬盘文件中读取,直接到ar维护的buff中读取
	CString name;
	ar >> name;//当反序列化后续数据时候,不需要到硬盘文件中读取,直接到ar维护的buff中读取
	ar.Close( );
	file.Close( );
	cout << age << ' ' << score << ' ' << name << endl;
}
int main(){
	Store( );
	Load( );
	return 0;
}

执行过程:

MFC 学习笔记

序列化过程:

MFC 学习笔记

伪代码:

class CArchive{
        enum Mode { store = 0, load = 1…};
	BOOL m_nMode;  //访问方式
	int m_nBufSize;    //buff的大小
	CFile* m_pFile;     //操作的文件对象
	BYTE* m_lpBufCur;  //当前指向
	BYTE* m_lpBufMax;  //终止指向
	BYTE* m_lpBufStart;  //开始指向
	….
}
CFile file;
file.Open( "E:/MFC/Day07/serial.txt", CFile::modeCreate | CFile::modeWrite );
CArchive ar(&file, CArchive::store, 4096) === CArchive::CArchive(&file,0, 4096)
{
  m_nMode = CArchive::store; // 0
  m_pFile = &file;//“E:/....serial.txt”
  m_nBufSize = 4096;
  m_lpBufStart = new BYTE[m_nBufSize];
  m_lpBufMax = m_lpBufStart + 4096;
  m_lpBufCur =  m_lpBufStart;
}

long age = 18;
ar << age === CArchive::operator<<(age)//函数内部this为&ar
{
  if (m_lpBufCur + sizeof(LONG) > m_lpBufMax)
  {
    Flush();
  }
  *m_lpBufCur = age;
  m_lpBufCur += sizeof(LONG);
}

float score = 88.5;
ar << score === CArchive::operator<<(score)//函数内部this为&ar
{
  if (m_lpBufCur + sizeof(float) > m_lpBufMax)
  {
    Flush();
  }
  *m_lpBufCur = score;//88.5
  m_lpBufCur += sizeof(float);
}

CString name = "zhangsan";
ar << name === CArchive::operator<<(name)//函数内部this为&ar
{
  AfxWriteStringLength(ar, 8 )
  {
    ar<<(unsigned char)nLength;//8
  }
  Write(name, 8)//函数内部this为&ar
  {
    memcpy_s(m_lpBufCur, (size_t)(m_lpBufMax - m_lpBufCur), name, 8);
    m_lpBufCur += 8;
  }
}

ar.Close( )//函数内部this为&ar
{
  Flush()//函数内部this为&ar
  {
    &file->Write(m_lpBufStart, ULONG(m_lpBufCur - m_lpBufStart));
    m_lpBufCur = m_lpBufStart;//重置当前指向
  }
}

              m_lpBufCur
 18 88.5 8 zhangsan|
|--------------------------------------------------------------------|
|                                                                    |
m_lpBufStart                                                       m_lpBufMax

反序列化:

MFC 学习笔记

序列化类对象:

就是序列化类对象的各个成员变量

序列化类对象的使用:

MFC 学习笔记

伪代码:

CFile file;
file.Open("E:/MFC/Day08/serial.txt", CFile::modeCreate|CFile::modeWrite);
CArchive ar(&file, CArchive::store, 4096);//归档类对象,维护缓冲区。
CMyDoc data(18, 88.5, "zhangsan");
ar << &data === operator<<(ar, const &data)
{
  ar.WriteObject(&data)//函数内部this为&ar
  {
    CRuntimeClass* pClassRef = &data->GetRuntimeClass();//文档类静态变量
    WriteClass(pClassRef);//将类的相关信息(类名/类大小/类版本)存入ar维护的buff中
    (&data)->Serialize(ar)//函数内部this为&data
    {
      ar << this->m_age << this->m_score << this->m_name; //序列化基本类型变量
    }
  }
}

CFile file;
file.Open( "E:/MFC/day08/serial.txt", CFile::modeRead );
CArchive ar( &file, CArchive::load, 4096 );//维护一个buff,大小4096字节
CMyDoc* pdata = NULL;//????????????
ar >> pdata === operator>>(ar, pdata)
{
  pdata = ar.ReadObject(RUNTIME_CLASS(CMyDoc))//函数内部this为&ar
  {
    CRuntimeClass* pClassRef = ReadClass(RUNTIME_CLASS(CMyDoc),...);
           //从文件读取 类的相关信息,和 RUNTIME_CLASS(CMyDoc)中信息进行比对,
           //如果相同返回RUNTIME_CLASS(CMyDoc),如果不同返回NULL
    CObject*pOb = RUNTIME_CLASS(CMyDoc)->CreateObject();
           //动态创建CMyDoc类的对象,并返回对象地址
    pOb->Serialize(ar)//函数内部this为刚刚创建的CMyDoc类对象(pOb)
    {
      ar >> m_age >> m_score >> m_name;//反序列化基本类型变量
    }
    return pOb;
  }
}

代码:

#include <afxwin.h>
#include <iostream>
using namespace std;

class CMyDoc : public CDocument{
//	DECLARE_SERIAL( CMyDoc )
	_DECLARE_DYNCREATE(CMyDoc) //动态创建机制的声明宏
	AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, CMyDoc* &pOb);//操作符重载函数
public:
	CMyDoc(int age=0, float score=0.0, CString name=""):m_age(age),m_score(score),m_name(name){}
	int m_age;
	float m_score;
	CString m_name;
	virtual void Serialize( CArchive& ar );
};
IMPLEMENT_SERIAL( CMyDoc, CDocument, 1 )
/*
动态创建机制实现宏站出来的东西
CArchive& AFXAPI operator>>(CArchive& ar, CMyDoc* &pOb)
{
	pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(CMyDoc));
			return ar;
}
*/
void CMyDoc::Serialize( CArchive& ar ){
	if( ar.IsStoring() ){
 		ar << this->m_age << this->m_score << this->m_name; //序列化基本类型变量
	}else{
		ar >> m_age >> m_score >> m_name;//反序列化基本类型变量
	}
}
void Store( ){//序列化(存储、写)数据
	CFile file;
	file.Open("E:/MFC/Day08/serial.txt", CFile::modeCreate|CFile::modeWrite);
	CArchive ar(&file, CArchive::store, 4096);//归档类对象,维护缓冲区。
	CMyDoc data(18, 88.5, "zhangsan");
	ar << &data; //序列化对象,就是将对象的各个成员变量序列化。
	ar.Close( );
	file.Close( );
}
void Load( ){//反序列化(加载/读)
	CFile file;
	file.Open( "E:/MFC/day08/serial.txt", CFile::modeRead );
	CArchive ar( &file, CArchive::load, 4096 );//维护一个buff,大小4096字节
	CMyDoc* pdata = NULL;
	ar >> pdata;
	ar.Close( );
	file.Close( );
	cout << pdata->m_age << ' ' << pdata->m_score << ' ' << pdata->m_name << endl;
}
int main(){
	Store( );
	Load( );
	return 0;
}

八.对话框机制

win32创建无模式对话框:
#include <windows.h>
#include "resource.h"
HINSTANCE g_hInstance = 0;
INT CALLBACK DlgProc( HWND hwndlg, UINT msgID, WPARAM wParam, LPARAM lParam ){
	switch( msgID ){
	case WM_DESTROY:
		MessageBox( NULL, "我要死了", "Infor", MB_OK );
		break;
	case WM_SYSCOMMAND:
		if( wParam == SC_CLOSE ){
			HWND hWnd = GetParent( hwndlg );
			EnableWindow(  hWnd ,TRUE );
			DestroyWindow( hwndlg );//销毁无模式对话框, 切忌不能EndDialog
//			EndDialog( hwndlg, 1001 );//只能隐藏无模式对话框, 可以销毁模式对话框
		}
		break;
	}
	return FALSE;//对话框的消息交给真正对话框窗口处理函数处理。
}
void OnNoModel( HWND hWnd ){
	EnableWindow( hWnd, FALSE );
//	HWND hDlg = CreateDialog( g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DlgProc );//直接创建

	HRSRC hRs = FindResource( g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG );
	HGLOBAL hGl = LoadResource( g_hInstance, hRs );
	LPCDLGTEMPLATE pTemplate = (LPCDLGTEMPLATE)LockResource( hGl );
	HWND hDlg = CreateDialogIndirect( g_hInstance, pTemplate, hWnd, DlgProc );

	ShowWindow( hDlg, SW_SHOW );
}
void OnCommand( HWND hWnd, WPARAM wParam ){
	switch(LOWORD(wParam)){
	case ID_NOMODEL:
		OnNoModel( hWnd );
		break;
	}
}
//窗口处理函数( 自定义,处理消息)
LRESULT CALLBACK Wnd

标签:

留言评论

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~