非MFC工程中使用MFC库
需求说明
C++工程的类型有很多,从VS(或VC)可以看到常见的有:Win32 Console Application、MFC Application、Win32 Project等。在创建MFC工程时,通过IDE的向导会自动帮我们创建相应的类文件和包含必需的头文件,但有时候我们需要在非MFC工程中包含MFC的库。至于为什么会有这个需要,为何不在一开始就创建MFC工程呢?可能有两种原因:1.在MFC工程会产生很多向导生成的代码以及资源文件,如基于单文档的工程会有View,Doc等类,很多时候我们并不需要这些东西,只需要一个空工程就可以了。2.使用第三方框架创建的工程,我们很难更改它的工程属性(如用Firebreath开发浏览器插件,通过脚本文件firebreath会自动帮我们生成VS下的工程)。
常见问题
在非MFC工程中使用MFC的库就需要包含相应的头文件,经常会遇到下面这个问题:
1. fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]
2. fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h>
问题分析
对于第1个问题,很简单:
选中工程名右键属性(Project),在Properties\Configuration Properties\General\Use of MFC中选择Use MFC in a Shared DLL
出现上面第2个问题主要是因为包含头文件的顺序不对。为什么包含WINDOWS.H的时候会有顺序要求,网上有一段传播的非常广泛解释:
如果在MFC工程中#include <windows.h>,那么会有以下编译错误(因为afxwin.h文件中包含了afx.h,afx.h文件中包含了afxver_.h,afxver_.h中包含了afxv_w32.h,而afxv_w32.h中包含了windows.h,请看以下分析):
compile error:
c:\program files\microsoft visual studio\vc98\mfc\include\afxv_w32.h(14) :
fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h>
如果编译器在编译afxv_w32.h文件之前编译了windows.h文件,编译器会报上面的错误,因为在afxv_w32.h文件中有下面的一句预编译报警:
#ifdef _WINDOWS_
#error WINDOWS.H already included. MFC apps must not #include <windows.h>
#endif
问题在于为什么afxv_w32.h中要有这么一句预编译处理。看了afxv_w32.h和windows.h文件就有点明白了。
在afxv_w32.h中有下面的预编译语句:
... ...
#undef NOLOGERROR
#undef NOPROFILER
#undef NOMEMMGR
#undef NOLFILEIO
#undef NOOPENFILE
#undef NORESOURCE
#undef NOATOM
... ...
在afxv_w32.h中还有一句:
#include "windows.h"
而在windows.h文件中有下面的预编译语句:
... ...
#define NOATOM
#define NOGDI
#define NOGDICAPMASKS
#define NOMETAFILE
#define NOMINMAX
#define NOMSG
#define NOOPENFILE
... ...
注意到在windows.h的开头有防止windows.h被重复编译的预编译开关:
#ifndef _WINDOWS_
#define _WINDOWS_
这样问题就明白了,虽然我不知道微软为什么要这么做,但是我知道如果在afxv_w32.h没有那句预编译报警,那么如果在编译afxv_w32.h之前
编译了windows.h,那么在windows.h中#define的NOATOM等宏就会被#undef掉,可能会导致相应的错误发生。
猜想原因可能如上所述,我的解决方法是,将包含有#include “windows.h"的头文件放在所有包含的头文件的最后面,这样使得对afxv_w32文件
的编译处理发生在先,这样,由于在afxv_w32.h中已经包含了windows.h,那么宏_WINDOWS_将被定义,后继的#include "windows.h"语句将形同虚设,
上面的编译报警也不会发生了。我觉得这种处理要比将所有的#include "windows.h”语句删掉要好一点。
一句话,编译器必须在编译windows.h之前编译afxv_w32.h,因为我不是十分清除什么时候afxv_w32.h会被编译,所以我将可能包含有#include "windows.h"的头文件放在其他头文件之后#include。
参考解决方法
解决这个问题的总体思路是:把#include <afxwin.h>的包含语句把到最前面。
sunshine1314 的博文《非MFC工程使用MFC库时的问题及解决办法》给出了一序列的解决方案,大家可能参考一下,也许能解决你们的问题。但我当时通过这一系列方法还是没能解决我的问题。
我的解决方案
我的问题是:用Firebreath开发浏览器插件,通过fbgen.py和prep2010.cmd脚本帮我们生成了基于VS2010的工程(这个工程中没有stdaf.h),我们要在这个工程中获得MFC中的HDC以及使用MessageBox,于是就碰到了上面提到的问题。
解决方案:
手动添加stdafx.h和stdafx.cpp文件使用预编译机制,在stdafx.h的最前面包含<afxwin.h>。于是问题就变成了stdafx.h的原理和手动添加stdafx.h文件及相应配置。下面我们以Win32 Console Application工程的TextProject为例,演示一下这过程。
1.在VS2010中创建Win32 Console Application工程的TextProject,创建向导会自动生成的stdafx.h和stdafx.cpp,省去了手动添加的过程。如果你的工程没有这两个文件可以手动创建。
2.stdafx.h和stdafx.cpp这两个文件已创建并添加到工程,下面讲讲相关的配制。
2.1选中工程名,右键属性(Properties),在Precompiled Header/Precompiled Header中选择Use(/Yu),Precompiled Header File中填stdafx.h。设置工程编译时使用预编译头文件stdafx.h(在VS中文件名的大小写不敏感,即StdAfx.h和stdafx.h是等价的)。
2.2选中stdafx.cpp文件,右键属性(Properties),在Precompiled Header/Precompiled Header中选择Create(/Yc), Precompiled Header File中填stdafx.h。这样设置的作用是:每次编译stdafx.cpp文件时创建.pch文件(扩展名pch表示预编译头文件 )。
3.在stdafx.h的开发包含<afxwin.h>文件:
#include <afxwin.h>
4.这时在我们的main函数中写入下面这句话,就可以弹出一个消息框:
AfxMessageBox(L"非MFC工程使用MFC库", MB_OK, 0 );
Stdafx.h的原理
关于stdafx.h的原理请看下一篇文章《预编译头文件(stdafx.h)的原理》。
非MFC工程中使用MFC库的更多相关文章
- 在非ARC工程中使用ARC库
选中工程->TARGETS->相应的target然后选中右侧的“Build Phases”,向下就找到“Compile Sources”了.为对应的库文件添加:-fobjc-arc参数即可 ...
- 在VC++空工程中使用MFC类,采用Unicode字符集后,运行工程程序报错的解决方案
创建一个VC++空工程,将Project Properties->General->Use of MFC改为Use MFC in a Shared DLL 新建一个源文件,内容如下 #in ...
- VC++ MFC工程中中如何将一个工程的资源(如对话框)复制到另外一个工程
问题的提出:在工程1中用到的资源,在工程2中已有现成的.即工程1中要用到的对话框和工程2的完全相同,而工程2中对该对话框的布局已设计好.控件变量都绑定好了.但由于该对话框的控件特别多,如果在工程1中再 ...
- 关于如何在MFC工程中输入不同的数据进行调试
我们可以采用c++的文件输入输出来进行调试 这样就绕过了不能使用黑窗口输入数据就不能调试的思维定式 不是黑窗口的我们都可以考虑用文件流输入输出 或者用控件来输入? http://blog.csdn.n ...
- [Visual Studio] [Config] [Transformation] [SlowCheetah] 在非Web工程中使用Transformation
1. 为VS安装SlowCheetah插件 https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.Sl ...
- MFC的使用——在共享DLL中使用MFC、在静态库中使用MFC(转)
原文转自 https://blog.csdn.net/albertsh/article/details/52838419 1.使用标准Windows库 使用WINDOWS SDK API库,不使用MF ...
- 在WIn32程序中使用MFC的CInternetSession运行异常,主要是因为获取目前应用程序名出错的解决办法
转载:http://group.gimoo.net/review/22564 头文件#include <afxinet.h"> 在非MFC工程中使用CInternetSessio ...
- WIN32 DLL中使用MFC
最近用WIN32 DLL,为了方便要用到MFC的一些库,又不想转工程,就网上找了很多方法,发现没有详细的介绍,有的也行不通,现在成功在WIN32 DLL中使用了MFC,记录一下以防以后用到忘记 一.修 ...
- 在WIN32 DLL中使用MFC
最近用WIN32 DLL,为了方便要用到MFC的一些库,又不想转工程,就网上找了很多方法,发现没有详细的介绍,有的也行不通,现在成功在WIN32 DLL中使用了MFC,记录一下以防以后用到忘记 一.修 ...
随机推荐
- The Road to learn React书籍学习笔记(第一章)
react灵活的生态圈 Small Application Boilerplate: create-react-app Utility: JavaScript ES6 and beyond Styli ...
- 笔记-python-lib-requests常用类/方法/属性
笔记-python-lib-requests常用类/方法/属性 1. requests模块常用类/方法/属性 在使用中发现对requests模块不够熟悉,写了几个案例后重新整理了一下文档,罗 ...
- Echarts 背景渐变柱状图
var dom = document.getElementById("container"); var myChart1 = echarts.init(dom); var app ...
- [EXCEL]使用技巧随记
1.比对两列中是否有重复项(B列中是否和A列重复) =IF(COUNTIF(A:A,B1)=0,"不重复","重复") Excel中用vlookup函数来对比两 ...
- Win7更换锁屏和开机画面
技术交流群:233513714 每次开机被Windows千年不变的开机画面和锁屏画面丑到的小伙伴们可以看过来,通过简单的几步就可以改掉系统默认的开机画面. 1.首先Windows+r键输入regedi ...
- JAVA中使用AES加密解密
技术交流群: 233513714 /** * AES加密测试 * * @param str 加密参数 */ public void aesTest(String str) { log.info(&qu ...
- javascript实现在textarea光标位置插入文字并移动光标到文字末尾
1.背景:实现在textarea光标位置插入文字并移动光标到文字末尾 如果每次通过val("ss")赋值的形式插入文字到textarea中,会将上一次赋的值覆盖掉. 2.思路: & ...
- GCD那些事儿
GCD GCD,全名Grand Central Dispatch,中文名郭草地,是基于C语言的一套多线程开发API,一听名字就是个狠角色,也是目前苹果官方推荐的多线程开发方式.可以说是使用方便,又不失 ...
- 《Cracking the Coding Interview》——第5章:位操作——题目3
2014-03-19 05:57 题目:给定一个整数N,求出比N大,而且二进制表示中和N有相同个数的‘1’的最小的数,比如3是‘11’,接下来的5是‘101’,再接下来的6是‘110’. 解法:从低位 ...
- android什么时候会产生ANR
ANR: Application No Response 1.界面操作(按钮点击)等待时间超过5秒 2.HandleMessage 回调函数中执行超过10秒(进行长时间处理不放在主界面,放在另一个线程 ...