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程序启动:
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方法。
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窗口和消息:
钩子简介:
#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窗口创建过程:
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(才是真正的窗口处理函数)
}
处理消息:
//以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虚函数的大前提下,仍然可以处理消息。
具体实现:
#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结构体的解释:
AFX_MSGMAP结构体的解释:
展开各部分作用介绍:
创建窗口的原理:
代码:
//以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消息:
消息的分类:
示例:
#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菜单:
菜单的使用:
方法一:
方法二:
#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消息类,其他类只有框架类处理一条路径)
框架类 ——> 应用程序处理类
设置菜单项状态:
设置右键菜单(上下文菜单):
代码:
#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工具栏以及两大机制:
工具栏:
相关类:
工具栏的使用:
代码:
#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;
运行时类信息机制:
在程序运行过程中可以获知对象的类的相关信息(例如:对象是否属于某个类)
使用:
代码:
#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的数据结构:
宏展开各部分:
执行过程:
关注这个宏 RUNTIME_CLASS(CDog)
伪代码:
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;
}
}
动态创建机制:
在不知道类名的情况下,将类的对象创建出来。
使用:
#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;
}
与运行时类信息机制区别:
代码:
RUNTIME_CLASS(CDog)->CreateObject()//函数内部this为本类(CDog)的静态变量地址(链表头
{
CObject* pObject = (*m_pfnCreateObject)() //CDog::CreateObject
{
return new CDog;
}
return pObject;
}
五.MFC视图和文档
视图窗口:
提供了一个用于显示数据的窗口
相关类:
CView及其子类,父类为CWnd类,封装了关于视图窗口的各种操作,以及和文档类的数据交互。
使用:
命令消息处理顺序:
视图类 -> 框架类 ->应用程序类
对象关系图:
代码:
#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;
文档类:
程序的创建过程:
代码:
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;//视图类对象用一个普通成员变量,保存文档类对象地址
}
}
对象关系图:
窗口切分:
代码:
#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;
命令消息处理顺序:
代码:
//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
}
}
}
文档类和视图类关系:
代码:
#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架构程序
单文档视图架构:
单文档视图架构特点:
只能管理一个文档(只有一个文档类对象)
单文档视图架构使用:
实现:
#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;
执行过程:
伪代码:
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);//创建框架窗口
//后续过程看前一天的伪代码
}
}
}
}
}
关于类向导的使用:
类向导可以帮助我们在已有的框架创建基础上再进一步帮我们生成代码。
选择: 位置 ->类向导
再这个里面可以选择要添加的项目,添加到的文件,添加的内容,框架会帮我们生成规范化的内容,我们只需要实现具体细节。
多文档视图架构:
特点:
可以管理多个文档 (可以有多个文档类对象)
多文档视图架构使用:
执行过程:
代码:
#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绘图:
绘图相关类:
伪代码:
绘图相关的
***********************************************
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
}
七、序列化机制:
文件序列化与反序列化:
文件操作相关类:
代码 :
#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;
}
序列化机制使用:
反序列化机制使用:
代码:
#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;
}
执行过程:
序列化过程:
伪代码:
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
反序列化:
序列化类对象:
就是序列化类对象的各个成员变量
序列化类对象的使用:
伪代码:
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
标签:
留言评论