您的位置:首页 > 其它

第3课 mfc框架程序剖析

2011-10-22 15:01 369 查看
1. 在main或WinMain之前,全局变量已经被分配内存并初始化了。

2. 构造子类时会调用父类的构造函数,而如果父类的构造函数中有this指针,那么此指针指向的是子类对象而不是父类对象

3.在MFC中在WinMain之前有个theApp全局变量先被构造并被初始化,而由于子类构造函数执行前,其父类的构造函数先被执行,所以CTestApp的父类CWinAPP的构造函数先执行。产生了theApp对象后,在WinMain()中的指针*pThread和*pApp就有了内容。

4.MFC大致流程:

CTestApp theApp;//构造全局对象

WinMain()

{

AfxWinMain();//调用下面的函数

}

AfxWinMain()

{

pThread->Initinstance();//初始化工作和注册窗口类,窗口显示和更新

pThread->Run();//消息循环

}

而在BOOLCTestApp::InitInstance()中的代码

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CTestDoc),

RUNTIME_CLASS(CMainFrame), // main SDI frame window

RUNTIME_CLASS(CTestView));

AddDocTemplate(pDocTemplate);

完成了将这三个类关联起来的工作。

5,MFC中不需要设计窗口类,应为MFC已经帮我们设计好了,我们只要注册就好了

6,注册窗口类:AfxEndDeferRegisterClass();

AfxEndDeferRegisterClass()在WINCORE.CPP中实现:

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister){...}

说明:设计窗口类:在MFC中事先设计好了几种缺省的窗口类,根据不同的应用程序的选择,调用AfxEndDeferRegisterClass()函数注册所选择的窗口类。

调 试:CWinApp::CWinApp();->CTestApptheApp;(->CTestApp::CTestApp())->CWinApp::CWinApp()->CTestApp::CTestApp()->_tWinMain(){}//进入程序

->AfxWinMain();->pApp->InitApplication();->pThread->InitInstance()//父类InitInstance虚函数;

->CTestApp::InitInstance()//子类实现函数;

->AfxEndDeferRegisterClass(LONG fToRegister)//注册所选择的窗口类(出于文档管理,注册提前,正常的应在PreCreateWindow中进行注册)//之后进入创建窗口阶段(以下再不做调试)

7,CMainFrame的PreCreateWindow()://主要是注册窗口类,以及在创建窗口之前让用户有机会对style进行修改

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE;

return TRUE;

}

说明:

CFrameWnd::PreCreateWindow()函数所在文件:WINFRM.CPP

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)

{

if (cs.lpszClass == NULL)

{

VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

//判断AFX_WNDFRAMEORVIEW_REG型号窗口类是否注册,如果没有注册则注册

cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOWbackground

//把注册后的窗口类名赋给cs.lpszClass

}

if((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)

cs.style |= FWS_PREFIXTITLE;

if(afxData.bWin4)

cs.dwExStyle |= WS_EX_CLIENTEDGE;

returnTRUE;

}

其中:

virtual BOOL PreCreateWindow(CREATESTRUCT&cs);//PreCreateWindow()是个虚函数,如果子类有则调用子类的。

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

const TCHAR _afxWndFrameOrView[] = AFX_WNDFRAMEORVIEW;//WINCORE.CPP文件中,定义为全局数组。

//#define AFX_WNDFRAMEORVIEW AFX_WNDCLASS("FrameOrView")

实际上正常的流程应该是在PreCreateWindow注册窗口类的,但是在SDI程序中,为了便于文档管理,注册提前了

8,创建窗口:

这里只讲解了框架窗口的创建,它的Create()函数在WINFRM.CPP中:

CFrameWnd::Create(...){

...

CreateEx(...);//从父类继承来的,调用CWnd::CreateEx().

...

}

CWnd::CreateEx()函数在WINCORE.CPP中:

BOOL CWnd::CreateEx(...){

...

if (!PreCreateWindow(cs))//虚函数,如果子类有调用子类的。

{

PostNcDestroy();

return FALSE;

}

...

HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,

cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,

cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

...

}

说 明:CreateWindowEx()函数与CREATESTRUCT结构体参数的对应关系,使我们在创建窗口之前可以通过 PreCreateWindow(cs)修改cs结构体成员来修改所要的窗口外观。PreCreateWindow(cs))//是虚函数,如果子类有调用子类的。

