mfc执行一个是for循环需要多长时间

mfc执行一个是for循环需要多长时间,第1张

一个线程的执行周期一般在线程函数返回之后结束。

MFC程序的运行步骤(主要是初始化):

打开一个MFC APPWizard(exe)工程,跟踪其执行步骤,可以发现,是以下顺序:

1、CXXApp中的全局变量定义(在WinMain()函数之前定义的全局变量)

CXXApp theApp

2、调用CXXApp构造函数(当然,创建一个类,它首先会调用自己的构造函数,这时WinMain()还没有运行呢,呵呵奇怪吧?跟上面例子的变量a,其实是差不多的。)

CXXApp ::CXXApp(){}

3、进入Winmain函数(_tWinMain为宏,值为WinMain)(这个函数不是我们自己写的,而且是隐藏在一个比较隐蔽的文件里面,D:/Program Files/Microsoft Visual Studio/VC98/MFC/src/WINMAIN.CPP里面。)

_tWinMain(){} (如果你查看它的定义,#define _tWinMain WinMain,其实两者是一样的)

4、完成初始化工作:包括窗口类注册、窗口产生、显示和更新

pThread->InitInstance() (由于InitInstance是虚函数,所以这次调用的是派生类的InitInstance()函数,也就是你能在theApp里面看到的那一个函数)

对于MFC程序,MainFrame,View,ToolBar,Controlbar等都是窗口,所以下面的窗口注册与创建、显示等要反复调用多次,一次对应一个窗口。

(1) 注册窗口类:AfxEndDeferRegisterClass()(相当于SDK里面的RegisterClass()函数)

(2)创建窗口:CMainFrame::PreCreateWindow()//反复调用一次是给我们修改窗口属性的机会

CFrameWnd::Create()

(3)消息循环:PumpMessage()

补充1:

在MFC中,由于涉及到(窗口)类定义,所以定义全局变量的时候,需要进行更多的步骤。

全局变量涉及到类定义(类似于C中的类型定义)的话,那么需要遵循以下步骤(以MFC的窗口类为例,这是在SDK 里面经常用到的,有用api编写过函数的,应该都知道)

1、设计一个窗口类

2、注册窗口类

3、创建窗口

4、显示及更新窗口

5、消息循环

补充2:本课涉及到MFC函数的源文件位置

根目录

找到您安装VC98下MFC的位置,比如我的机子上为:D:/Program Files/Microsoft Visual Studio/VC98/MFC。下面提供的就是相对路径了。在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。

1,寻找WinMain人口:

路径:MFC|SRC|APPMODUL.CPP:

_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

{

// call shared/exported WinMain

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)

}

注意:(#define _tWinMainWinMain)

2,对于全局对象或全局变量来说,在程序运行即WINMAIN函数加载的时候,已经为全局对象或全局变量分配了内存和赋初值。(理解先运行构造函数CTEAPP:CTEAPP()再运行WinMain的关键)

所以:CTEApp theApp->CTEApp ::CTEApp(){}->_tWinMain(){}

说明:每一个MFC程序,有且只有一个从WinApp类派生的类(应用程序类),也只有一个从应用程序类所事例化的对象,表示应用程序本身。在WIN32程序当中,表示应用程序是通过WINMAIN入口函数来表示的(通过一个应用程序的一个事例号这一个标识来表示的)。在基于MFC应用程序中,是通过产生一个应用程序对象,用它来唯一的表示了应用程序。

3,通过构造应用程序对象过程中调用基类CWinApp的构造函数,在CWinApp的构造函数中对程序包括运行时一些初始化工作完成了。

CWinApp构造函数:MFC|SRC|APPCORE.CPP

CWinApp::CWinApp(LPCTSTR lpszAppName){...}//带参数,而CTEApp构造函数没有显式向父类传参,难道CWinApp()有默认参数 见下:

(在CWinApp类定义中, CWinApp(LPCTSTR lpszAppName = NULL))

注意:CWinApp()函数中:

pThreadState->m_pCurrentWinThread = this

pModuleState->m_pCurrentWinApp = this

(this指向的是派生类CTEApp对象,即theApp)

调试:CTEApp theApp( -> CTEApp ::CTEApp())-> CWinApp::CWinApp() (先调用基类初始化函数) -> CTEApp ::CTEApp() -> _tWinMain(){}(红色箭头表示依次运行的顺序)

4,_tWinMain函数中通过调用AfxWinMain()函数来完成它要完成的功能。(Afx*前缀代表这是应用程序框架函数,是一些全局函数,应用程序框架是一套辅助生成应用程序的框架模型,把一些类做一些有机的集成,我们可根据这些类函数来设计自己的应用程序)。

AfxWinMain()函数路径:MFC|SRC|WINMAIN.CPP:

在AfxWinMain()函数中:

CWinApp* pApp = AfxGetApp()

说明:pApp存储的是指向WinApp派生类对象(theApp)的指针。

//_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()

// { return afxCurrentWinApp}

调用pThread->InitInstance()

说明:pThread也指向theApp,由于基类中virtual BOOL InitApplication()定义为虚函数,所以调用pThread->InitInstance()时候,调用的是派生类CTEApp的InitInstance()函数。

nReturnCode = pThread->Run()

说明:pThread->Run()完成了消息循环。

5,注册窗口类:AfxEndDeferRegisterClass()

AfxEndDeferRegisterClass()函数所在文件:MFC|SRC|APPCORE.CPP

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

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

调试:CWinApp::CWinApp()->CTEApp theApp(-> CTEApp ::CTEApp())->CWinApp::CWinApp() -> CTEApp ::CTEApp() -> _tWinMain(){}//进入程序

-> AfxWinMain() -> pApp->InitApplication();-> pThread->InitInstance()//父类InitInstance虚函数->CTEApp::InitInstance()//子类实现函数-> AfxEndDeferRegisterClass(LONG fToRegister)//注册所选择的窗口类(出于文档管理,注册提前,正常的应在PreCreateWindow中进行注册)//之后进入创建窗口阶段(以下再不做调试)

6,PreCreateWindow()://主要是注册窗口类,提供这个函数主要是允许程序对窗口的参数进行多次的修改,而且这个函数也是反复调用的。

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs)

