CView类的使用

首先我们来写一个样例:

1.建一个win32简单应用程序,不要觉得这样就不能写出MFC程序,由于是不是MFC程序取决于调没调MFC函数。

2. 删除入口函数。仅仅留下#include "stdafx.h"

3.将stdafx.h中的头文件 <windows.h> 更改为 <afxwin.h>。

4.Project-->Settings菜单项中设置使用MFC库

5.编写代码

#include "stdafx.h"
#include "resource.h"
//视图类(创建方式与工具栏与工具栏步骤类似)
class CMyView:public CView
{
public:
	virtual void OnDraw( CDC* pDC );
	DECLARE_MESSAGE_MAP	()
protected:
	afx_msg void OnTest();

};
BEGIN_MESSAGE_MAP(CMyView,CView)
ON_COMMAND(ID_TEST,OnTest)
END_MESSAGE_MAP()

void CMyView::OnTest()
{
	MessageBox("CMView::OnTest");
}
void CMyView::OnDraw( CDC* pDC )
{
	pDC->TextOut(100,100,"Hello World!");
}
//框架窗体类
class CMainFrame :public CFrameWnd
{
public:
//	CMyView m_wndView;//视图类对象
	CMyView*m_pWndView;//视图类的指针
	DECLARE_MESSAGE_MAP()
protected:
	afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
	
};
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()

int CMainFrame::OnCreate( LPCREATESTRUCT lpCreateStruct ) 
{
	if(-1==CFrameWnd::OnCreate(lpCreateStruct))//父类的
	{
		return -1;
	}
	//创建视图窗体
	m_pWndView = new CMyView;//在堆中创建对象
	m_pWndView->Create(NULL,"MyView",WS_VISIBLE|WS_CHILD|WS_BORDER,CRect(0,0,100,100),
		this,AFX_IDW_PANE_FIRST);//AFX_IDW_PANE_FIRST可使边框和客户区重叠
	//将视图设置为活动视图
	//方式1:调用函数  
	//	SetActiveView(m_pWndView);
	//方式2:指针赋值
	m_pViewActive = m_pWndView;

	return 0;
}
//应用程序类
class CViewApp :public CWinApp
{
public:
	virtual BOOL InitInstance();


};
CViewApp theApp;//唯一的应用程序对象
BOOL CViewApp::InitInstance()
{
	//创建主要的主框架窗体
	CMainFrame *pFrame = new CMainFrame;
	//创建窗体,内部调用Create函数
	pFrame->LoadFrame(IDR_MENU1);//比Create函数用起来简单
	//将窗体设置为应用程序主窗体
	m_pMainWnd = pFrame;
	//显示和更新
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateData();

	return TRUE;
}
注意:

实例化CMyView对象前必须重写OnDraw()函数,由于OnDraw()是纯虚函数
        视图窗体的创建是在CMainFrame的 OnCreate()函数中调Create函数

思考&提升:

1. 为什么非要使用视图类的指针来?

 因为在CView::PostNcDestroy()函数中,调用了delete this;  所以,视图对象的创建放到堆中。即new 对象。

2. 创建视图时,如何视图铺满框架窗体的客户区?

创建时视图的ID填AFX_IDW_PANE_FIRST

3.  为什么要将视图对象设置为框架窗体的活动视图?

由于 处理菜单等命令消息的先后顺序: 活动视图->框架窗体->应用程序。

我们将对此进行验证:在消息提示框那行加断点,调试执行,我们通过调用堆栈得到下图调用信息



菜单消息都属于命令消息。所以我们找CFrameWnd 的 OnCmdMsg。双击进入CFrameWnd::OnCmdMsg()中得到

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
	AFX_CMDHANDLERINFO* pHandlerInfo)
{
	CPushRoutingFrame push(this);

	// pump through current view FIRST
	CView* pView = GetActiveView();
	if (pView != NULL && pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;

	// then pump through frame
	if (CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;

	// last but not least, pump through app
	CWinApp* pApp = AfxGetApp();
	if (pApp != NULL && pApp->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;

	return FALSE;
}

能够看出:处理菜单等命令消息的先后顺序: 活动视图->框架窗体->应用程序


4.OnPaintOnDraw之间的关系?

OnPaint调的是OnDraw。

由于OnDraw函数比OnPaint更简单。不用加入消息映射所以视图的信息显示,直接在OnDraw函数中。



5.为什么不用框架窗体的客户区显示数据。而非要用视图窗体显示?

框架窗体:就好像个容器,负责装各种各样的子窗体
视图窗体:是一种子窗体。父类是框架窗体,负责显示数据。这样做是由于当应用程序比較复杂时,我们希望一个类去做一件事


posted @ 2017-04-20 10:57  lytwajue  阅读(2998)  评论(0编辑  收藏  举报