MFC程序解析以及使用cl.exe、link.exe编译连接Windows API和MFC程序


(如有错误,请大佬指出、更正)

一、实验目的

1.完成一个简单的MFC程序,通过此来了解MFC的对象类和程序执行流程。
2.运用VC6++或者Virtual Studio的cl.exe和link.exe来编译和连接Windows API程序和MFC程序。

二、实验配置

Virtual Studio 2015和Windows10操作系统

三、MFC程序创建和解析

(一)、创建MFC程序

打开VS2015,点击新建工程,然后如下图操作。
在这里插入图片描述
我选择了基于对话框的程序。
在这里插入图片描述
选择生成类(对本实验基本没影响)在这里插入图片描述
其余的都点击下一步。
创建完成后,不做任何修改,点击就可已运行。
在这里插入图片描述
VS提供了一个基于对话窗的MFC程序,比较方便。

(二)、分析MFC程序

MFC的所有类都继承自CObject,下图是MFC类结构层次。
在这里插入图片描述
MFC大致执行是按照:注册窗口-》产生窗口-》更新窗口-》消息循环。从注册窗口函数开始直至消息循环函数结束。MFC具体执行流程
主函数代码为:
其中,我添加了两个部分。它们分别来自appmodul.cpp和winmain.cpp。这两个文件在:安装目录\VC\atlmfc\src\mfc。
VS2015将这两个文件和其它文件封装在一起,对外部是隐藏的。在VS内执行程序时,会自动将这两个文件中的函数进行调用。
注:不加入这些函数,后面使用控制台编译链接MFC程序会出现找不到程序入口的错误

// MFC_test2.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "MFC_test2.h"
#include "MFC_test2Dlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//来自appmodul.cpp
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow);

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
#pragma warning(suppress: 4985)
{
	// call shared/exported WinMain
	return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}


//来自winmain.cpp
int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
{
	ASSERT(hPrevInstance == NULL);

	int nReturnCode = -1;
	CWinThread* pThread = AfxGetThread();
	CWinApp* pApp = AfxGetApp();

	// AFX internal initialization
	if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
		goto InitFailure;

	// App global initializations (rare)
	if (pApp != NULL && !pApp->InitApplication())
		goto InitFailure;

	// Perform specific initializations
	if (!pThread->InitInstance())
	{
		if (pThread->m_pMainWnd != NULL)
		{
			TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
			pThread->m_pMainWnd->DestroyWindow();
		}
		nReturnCode = pThread->ExitInstance();
		goto InitFailure;
	}
	nReturnCode = pThread->Run();

InitFailure:
#ifdef _DEBUG
	// Check for missing AfxLockTempMap calls
	if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
	{
		TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
			AfxGetModuleThreadState()->m_nTempMapLock);
	}
	AfxLockTempMaps();
	AfxUnlockTempMaps(-1);
#endif

	AfxWinTerm();
	return nReturnCode;
}


// CMFC_test2App,自己创建的工程cpp