{

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE

return TRUE

}

说明:

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

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT&cs)

{

if (cs.lpszClass == NULL)

{

VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG))

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

cs.lpszClass = _afxWndFrameOrView // COLOR_WINDOW background

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

}

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

cs.style |= FWS_PREFIXTITLE

if (afxData.bWin4)

cs.dwExStyle |= WS_EX_CLIENTEDGE

return TRUE

}

其中:

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

#define VERIFY(f) ASSERT(f)

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

define AFX_WNDFRAMEORVIEW_REG 0x00008

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

//#define AFX_WNDFRAMEORVIEW AFX_WNDCLASS("FrameOrView")

7,创建窗口:

Create()函数路径:MFC|SRC|WINFRM.CPP:

CFrameWnd::Create(...){

...

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

...

}

CWnd::CreateEx()函数路径:MFC|SRC|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

intcy

intcx

inty

intx

LONG style

LPCTSTRlpszName

LPCTSTRlpszClass

DWORD dwExStyle

} CREATESTRUCT

8,显示和更新窗口:

CTEApp类,TEApp.cpp中

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

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

说明:调用的顺序

class CTEApp : public CWinApp{...}

class CWinApp : public CWinThread{...}

class CWinThread : public CCmdTarget

{

...

public:

CWnd* m_pMainWnd

...

...

}

9,消息循环:

int AFXAPI AfxWinMain()

{ ...

// Perform specific initializations

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

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

nReturnCode = pThread->Run()

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

...

}

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

CWinThread::Run()方法路径:MFC|SRC|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 places the 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

}

9,文档与视结构:

可以认为View类窗口是CMainFram类窗口的子窗口。

DOCument类是文档类。

DOC-VIEW结构将数据本身与它的显示分离开。

文档类:数据的存储,加载

视类:数据的显示,修改

10,文档类,视类,框架类的有机结合:

在CTEApp类CTEApp::InitInstance()函数中通过文档模板将文档类,视类,框架类的有机组织一起。

...

CSingleDocTemplate* pDocTemplate

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CTEDoc),

RUNTIME_CLASS(CMainFrame),// main SDI frame window

RUNTIME_CLASS(CTEView))

AddDocTemplate(pDocTemplate)//增加到模板

哈,小伙子精神不错啊...

是这样的.....

MFC的基于于对话框的应用程序与文档的应用程序用的不是同一个run.

你上面的理解是文档类型的.

到于对话框,请看CTestApp::InitInstance()中的代码,其中有以下几句:

CTestDlg dlg

m_pMainWnd = &dlg

int nResponse = dlg.DoModal()

大致是这样吧.这个DoModal内部有为模态对话框重建一个消息循环,模态对话框用得就是这样消息循环.你可以去百度下大牛们对模态对话框消息循环的分析.

当对话框退出的时候,InitIntance总是会返回false,而这在winmain里的有大致这样的代码:

if(!initInstance())//函数不是这样直接写,但最终是调用这个函数

{

XXXXXXXXXX

goto failture

}

这个goto语句直接会将CWinApp::Run直接跳过.从而直接结束winmain.

明白?给点分吧,打字不容易啊,兄弟


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12021803.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存