命令消息处理顺序
一个框架可以有多个视图窗口,框架类对象保存活动视图窗口的地址
CWnd CFrameWnd CMyFrameWnd 类内类外都具备消息映射机制的声明宏和实现宏,宏展开后每个内都存在静态变量(两个成员,第一个成员指向父类静态变量,第二个成员指向相应数组的首地址)和静态数组
视图类 CView CMyView也具备消息映射机制
命令消息处理顺序:视图类-文档类-框架类-应用程序类
伪代码
文档类和视图类的关系
视图类成员函数:获取和视图类对象关联的文档类对象,调用GetDocument()
文档类成员函数:当文档类数据发生变化时,调用UpdateAllViews刷新和文档类对象相关联的视图类对象(视图窗口)
文档类管理数据,视图类显示数据
#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() {
//AfxMessageBox("文档类处理了WM_COMMAND消息");
this->str = "hello world";//接受到的数据
// this->UpdateAllViews(NULL);//刷新和此文档类对象关联的所有视图窗口
//this->m_viewList;
POSITION pos = this->GetFirstViewPosition();//得到m_viewList的迭代器,指向头节点的前一个位置 GetFirstXXXPosition
CView* pView =this->GetNextView(pos);
this->UpdateAllViews(pView);//刷新和此文档类对象关联的除了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();
};
BEGIN_MESSAGE_MAP(CMyView,CView)
// ON_COMMAND(ID_NEW,OnNew)
ON_WM_CREATE()
END_MESSAGE_MAP()
IMPLEMENT_DYNCREATE(CMyView,CView)//支持动态创建机制
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;//m_pDocument为保护成员
CMyDoc* pDoc = (CMyDoc*)this->GetDocument();//GetDocument公有成员函数
pDC->TextOutA(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;//不能返回父类
}
int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
return CFrameWnd::OnCreate(pcs);//动态创建视图类对象,并创建视图窗口
}
void CMyFrameWnd::OnPaint() {
PAINTSTRUCT ps = { 0 };
HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
::TextOut(hdc, 200, 200, "框架窗口客户区", 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;
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;