新建一个MFC单文档项目,后面选项都可以默认。
在(初识MFC,一个简单的窗口程序)中,了解到,窗口程序大致有七个步骤,那么这个自动生成的程序是否也是这样,此处剖析代码,寻找相同之处。
1.程序执行顺序,先到theApp全局对象定义处,然后是MFCApplicationApp(***App,你自己的项目名)构造函数处,然后才是WinMain函数。
对于MFC程序来说,通过产生一个应用程序类的对象来唯一标识应用程序的实例。每一个MFC程序有且仅有一个从应用程序类(CWinApp)派生的类,每一个MFC程序实例有且仅有一个该派生类的实例化对象,也就是theApp全局对象,该对象就表示了应用程序本身。
2.WinMain函数通过调用AfxWinMAin函数实现。其中有两个变量分别指向theApp,并且调用不同的函数,pApp->InitApplication();(主要实现MFC内部管理方面的工作,---- 我也不知道具体做了什么工作)pThread->InitInstance();(实现设计窗口类、注册、创建、显示、更新窗口)pThread->Run();(消息循环)
3.InitInstance()函数:参考下面函数中的注解,
以下是CMy0714MFCApplication1App类(CMy0714MFCApplication1.cpp)的部分代码,主要是InitInstance()函数。
1.MFC--microsoft foundation class,微软基础类库,C++面向对象的函数库,类的方式提供,帮助开发windows应用程序。
2.MFC中后缀名为ex的函数 均为扩展函数
3.CWinAPP应用程序类,负责管理应用程序的流程
CFrameWnd框架窗口类,负责管理框架窗口
CView视图窗口类,负责显示数据
CDocument文档类,负责管理数据
CDialog对话框窗口类
4.使用MFC编程的程序员刚开始都会提出这样一个问题:我的程序是从哪儿开始执行的?回答是:从WinMain()开始执行的。提出这样的问题是由于在他们所编写的MFC应用中看不到WinMain()函数。这个函数是隐藏在MFC框架中,MFC的设计者将它作得很通用(这主要得益于Window的消息驱动的编程机制,使得作一个通用的WinMain()很容易),因此在一般情况下,无需更改WinMain()的代码,MFC的设计者也不提倡程序员修改WinMain()的代码。在MFC中,实际实现WinMain()的代码是AfxWinMain()函数(根据其前缀Afx就知道这是一个全局的MFC函数)。 --------------- (深入浅出MFC)
一个Win32应用程序(或进程)是由一个或多个并发的线程组成的,其中第一个启动的线程称为主线程,在Window下,一般将线程分成两大类,界面线程和工作线程,工作线程就是一般的线程,它没有窗口,没有消息队列等,界面线程拥有一个或多个窗口,拥有一个消息队列和其他专属于界面线程的元素。在讨论AfxWinMain()之前,首先要简略提一下MFC中的两个重要的类,CWinThread和CWinApp,CWinThread是用来封装界面线程的类,CWinApp是从CWinThread派生而来的。在CWinThread中,有两个很重要的虚拟函数InitInstance()和ExitInistance(),MFC的程序员应该对这两个函数应该很熟悉。在CWinApp中,增加了另外一个虚拟函数InitApplication(),讨论AfxWinMain()的主要目的是看这些函数是如何被调用的。 --- (深入浅出MFC)
5.虚拟函数InitInstance()和ExitInistance() ------------->>>>>>>>> 应用程序启动时初始化及退出前清除变量等的地方。
6.框架应用程序将大部分时间花在CWinApp类的Run成员函数中。 初始化后, WinMain 调用 Run 以处理消息循环。
Run 遍历消息循环,并检查消息队列中的可用消息。 如果有可用的消息, Run 则调度该消息以进行操作。 如果没有可用的消息(通常为 true), Run 则调用 OnIdle 以执行你或框架可能需要完成的任何空闲时间处理。 如果没有要执行的消息和空闲处理,则应用程序将进行等待,直到发生某些情况。 当应用程序终止时, Run 调用 ExitInstance 。 OnIdle 成员函数中的数字显示了消息循环中的操作序列。 --------- (深入浅出MFC?应该是的吧,忘记了)
7.视类窗口始终覆盖在框架类窗口之上------->>>>所有操作,包括鼠标单击、鼠标移动、等操作只能由视类窗口捕获,所以框架类窗口收不到鼠标左键单机的消息
8.C++窗口类对象与窗口并不是一回事。它们之间的唯一关系是C++窗口类对象内部定义了一个变量成员,用于保存和这个C++窗口类对象相关的那个窗口的句柄。窗口销毁时,与之对应的C++窗口类对象是否销毁,要看其生命周期是否结束。但是当C++窗口类对象销毁时,与之相关的窗口会销毁。
9.很多窗口类的函数调用不需要传递窗口句柄,因为它们在内部维护了一个窗口句柄成员变量。
10.在窗口中显示按钮: 即框架上和视图上显示按钮。
在(初识MFC,一个简单的窗口程序)中,了解到,窗口程序大致有七个步骤,那么这个自动生成的程序是否也是这样,此处剖析代码,寻找相同之处。
1.程序执行顺序,先到theApp全局对象定义处,然后是MFCApplicationApp(***App,你自己的项目名)构造函数处,然后才是WinMain函数。
对于MFC程序来说,通过产生一个应用程序类的对象来唯一标识应用程序的实例。每一个MFC程序有且仅有一个从应用程序类(CWinApp)派生的类,每一个MFC程序实例有且仅有一个该派生类的实例化对象,也就是theApp全局对象,该对象就表示了应用程序本身。
2.WinMain函数通过调用AfxWinMAin函数实现。其中有两个变量分别指向theApp,并且调用不同的函数,pApp->InitApplication();(主要实现MFC内部管理方面的工作,---- 我也不知道具体做了什么工作)pThread->InitInstance();(实现设计窗口类、注册、创建、显示、更新窗口)pThread->Run();(消息循环)
3.InitInstance()函数:参考下面函数中的注解,
以下是CMy0714MFCApplication1App类(CMy0714MFCApplication1.cpp)的部分代码,主要是InitInstance()函数。
1 // 唯一的一个 CMy0714MFCApplication1App 对象 2 CMy0714MFCApplication1App theApp; 3 4 // CMy0714MFCApplication1App 初始化 5 6 BOOL CMy0714MFCApplication1App::InitInstance() // 实现到窗口的显示与更新 7 { 8 // 如果一个运行在 Windows XP 上的应用程序清单指定要 9 // 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式, 10 //则需要 InitCommonControlsEx()。 否则,将无法创建窗口。 11 INITCOMMONCONTROLSEX InitCtrls; 12 InitCtrls.dwSize = sizeof(InitCtrls); 13 // 将它设置为包括所有要在应用程序中使用的 14 // 公共控件类。 15 InitCtrls.dwICC = ICC_WIN95_CLASSES; 16 InitCommonControlsEx(&InitCtrls); 17 18 CWinAppEx::InitInstance(); 19 20 21 // 初始化 OLE 库 22 if (!AfxOleInit()) 23 { 24 AfxMessageBox(IDP_OLE_INIT_FAILED); 25 return FALSE; 26 } 27 28 AfxEnableControlContainer(); 29 30 EnableTaskbarInteraction(FALSE); 31 32 // 使用 RichEdit 控件需要 AfxInitRichEdit2() 33 // AfxInitRichEdit2(); 34 35 // 标准初始化 36 // 如果未使用这些功能并希望减小 37 // 最终可执行文件的大小,则应移除下列 38 // 不需要的特定初始化例程 39 // 更改用于存储设置的注册表项 40 // TODO: 应适当修改该字符串, 41 // 例如修改为公司或组织名 42 SetRegistryKey(_T("应用程序向导生成的本地应用程序")); 43 LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU) 44 45 46 InitContextMenuManager(); 47 48 InitKeyboardManager(); 49 50 InitTooltipManager(); 51 CMFCToolTipInfo ttParams; 52 ttParams.m_bVislManagerTheme = TRUE; 53 theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL, 54 RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams); 55 56 // 注册应用程序的文档模板。 文档模板 57 // 将用作文档、框架窗口和视图之间的连接 58 CSingleDocTemplate* pDocTemplate; // 注册与创建窗口应当是这一块,2022/07/14 59 pDocTemplate = new CSingleDocTemplate( // pDocTemplate把文档对象/框架对象/视类对象有机地组织在一起 60 IDR_MAINFRAME, 61 RUNTIME_CLASS(CMy0714MFCApplication1Doc), 62 RUNTIME_CLASS(CMainFrame), // 主 SDI 框架窗口 63 RUNTIME_CLASS(CMy0714MFCApplication1View)); 64 // 是在这里创建窗口的,RUNTIME_CLASS(CMainFrame), 就是创建主框架窗口,RUNTIME_CLASS(CTestView)创建视图子窗口。 65 // 这个RUNTIME_CLASS是宏实现, 其实就是动态创建运行类的实例,返回实例指针 66 if (!pDocTemplate) 67 return FALSE; 68 AddDocTemplate(pDocTemplate); 69 70 71 // 分析标准 shell 命令、DDE、打开文件操作的命令行 72 CCommandLineInfo cmdInfo; 73 ParseCommandLine(cmdInfo); 74 75 76 // 调度在命令行中指定的命令。 如果 77 // 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。 78 if (!ProcessShellCommand(cmdInfo)) 79 return FALSE; 80 81 // 唯一的一个窗口已初始化,因此显示它并对其进行更新 82 m_pMainWnd->ShowWindow(SW_SHOW); // 窗口显示与更新 83 m_pMainWnd->UpdateWindow(); // m_pMainWnd是CWnd类型的指针,指向CMainFrame对象的指针 84 return TRUE; 85 }
4.窗口过程函数的指定隐藏在AfxEndDeferRegisterClass函数之中。
最后,做一些相关的笔记整理:
1.MFC--microsoft foundation class,微软基础类库,C++面向对象的函数库,类的方式提供,帮助开发windows应用程序。
2.MFC中后缀名为ex的函数 均为扩展函数
3.CWinAPP应用程序类,负责管理应用程序的流程
CFrameWnd框架窗口类,负责管理框架窗口
CView视图窗口类,负责显示数据
CDocument文档类,负责管理数据
CDialog对话框窗口类
4.使用MFC编程的程序员刚开始都会提出这样一个问题:我的程序是从哪儿开始执行的?回答是:从WinMain()开始执行的。提出这样的问题是由于在他们所编写的MFC应用中看不到WinMain()函数。这个函数是隐藏在MFC框架中,MFC的设计者将它作得很通用(这主要得益于Window的消息驱动的编程机制,使得作一个通用的WinMain()很容易),因此在一般情况下,无需更改WinMain()的代码,MFC的设计者也不提倡程序员修改WinMain()的代码。在MFC中,实际实现WinMain()的代码是AfxWinMain()函数(根据其前缀Afx就知道这是一个全局的MFC函数)。 --------------- (深入浅出MFC)
一个Win32应用程序(或进程)是由一个或多个并发的线程组成的,其中第一个启动的线程称为主线程,在Window下,一般将线程分成两大类,界面线程和工作线程,工作线程就是一般的线程,它没有窗口,没有消息队列等,界面线程拥有一个或多个窗口,拥有一个消息队列和其他专属于界面线程的元素。在讨论AfxWinMain()之前,首先要简略提一下MFC中的两个重要的类,CWinThread和CWinApp,CWinThread是用来封装界面线程的类,CWinApp是从CWinThread派生而来的。在CWinThread中,有两个很重要的虚拟函数InitInstance()和ExitInistance(),MFC的程序员应该对这两个函数应该很熟悉。在CWinApp中,增加了另外一个虚拟函数InitApplication(),讨论AfxWinMain()的主要目的是看这些函数是如何被调用的。 --- (深入浅出MFC)
5.虚拟函数InitInstance()和ExitInistance() ------------->>>>>>>>> 应用程序启动时初始化及退出前清除变量等的地方。
6.框架应用程序将大部分时间花在CWinApp类的Run成员函数中。 初始化后, WinMain 调用 Run 以处理消息循环。
Run 遍历消息循环,并检查消息队列中的可用消息。 如果有可用的消息, Run 则调度该消息以进行操作。 如果没有可用的消息(通常为 true), Run 则调用 OnIdle 以执行你或框架可能需要完成的任何空闲时间处理。 如果没有要执行的消息和空闲处理,则应用程序将进行等待,直到发生某些情况。 当应用程序终止时, Run 调用 ExitInstance 。 OnIdle 成员函数中的数字显示了消息循环中的操作序列。 --------- (深入浅出MFC?应该是的吧,忘记了)
7.视类窗口始终覆盖在框架类窗口之上------->>>>所有操作,包括鼠标单击、鼠标移动、等操作只能由视类窗口捕获,所以框架类窗口收不到鼠标左键单机的消息
8.C++窗口类对象与窗口并不是一回事。它们之间的唯一关系是C++窗口类对象内部定义了一个变量成员,用于保存和这个C++窗口类对象相关的那个窗口的句柄。窗口销毁时,与之对应的C++窗口类对象是否销毁,要看其生命周期是否结束。但是当C++窗口类对象销毁时,与之相关的窗口会销毁。
9.很多窗口类的函数调用不需要传递窗口句柄,因为它们在内部维护了一个窗口句柄成员变量。
10.在窗口中显示按钮: 即框架上和视图上显示按钮。
2022-08-01(0714--拖延症晚期)
分类:
Windows开发 / MFC
, C/C++随笔
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)