实验内容:
- 完成一个简单的MFC程序,并分析代码中对象类的关系以及程序的运行流程;
- 用命令行工具cl.exe,link.exe编译链接Windows API程序和MFC程序。
文章目录
一、MFC程序
MFC:将大多数Windows API和相应的数据进行封装;
这里用到了MFC的几个类:CDocument类(文档类),CWinApp类(应用程序类),CFrameWnd类(框架窗口类),CView类(视图窗口类),CDocTemplate类(文档模板类)。
1、VS2019建立MFC工程
(1)打开vs2019,选择创建新项目,搜索所需要模板,选择MFC应用,点击下一步;
(2)如果没有MFC,则是因为没有下载MFC组件,需要重新下载。
(3)选择“使用C++的桌面开发”,再把“适用于最新v142生成工具的C++ MFC(x86和x64)”勾上。
(4)重新安装后,则进行第一步,然后选择路径和项目名称。
(5)这里我选择的是单个文档,项目样式选择MFC standard,视觉样式和颜色选择Windows Native/Default,然后下一步,后面的一直默认即可。
(6)调试,效果如下
2、代码的设计及实现
(1)代码设计(简单文本与图形输出)
找到视图,修改Ondraw
void CM1View::OnDraw(CDC* pDC)
{
CM1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
pDC->TextOut(10, 120, _T("Hello World!"));
pDC->Rectangle(20, 20, 100, 100);
}
(2)效果图
二、用命令行工具cl.exe,link.exe编译链接
1、编译链接Windows API程序
(1)设置环境变量,找到cl.exe,link.exe的文件路径添加到系统变量Path中;
右键点击此电脑,点击属性,进入控制面板,选择高级系统设置,选择环境变量;
选择系统变量和用户变量的Path,选择编辑;
选择新建,把cl.exe,link.exe的文件路径添加进去,我的路径都是D:\vs2019\Community\VC\Tools\MSVC\14.27.29110\bin\Hostx86\x86;
接下来设置INCLUDE环境变量,在用户变量那里选择新建,变量名为INCLUDE,
设置LIB环境变量,在用户变量选择新建,变量名为LIB;
(2)用cl.exe编译
编译Win.cpp程序:
接下来就报了一个错:targetver.h(6): fatal error C1083: 无法打开包括文件: “SDKDDKVer.h”,(图我忘截了)后来我就直接在文件夹(Windows Kits)搜索这个头文件,显示如下:
我就把它这路径添加到LIB环境变量和INCLUDE环境变量中,结果还是那个错误,之后我就直接把所有需要用到的头文件和库都添加到里面,内容如下:
INCLUDE环境变量:
LIB环境变量:
之后再编译它,又有了另外的错误,然后我又换了其他的命令就成功了。
然后就会出现obj文件
(3)使用link.exe链接
如果直接使用link.exe Win.obj就会报如下错误:
需要添加静态库lib,所以我就直接把项目里的库都加进去了;
然后就成功了。
之后会生成一个.exe文件,点击运行它就可以,只是我这个没啥反应。
2、编译链接MFC程序
(1)设置环境变量
将“D:\vs2019\Community\VC\Tools\MSVC\14.27.29110\atlmfc\include”添加到INCLUDE环境变量中,“D:\vs2019\Community\VC\Tools\MSVC\14.27.29110\atlmfc\lib\x86”添加到LIB环境变量中(这是我的路径,你们的可能存的地方不一样),和上述步骤一样,我就不截图了。
(2)用cl.exe编译
(3)用link.exe链接
。。。然后就又报了一个错,是没有定义入口函数的问题,需要自己添加:
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);
}
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;
}
然后重新编译链接,就又报错,就很无奈。。。
然后我同学告诉我说是因为还有其他的cpp文件,我没有编译,然后我就将所有的cpp文件都编译了一遍
然后再链接,就成功啦!
三、总结
这次学习了MFC程序,了解了MFC执行的大概过程,以及各个类,函数的作用;同时学习了cl.exe,link.exe编译链接的过程。实验过程中也遇到了很多错,然后网上关于API以及MFC的命令行工具编译链接的资料又很少,就会遇到很多不可避免地错误,就很让人头疼。
四、参考
1、VS2017实现简单的MFC窗口程序及用cl.exe和link.exe编译链接
2、Visual C++程序设计——MFC整理笔记