分享
 
 
 

献给广大需要在VC6中用MFC打开Access 2000数据库的朋友(Microsoft的解答)

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

Q I need to work with a Microsoft Access 2000 database and Data Access Objects (DAO) 3.6 from C++ with MFC. When I try to use CDaoRecordset, I get an "Unrecognized database format" error message. MFC probably uses DAO 3.5. How can I open files in MFC that were created with Microsoft Access 2000?

Ing. Jozef Sakalos

Slovakia

A This question is also discussed in the Knowledge Base article Q236991 (http://support.microsoft.com/support/kb/articles/ Q236/9/91.asp), but since so many people have asked, I'll cover it here. The problem is that MFC is using the wrong DAO DLL. When you call AfxDaoInit to initialize DAO for MFC, MFC first determines which version of the DAO engine to load.

// in daocore.cpp

void AFXAPI AfxDaoInit()

{

BYTE bUseDao = _AfxDetermineDaoVersion();

switch (bUseDao) {

case 35:

// Use DAO350.DLL

break;

case 30:

// Use DAO300.DLL

break;

case 36:

// Use DAO360.DLL

break;

}

}

_AfxDetermineDaoVersion is a macro that expands to 30, 35, or 36, depending on which version of MFC you have.

#if _MFC_VER >= 0x0601

#define _AfxDetermineDaoVersion() (36)

#else

#define _AfxDetermineDaoVersion() (35)

#endif

The previous code only shows how _AfxDetermineDaoVersion expands when you link with a static MFC (_AFXDLL not #defined). If you're linking with MFC as a DLL (_AFXDLL #defined), _AfxDetermineDaoVersion expands to a real inline function:

static inline BYTE _AfxDetermineDaoVersion()

{

BYTE bReturn = 35;

AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

if (pModuleState->m_dwVersion < 0x421)

bReturn = 30;

else if (pModuleState->m_dwVersion >= 0x0601)

bReturn = 36;

return bReturn;

}

The only difference between these cases is that in the first situation, the MFC version number is hardcoded as _MFC_ VER. For dynamically linked projects, MFC gets the version from your module's state. This is required because apps with different MFC versions can potentially call the same MFC42.DLL. Either way, MFC uses its own version number to determine which version of DAO to use. If the MFC version is 0x0601 (6.1) or higher, MFC uses DAO 3.6, the version used by Microsoft Access 2000.

So in order to gain access to Microsoft Access 2000 databases, you need MFC version 6.1. There's only one problem: there is no version 6.1 of MFC. The current version is 6.0!

// in afxver_.h

#define _MFC_VER 0x0600

The only way I know to get MFC 6.1 requires a time-travel device. So the question is: what's going on here? If there's no version 6.1, why does daocore.cpp have 0x0601 in it? The obvious way to support a different DAO version would have been to put the DAO version number as an argument to AfxDaoInit—after all, why should the DAO version be tied to the MFC version? But who thinks of version numbers the first time they write the code? But once a signature for AfxDaoInit was chosen, the MFC folks were forever constrained because they had to maintain strict binary backward compatibility with MFC42.DLL. Adding an argument to AfxDaoInit would change the function signature and hence the DLL entries. So the problem confronting the Redmondtonians was: how to tell MFC to use the new DAO, without introducing any new functions or function arguments? Using the MFC version number provided a convenient, if kludgy, way. (Of course, I'm only guessing that's what happened.)

So, to use the latest DAO engine, all you have to do is make MFC pretend it's the mysterious nonexistent version 6.1. If you're building with MFC as an MFC DLL, all you have to do is write:

AfxGetModuleState()->m_dwVersion = 0x0601;

AfxDaoInit();

That is, set the version number in your module state to 6.1 before you call AfxDaoInit. If you're the paranoid sort—and who isn't paranoid from time to time—you can save the original version and restore it after doing your business. A simple grep reveals, however, that _AfxDetermineDaoVersion is the only function in all of MFC that uses the mysterious 0x0601 version, so changing the version to 0x0601 should have no side effects.

If you're using the static MFC library, life is a little more difficult. The MSDN™ article mentioned earlier advises that you edit daocore.cpp and rebuild MFC. Yikes! That's a bit drastic for my taste. You should never rebuild MFC if you can avoid it. Better to confine whatever workarounds you need to your own project. Life is safer and more predictable if you make a hard and fast rule that the MFC libraries and code hierarchy are off limits. In fact, you should do what I do as soon as I install any new version of MFC or any SDK—set the read-only attribute on all the files.

But then how can you make MFC use DAO360.DLL in a static MFC build? Easy. Just copy the offending MFC source file (in this case, daocore.cpp) to your code directory, make the changes, and add it to your project. This is always a better way to modify MFC than munging MFC directly. When the linker needs a function or symbol from daocore.obj, it'll find the one in your modified version and, therefore, never need to load daocore.obj from MFC42.LIB. Of course, most MFC modules won't compile outside of their context; there are always some #include files from \mfc\src that you need. The easiest way to find them is just keep compiling and fixing until there are no more errors to fix. For daocore.cpp it turns out you need afximpl.h and daoimpl.h. afximpl.h is the MFC main internal include file, but in fact the only thing daocore.cpp needs from afximpl.h is _countof, so it's easier to copy the definition.

// Add these lines to the top of daocore.cpp

#include "daoimpl.h"

#define _countof(array) (sizeof(array)/sizeof(array[0]))

#undef _MFC_VER

#define _MFC_VER 0x0601

Once you add these lines to daocore.cpp and copy daoimpl.h to your project, daocore.cpp will compile with only a single warning, which you can safely ignore. And since you've redefined _MFC_VER to 0x0601, _AfxDetermineDaoVersion will now use DAO 3.6 (DAO360.DLL). Problem solved.

Just don't forget—this is only a stopgap measure! Once the Redmondtonians release the next MFC, you can return to life as usual. But you should remember this general technique: if you're absolutely, positively sure you need to modify MFC, don't modify the source directly. Instead, copy the module you want to change, plus any #include files and #defines it needs, and add it to your project. This method works whether you're linking with MFC as a static or dynamic library.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有