BEGIN_MESSAGE_MAP(CMFC_test2App, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// CMFC_test2App 构造

CMFC_test2App::CMFC_test2App()
{
	// 支持重新启动管理器
	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;

	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 CMFC_test2App 对象

CMFC_test2App theApp;


// CMFC_test2App 初始化

BOOL CMFC_test2App::InitInstance()
{
	// 如果一个运行在 Windows XP 上的应用程序清单指定要
	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
	//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	// 将它设置为包括所有要在应用程序中使用的
	// 公共控件类。
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinApp::InitInstance();


	AfxEnableControlContainer();

	// 创建 shell 管理器,以防对话框包含
	// 任何 shell 树视图控件或 shell 列表视图控件。
	CShellManager *pShellManager = new CShellManager;

	// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题
	CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	CMFC_test2Dlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}
	else if (nResponse == -1)
	{
		TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");
		TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");
	}

	// 删除上面创建的 shell 管理器。
	if (pShellManager != NULL)
	{
		delete pShellManager;
	}

#ifndef _AFXDLL
	ControlBarCleanUp();
#endif

	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
	//  而不是启动应用程序的消息泵。
	return FALSE;
}

VS还有每个函数的使用解析。在ReadMe.txt文件里面。
下面展示部分内容。

================================================================================
    MICROSOFT 基础类库 : MFC_test2 项目概述
===============================================================================

应用程序向导已为您创建了此 MFC_test2 应用程序。此应用程序不仅演示 Microsoft 基础类的基本使用方法,还可作为您编写应用程序的起点。

本文件概要介绍组成 MFC_test2 应用程序的每个文件的内容。

MFC_test2.vcxproj
    这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。

MFC_test2.vcxproj.filters
    这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。

MFC_test2.h
    这是应用程序的主头文件。
    其中包括其他项目特定的标头(包括 Resource.h),并声明 CMFC_test2App 应用程序类。

四、使用cl.exe和link.exe

cl是编译工具,而link是链接工具。程序在编译完之后,需要链接各种文件才能形成最终的可执行文件。

(一)、Windows API

1.实验代码

参考这里(之前写过)

2.实验步骤

(1)环境配置

右键点击此电脑——》左键点击属性——》
在这里插入图片描述
——》
在这里插入图片描述
——》新建时,变量值用 ;(英文分号)隔开。
在这里插入图片描述
我的INCLUDE环境,每台电脑环境会不一样。

//这里包含了后面要用的环境
E:\VS2015\VC\include
E:\VS2015\VC\atlmfc\include
C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\shared
C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\ucrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\um
C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\winrt

LIB环境

//前3个Windows API需要
E:\VS2015\VC\lib
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.14393.0\um\x86
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.14393.0\ucrt\x86
//后3个MFC需要,编译或者链接API出错,可以先将后3个删除再试
E:\VS2015\VC\atlmfc\lib
E:\VS2015\VC\atlmfc\lib\amd64
E:\VS2015\VC\atlmfc\lib\arm

按下win+R——》输入cmd——》进入控制台输入cl。如下所示,则环境配置完成。在这里插入图片描述

(2)编译

用cl命令编译main.cpp在这里插入图片描述
会生成.obj文件在这里插入图片描述

(3)链接

使用link命令链接main.obj
为防止出现下面错误,需要添加另外的库user32.lib gdi32.lib在这里插入图片描述
成功后会出现main.exe在这里插入图片描述

(二)、MFC

1.实验代码

在上文分析MFC程序的主函数。

2.实验步骤

(1)环境配置

在上文Windows API环境配置

(2)编译

还是用cl命令分别编译MFC_test2.cpp和MFC_test2Dlg.cpp在这里插入图片描述
生成.obj文件
在这里插入图片描述

(3)链接

使用link命令链接MFC_test2.obj和MFC_test2Dlg在这里插入图片描述
生成MFC_test2.exe在这里插入图片描述

五、总结和部分错误解决

我尝试将appmodul.cpp和winmain.cpp编译后加入到原MFC_test2.cpp(代码中未加入appmodul.cpp和winmain.cpp的函数)中,但是会缺少文件。由此可见,VS是将一些文件一起封装的,运行出来的总的程序会比使用cl和link的大。
最容易出错的是环境配置部分。在这里插入图片描述
这种错误需要检查环境中的类型是否一致(或与计算机一致)。

如果是找不到或者打不开文件,就要在环境变量里面添加此文件。

  1. fatal error cxxx: xxxxxx.h:不包括路径
  2. fatal error LINKxxxx: 无法打开文件“xxxx.lib”

六、参考资料

1.如何使用cl.exe和linker.exe编译链接Windows API程序和MFC程序 (记得点赞)
2.完成一个MFC程序并进行分析;用VS命令行工具编译链接 (这个贼详细)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值