HWND CreateWindowEx(

DWORD dwExStyle,

LPCTSTR lpClassName,

LPCTSTR lpWindowName,

DWORD dwStyle,

int x,

int y,

int nWidth,

int nHeight,

HWND hWndParent,

HMENU hMenu,

HINSTANCE hInstance,

LPVOID lpParam

);

typedef struct tagCREATESTRUCT { // cs

LPVOID lpCreateParams;

HINSTANCE hInstance;

HMENU hMenu;

HWND hwndParent;

int cy;

int cx;

int y;

int x;

LONG style;

LPCTSTR lpszName;

LPCTSTR lpszClass;

DWORD dwExStyle;

} CREATESTRUCT;

9,显示和更新窗口:

CTestApp类,TestApp.cpp中

m_pMainWnd->ShowWindow(SW_SHOW);//显示窗口,m_pMainWnd指向框架窗口

m_pMainWnd->UpdateWindow();//更新窗口

说明:

class CTestApp : public CWinApp{...}

class CWinApp : public CWinThread{...}

class CWinThread : public CCmdTarget

{

...

public:

CWnd* m_pMainWnd;

...

}

10,消息循环:

int AFXAPI AfxWinMain()

{ ...

// Perform specific initializations

if (!pThread->InitInstance()){...}

//完成窗口初始化工作,完成窗口的注册,完成窗口的创建,显示和更新。

nReturnCode = pThread->Run();

//继承基类Run()方法,调用CWinThread::Run()来完成消息循环

...

}

////////////////////////////////////////////////////////////////

CWinThread::Run()函数在THRDCORE.CPP中

int CWinThread::Run()

{ ...

// phase2: pump messages while available

do//消息循环

{

// pump message, but quit on WM_QUIT

if (!PumpMessage())//取消息并处理

return ExitInstance();

...

} while (::PeekMessage(&m_msgCur, NULL, NULL, NULL,PM_NOREMOVE));

...

}

说明:

BOOL PeekMessage(,,,,)函数说明

The PeekMessage function checks a thread message queue for a message and placesthe message (if any) in the specified structure.

If a message is available, the return value is nonzero.

If no messages are available, the return value is zero.

/////////////////////////////////////////////////////////////

BOOL CWinThread::PumpMessage()

{

...

if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))//取消息

{...}

...

// process this message

if (m_msgCur.message != WM_KICKIDLE &&!PreTranslateMessage(&m_msgCur))

{

::TranslateMessage(&m_msgCur);//进行消息(如键盘消息)转换

::DispatchMessage(&m_msgCur);//将消息路由给操作系统,由相应的消息响应函数来处理

}

return TRUE;

}

11.如何在单文档文件中显示一个CButton的对象?

在CMainFrame::OnCreate()中定义一个CButton的对象btn;然后调用btn.Create("维新",WS_DISABLED |WS_CHILD | WS_VISIBLE | BS_AUTO3STATE,

CRect(0,0,300,100),/*GetParent(),*/this,123);

注意点:

(1).此处btn不能是局部变量,否则它的生命周期太短,将不能显示。

(2).在create函数的第二个参数中加入WS_VISIBLE 参数才行。否则必须调用ShowWindow

也可以在view的OnCreate消息响应函数中加入

(3).CButton类的定义头文件在afxwin.h中,而stdafx.h包含了afxwin.h,所以可以直接使用。因为MFC中的每一个类中都有#include"stdafx.h"的声明。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: