mfc编程 孙鑫_孙鑫VC++视频教程笔记-(3)MFC程序框架的剖析 附1-SDI程序流程图-程序员宅基地

技术标签: mfc编程 孙鑫  

1,寻找WinMain人口:

在安装目录下找到MFC文件夹下的SRC文件夹,SRC下是MFC源代码。

路径:MFC|SRC|APPMODUL.CPP:

_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

{

// call shared/exported WinMain

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

注意:(#define _tWinMain WinMain)

2,对于全局对象或全局变量来说,在程序运行即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)

调试:CWinApp::CWinApp();->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;

int cy;

int cx;

int y;

int x;

LONG style;

LPCTSTR lpszName;

LPCTSTR lpszClass;

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;

}

10,文档与视结构:

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

DOCument类是文档类。

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

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

视类:数据的显示,修改

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

在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);//增加到模板...

----------------------------------------------------------------------------->

//AfxWinMain()函数在WINMAIN.CPP文件中,它主要调用以下函数

AfxWinInit();

pApp->InitApplication(); //内部初始化管理

pThread->InitInstance(); //调用子类中的InitInstance()

CTestApp::InitInstance();

┣━ProcessShellCommand(cmdInfo); //对命令行进行解释

┃ CTestDoc::CTestDoc(); //构造文档类对象

┃ CMainFrame::CMainFrame(); //构造框架窗口对象

┃ CFrameWnd::LoadFrame(); //WINFRM.CPP

┃ ┣━AfxEndDeferRegisterClass(); //WINCORE.CPP,注册窗口类

┃ ┃ AfxRegisterClass(); //WINCORE.CPP

┃ ┣━CMainFrame::PreCreateWindow();

┃ ┃ CFrameWnd::PreCreateWindow();

┃ ┃ AfxEndDeferRegisterClass();

┃ ┣━AfxRegisterClass();

┃ ┗━CFrameWnd::Create(); //创建CMainFrame窗口

┃ CWnd::CreateEx();

┃ CMainFrame::PreCreateWindow();

┃ CFrameWnd::PreCreateWindow();

┃ CTestView::CTestView(); //构造CTestView对象

┃ CWnd::CreateEx(); //创建CTestView窗口

┃ AfxEndDeferRegisterClass();

┃ AfxEndDeferRegisterClass();

┃ CWnd::CreateEx(); //创建CToolBar工具栏

┃ AfxEndDeferRegisterClass();

┃ CWnd::CreateEx(); //创建CStatusBar状态栏

┃ AfxEndDeferRegisterClass();

┃ AfxRegisterClass();

┃ CWnd::CreateEx(); //创建CDockBar

┃ AfxEndDeferRegisterClass();

┃ CWnd::CreateEx(); //创建CDockBar

┃ AfxEndDeferRegisterClass();

┃ CWnd::CreateEx(); //创建CDockBar

┃ AfxEndDeferRegisterClass();

┃ CWnd::CreateEx(); //创建CDockBar

┣━m_pMainWnd->ShowWindow(SW_SHOW); //显示窗口

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

nReturnCode = pThread->Run(); //进入消息循环

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39969257/article/details/113008959

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签