说明:
说明1:所有MFC框架下的代码在C:\ProgramFiles\Microsoft Visual Studio 9.0\VC\ce\atlmfc\src\mfc中
说明2:显示过程中的各个函数实际上是隐式过程中用到的函数的重写
说明3:窗口create函数完成后将产生WM_CREATE消息,该消息会触发oncreate函数的响应;类似的当客户区create函数完成后将产生WM_CREATE消息,该消息会触发oncreate函数的响应;这就是为什么对客户区初始化时要人为的产生WM_CREATE消息再对oncreate进行重写的原因了。
说明4:这里再说一下Cwingview类的ondraw函数了这个函数在窗口进行重绘时调用,那么什么时候进行重绘呢?
1) 文档类的数据发生变化
2) 其它类中认为的调用(view类的)invalidate函数或updateallviews函数
3) 更加全面的总结如下:
第一次创建一个窗口时
改变窗口的大小时
把窗口从另一个窗口背后移出时
窗口显示数据变化时,应用程序引发重绘操作
通过CWnd::Invalidate、CWnd::InvalidateRect或CWnd::InvalidateRgn函数把指定区域加到窗口的Update Region中。
窗口的Update Region不为空时,系统会自动产生WM_PAINT消息
说明5:窗口的绘制工作总是在WM_PAINT消息处理中进行的,WM_PAINT的产生会触发onpaint函数,而该函数会调用ondraw函数,故我们经常对ondraw进行编辑
说明6:当文档数据发生变化时,文档对象调用CDocument::UpdateAllView()通知所有视图,作为响应,视图的OnUpdate()成员被调用。所以,重载的OnUpdate()应该能够根据需要,将文档数据的变化反映在视图中。CView::OnUpdate()只是简单地使客户区无效,导致客户区重画。例如: void CView::OnUpdate(CView* pSender, LPARAM, CObject*) { ASSERT(pSender != this); UNUSED(pSender); // unused in release builds Invalidate(TRUE); }
说明7:从说明6中可以看出onupdate的实现是通过invalidate来实现的,故在不能自动重绘的地方我们可以人为的调用invalidate函数或updateallviews函数
说明8:在如OnDraw等函数中传递一个指向CDC 对象的指针
如OnDraw(CDC*pDC);
使用构造函数构建对象
一般不构造CDC对象
在CWnd类的OnPaint函数中,定义CPaintDC对象
CPaintDC dc(this);
在CWnd类的其它函数中,定义CClientDC和CWindowDC的对象
CClientDC dc(this);
CWindowDC dc(this);
说明9:
当窗口的某个区域需要重绘时激发窗口重绘消息WM_PAINT,相应消息处理 函数CWnd::OnPaint将被调用。CPaintDC一般只用于OnPaint函数中,在处理完窗口重绘后, CPaintDC对象的析构函数把WM_PAINT消息从消息队列中清除,避免不断地重绘操作。坐标原点(0,0)是客户区的左上角。
CClientDC用于特定窗口客户区(窗口中除边框、标题栏、菜单栏、状态栏外的中间部分)的输出,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC,不需要显式释放DC资源。一般用于响应非重绘消息(如键盘和鼠标消息)的绘图操作。坐标原点(0,0)是客户区的左上角。
CWindowDC在整个应用程序窗口上画图,而CClientDC和CPaintDC只能在客户区绘制图形;除非要自己绘制窗口边框和按钮,否则一般不用它。坐标原点(0,0)是屏幕的左上角。
说明:10:颜色填充工具
CPen类:GDI 画笔,用于画线。默认的画笔用于绘制与一个像素等宽的黑色实线。
CBrush类:GDI 画刷,用来填充一个封闭图形对象(如矩形、圆形)的内部区域,默认的画刷颜色是白色。
CFont类:GDI字体,用来绘制文本,可设置文字的大小、是否加粗、是否斜体、是否加下划线等。
CBitmap类:GDI 位图,用于填充区域。
CPalette类:GDI 调色板,包含系统可用的色彩信息,是应用程序和彩色输出设备环境(如显示器)的接口。
CRgn类:GDI 区域,用于设备环境(通常是窗口)内的区域操作,通常和CDC类中与裁剪(clipping)有关的成员函数配合使用。
备注:
备注1:这个全局对象一产生,便执行其构造函数,因为并没有定义CwingApp构造函数,所以即执行CWinApp类的构造函数,该函数定义于APPCORE.CPP中,CWinApp之中的成员变量将因为theApp这个全局对象的诞生而获得配置与初值。
备注2: // 注册应用程序的文档模板。文档模板
// 将用作文档、框架窗口和视图之间的连接
CSingleDocTemplate*pDocTemplate;
pDocTemplate = newCSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CeagleDoc),
RUNTIME_CLASS(CMainFrame), // 主SDI 框架窗口
RUNTIME_CLASS(CeagleView));//当一个文档对应多个视图时可再建立一个模板进行再绑定。
if(!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
备注3:MFC早已准备好并由链接器直接加到应用程序代码中了,原来她在APPMODUL.CPP里面,好,我们就认为当theApp配置完成后,程序就转到APPMODUL.CPP来了。那执行什么呢?看看下面从APPMODUL.CPP摘出来的代码:
extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCEhPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
// call shared/exportedWinMain
return AfxWinMain(hInstance,hPrevInstance, lpCmdLine, nCmdShow);
}
备注4:_tWinMain函数返回值是AfxWinMain函数的返回值,AfxWinMain函数定义于WINMAIN.CPP第21行,稍加整理,去芜存菁,就可以看到这个“程序进入点”主要做些什么事:
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCEhPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
int nReturnCode = -1;
CWinApp* pApp = AfxGetApp(); //获得cwingdoc的指针
AfxWinInit(hInstance,hPrevInstance, lpCmdLine, nCmdShow);
pApp->InitApplication();
pApp->InitInstance()
nReturnCode = pApp->Run();
AfxWinTerm();
return nReturnCode;
}
备注5:AfxGetApp()函数是取得CMyWinApp对象指针,故上面函数第6至8行相当于调用:
CMyWinApp::InitApplication();
CMyWinApp::InitInstance()
CMyWinApp::Run();
因而导致调用:
CWinApp::InitApplication(); //因为 CMyWinApp 并没有改写InitApplication
CMyWinApp::InitInstance() //因为 CMyWinApp 改写了InitInstance
CWinApp::Run(); //因为 CMyWinApp 并没有改写 Run
备注6:现在已经来到CWinApp::InitInstance了,该函数先new一个CMyFrameWnd对象,从而产生主窗口。在创建CMyFrameWnd对之前,要先执行构造函数CMyFrameWnd::CMyFrameWnd(),该函数用Create函数产生窗口:
CMyFrameWnd::CMyFrameWnd()
{
Create(NULL, "Hello MFC", WS_OVERLAPPEDWINDOW, rectDefault, NULL,"MainMenu");
}
其中Create是CFrameWnd的成员函数,它将产生一个窗口,用过SDK编程序的朋友都知道,要创建主窗口时要先注册一个窗口类,规定窗口的属性等,但,这里使用哪一个窗口类呢?Create函数第一个参数(其它参数请参考MSDN或《深出浅出MFC》详解)指定窗口类设为NULL又是什么意思啊?意思是要以MFC内建的空中类产生一个标准的外框窗口,但,我们的程序一般都没有注册任何窗口类呀!噢,Create函数在产生窗口之前会引发窗口类的注册操作。
让我们先挖出Create函数都做了些什么操作,Create函数定义于WINFRM.CPP的第538行(在此我就不把代码Copy过来了,你自己打开出来看吧),函数在562行调用CreateEx函数,由于CreateEx是CWnd的成员函数,而CFrameWnd是从CWnd继而来,故将调用CWnd::CreateEx。此函数定义于WINCORE.CPP第665行,下面是部分代码:
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTRlpszClassName,
Reference:
http://zhidao.baidu.com/question/469539277.html
http://wenku.baidu.com/view/0787810c763231126edb1148.html
http://blog.csdn.net/sgs1018/article/details/8902648
http://zhidao.baidu.com/question/319088486.html
http://wenku.baidu.com/view/d8b77bd4b9f3f90f76c61bbd.html
http://zhidao.baidu.com/question/246011777.html
http://blog.csdn.net/sgs1018/article/details/8902648