DIY一个MFC程序

Posted 独饮月色的猫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DIY一个MFC程序相关的知识,希望对你有一定的参考价值。

前面剖析了MFC的基本框架:


1.通过定义一个CXXX(项目名)App类的全局对象theApp启动应用程序(在进入WinMain函数之前)

       具体就是在定义theApp对象时自动调用了CXXXApp类的构造函数,同时根据C++继承的原理,调用前会先调用其基类CWinApp构造函数。完成一些初始化工作,注意的是这里把theApp对象保存在了属于m_pCurrentWinApp中。


2.接着进入WinMain函数(实际上由AfxWinMain来实现),通过InitApplication,InitInstance、Run三个函数完成窗口类选择、注册并建立窗口,显示、更新窗口,建立消息循环

       具体就是在AfxWinMain中通过AfxGetApp,AfxGetThread函数把m_pCurrentWinApp中保存的theApp对象赋给pApp和pThread,然后pApp->InitApplication()完成MFC内部管理工作,pThread->InitInstance()完成注册窗口类,创建窗口等工作,pThread->Run()完成消息循环的建立。


3.接着进入消息循环虽然也设置了默认的窗口过程函数,但实际上是采用了消息映射机制来处理各种消息。当收到WM_QUIT消息时,退出消息循环,程序结束。


        


既然找到了这些封装在底层框架中的Windows API函数,以及对MFC框架有一些理解了,那么通过借助MFC类库的几个类自己应该也能在Win32项目中DIY一个MFC程序。 


首先,用VS2013建立一个名为MFCFrame的Win32空项目,在解决方案资源管理器视窗下在源文件中添加---新建项一个名为MFC的C++文件。

通过前面的剖析可以发现需要建立CWinApp的派生类然后定义这个派生类的对象theApp,还有就是CFrameWnd的派生类(在AfxWinMain中进行窗口相关操作必不可少,这个派生类中的m_pMainWnd用于保存CreateWindow返回的窗口句柄)。


在Win32项目下DIY一个MFC程序:

#include <afxwin.h>   //要用到MFC相关类库

class MyFrame : public CFrameWnd

//m_pMainWnd成员变量继承而来,无需定义
public:
	MyFrame()
	
		MessageBox(TEXT("进入MyFrame构造函数,执行窗口相关工作"), TEXT("MyMFC"), MB_OK);
		Create(NULL, TEXT("MyMFC"));	//调用CFrameWnd::Create,只填两个实参,剩下的用缺省值
	
;

class MyApp : public CWinApp

public:
	MyApp()
			
		MessageBox(0, TEXT("退出CWinApp构造函数,已保存theApp对象"), TEXT("MyMFC"), MB_OK);	
	
	BOOL InitInstance();    //MFC中InitIntance是虚函数,但实际调用的确实是CWinApp派生类的
	BOOL ExitInstance();
;
BOOL MyApp::InitInstance()

	MessageBox(0, TEXT("现在在WinMain中,执行InitInstance"), TEXT("MyMFC"), MB_OK);
	MyFrame* pFrame=NULL;
	pFrame = new MyFrame;       //自动调用了MyFrame的构造函数
	m_pMainWnd = pFrame;        //pFrame指针在InitInstance函数结束时析构,转存到m_pMainWnd这个MyFrame类的成员变量中
	pFrame->ShowWindow(SW_NORMAL);
	pFrame->UpdateWindow();
	return TRUE;
;
BOOL MyApp::ExitInstance()

	MessageBox(0, TEXT("窗口已销毁,执行ExitInstance结束程序"), TEXT("MyMFC"), MB_OK);
	return TRUE;
;
MyApp theApp;

编译错误了吧。。这里需要在这个项目的属性页里面--配置属性--常规--MFC的使用--在静态库中使用MFC

(或者选择在共享DLL中使用MFC。区别:使用动态链接时可能需要把一些库一起打包,以防止有的机子上没有该库文件或者版本不兼容而出现的库的依赖问题;使用静态链接,会把程序所需的库一起编译,生成的文件可能会大些,但是可执行文件移植时不会出错。


这样就能编译链接成功了~


代码中有很多注释加上前面我的笔记也有剖析,但还是解释一些难理解的地方:

1.第一个MessageBox函数为何只有三个参数(不需要窗口句柄作参数),还有TEXT函数是干什么用的?

首先解释TEXT,我使用的VS2013作IDE,选择的Unicode字符集,Unicode相比于ANSI的好处找本书都有。。这里就不说了。

#ifdef UNICODE

#define MessageBox MessageBoxW   //W表示Wide,宽字符(双字节)

......

而Char*非LPCTSTR类型,使用TEXT转换。

MyFrame类内用的MessageBox函数实际上非_stdcall MessageBox,而是CWnd::MessageBox,定义自然也就不同,CWnd类内有存放窗口句柄的成员变量自然就不需要提交窗口句柄这一参数了~


2.InitInstance是怎么调用的?

这里需要注意的是MFC中WinMain是由编译链接时才加入到程序中的,InitInstance正是在WinMain中被调用,可以找WinMain定义来看。


3.m_pMainWnd怎么来的?有什么用?

在CWinThread里定义:CWnd* m_pMainWnd; 然后继承下来给了CWinApp,还有MyApp。

作用见注释,由于这个变量是线程类的,线程未结束它的生命周期就没结束,没线程了,它就消失,窗体框架也结束。


4.ShowWindow和UpdateWindow为什么没有像Windows SDK编程那样把窗口句柄作参数?

有心的话会注意到这里是用pFrame指针指向的MyFrame类对象来调用这两个函数的,而MyFrame类继承了一个存放窗口句柄的窗口对象(成员变量),调用成员函数时使用本类的成员变量当然是合法的,无需作为参数传递进来。




实验:在MyApp::InitInstance函数中去掉p_MainWnd=pFrame;

结果:窗口当然还是可以生成,只不过在同时(未点击窗口右上方关闭来产生关闭事件,由操作系统包装此事件发送WM_QUIT消息)会出现标识ExitInstance函数用的小MessageBox窗口,就是说窗口刚刚产生完(InitInstance刚刚执行完),窗口对象的生命周期就坑爹的没了。。窗口对象一经析构,窗口自然销毁,执行ExitInstance结束程序。











以上是关于DIY一个MFC程序的主要内容,如果未能解决你的问题,请参考以下文章

MFC程序连接access数据库,目标机出现“未找到提供的程序,该程序未正确安装”

最简单DIY基于ESP32CAM的物联网相机系统⑥(用上位机VS2013 MFC实现WIFI图传)

Mysql数据库简介

解决应用程序无法正常启动0xc0150002问题

Xshell启动报错:由于找不到mfc110.dll,无法继续执行代码。重新安装程序可能会解决此问题

由于找不到 mfc110u.dll,无法继续执行代码。重新安装程序可能会解决此问题