INFO: MFC 3.x转换为4.0的常见问题
发表于:2007-07-01来源:作者:点击数:
标签:
本文适用于: 包含于: - Microsoft Visual C++, 32-bit Edition, versions 4.0, 4.1, 4.2, 5.0 的微软基本类库(Microsoft Foundation Classes,MFC)。 概述: 本文列举了当你想把用MFC 3.x(这个MFC包含在Visual C++ 2.x中)编写的应用程序port为利用MFC 4
本文适用于:
包含于: - Microsoft Visual C++, 32-bit Edition, versions 4.0, 4.1, 4.2, 5.0 的微软基本类库(Microsoft Foundation Classes,MFC)。
概述:
本文列举了当你想把用MFC 3.x(这个MFC包含在Visual C++ 2.x中)编写的应用程序port为利用MFC 4.0(这个MFC包含在Visual C++ 4.0)工作时,最常遇到的一些
bug问题,和其他问题。
一般问题
1.MFC不再预先注册Window 类。
在4.0以前的版本中,MFC预先注册了四个窗口类(WNDCLASS),正如MFC Technical Note number 1中所说明的那样。这些窗口类是AfxWnd, AfxFrameOrView, AfxMDIFrame,和AfxControlBar。大多数防止产生一个应用程序的多个实例的代码(如ONETIME样本)都依赖于这些类。现在,在4.0版本中,在创建相应类型的窗口之前,这些类是不会被注册的。如果MFC追踪功能被打开,GetLastError会将值0x57F (ERROR_WNDCLASS_DOES_NOT_EXIST)返回到调试输出窗口。基于一个自定义WNDCLASS(填满来自MFC窗口类的信息)的窗口可能会不能显示和发送窗口创建失败的消息。
从4.0版本开始,当用RegisterClass 或AfxRegisterClass注册窗口类时,你需要提供所有必要的信息。不要靠::GetClassInfo去找回MFC窗口类的类值。
如果要知道更多的信息,请看MFC Technical Note 1和下列Microsoft Knowledge Base中的文章。
ARTICLE-ID: Q140596
TITLE: MFC 4.0 No Longer Pre-Registers Window Classes
ARTICLE-ID: Q141752
TITLE: SAMPLE: Limiting 32-bit Applications to a Single Instance
2.BUG: CFormView上的第一个控件,在OnInitialUpdate执行之前获得OnSetFocus。
如果在OnSetFocus中有涉及到直到调用基本类OnInitDialog 时才被子类化的CWnd对象的代码时,就会发生问题。当任何其他句柄作为获得焦点的控件结果被调用时,也会发生这一问题。例如,当单选按钮获得焦点时,会产生一个BN_CLIKED。如果想得到其他信息和工作区,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q142274
TITLE: FIX: Assertion Failure When Handling xN_SETFOCUS in
CFormView
3.CWinApp::m_templateList不在存在了:
CWinApp 的m_templateList成员变量在4.0版本以前的MFC中并没有说明,但却经常使用,被称为porting issue。微软建议使用GetFirstDocTemplatePosition()和GetNextDocTemplate()成员函数访问应用程序的模板。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q106455
TITLE: How to A
cquire a List of All CDocument Objects
4.BUG:CString +=操作符可能被空字符串中断。
导致这一bug的特定事件序列是复杂的。在MFC源代码中有一个bug,当+=操作符使用一个空字符串时,它不能作出正确地处理。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q142385
TITLE: FIX: Using CString::operator+= May Cause an A
clearcase/" target="_blank" >ccess Violation
5.BUG:当滚动条被编程滚动时,WM_xSCROLL 消息的OnWndMsg事件中断。
在MFC 4.0中加入了新的代码,用于将完整的32位地址(如果有)传送到OnxScroll句柄,因为WM_xSCROLL消息只能打包16位的地址信息。不幸的是,不论什么时候只要应用程序用SendMessage向自己发送一个WM_xSCROLL消息来编程滚动滚动条,新加入的代码就会中断。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q147684
TITLE: FIX: Sending WM_xSCROLL Message Causes Invalid ASSERT
6.BUG:现在OnInitMenuPopup在返回前删除菜单临时 map。
在4.0版的MFC中,在CWnd::OnInitMenuPopup中加入了对AfxLockTempMaps和AfxUnlockTempMaps的调用。当调用AfxUnlockTempMaps时,MFC的临时对象映射引用计数器将变为零,使得所有的临时MFC对象都被删除。当对OnInitMenuPopup的调用返回时,被传送到OnInitMenuPopup 的CMenu指针(这是一个临时指针)将是无效的。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q141532
TITLE: FIX: OnInitMenuPopup Deletes Temporary Objects
7.文档化的CRuntimeClass::m_pfnConstructObject现在是m_pfnCreateObject.
在4.0版以前的MFC中,m_pfnConstructObject是CRuntimeClass的一个文档化成员变量,但现在为了反映参数和返回值的改变,名字也相应作了更改。包含在Visual C++ 4.0中的文档并没有进行相应的更新,错误地引用了旧的函数名。
8.BUG:缺省的基于对话框的应用程序在Win32s中不工作。
当AppWizard产生一个基于对话框的应用程序时,它为主对话框使用一个DIALOGEX资源。但是,Win32s不支持DIALOGEX资源。结果,在Win32s中,对话框看起来有点不对。通过从对话框编辑器中去掉WS_EX_APPWINDOW类型和在.rc文件中将DIALOGEX声明改为DIALOG声明,可以对这个问题进行修正。
要想得到更多的信息,请看Visual C++ Readme文件和下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q138971
TITLE: BUG: Default Dialog-Based Application Doesn@#t Work in Win32s
CPropertySheet
现在,许多CPropertySheet的MFC实现已经被更改用来包装Windows Property Sheet通用控件。格式和尺寸上有一些改变,但更重要的是,如果代码使用了CPropertySheet的任何私有MFC实现,当类的大多数未文档化成员不在那时,代码就会中断。
9.CPropertySheet总是将它的字体变为缺省字体。
即使在资源编辑器中改变了属性页的字体,在运行时属性页也会以系统字体显示。如果有必要改变字体,在OnInitDialog中调用SetFont();然后使用合适的MoveWindow()调整页的大小并移动,调整页上所有控件的大小。还有,无论什么时候,当一个页被激活时,属性也就会恢复到原来的大小,因此,有必要调整页的大小以响应标签控件上的单击。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q142170
TITLE: SAMPLE: PRPFONT - How to Set CPropertySheet Fonts
10.调用一个基本类后应该修改OnInitDialog中的属性页。
在CPropertySheet::OnInitDialog期间,属性页的大小被调整,四个标准按钮(OK, Cancel, Apply, 和 Help)被隐藏在非模态属性页的底部。调用基本类以后在OnInitDialog中修改页的大小或定制用户化的四个属性页按钮是合适的。在以前版本的MFC中,在OnCreate中隐藏一些模态属性页显示的按钮是很平常的事。现在,通过在PROPSHEETHEADER 结构 CPropertySheet::m_psh中修改类型,可以很容易地去掉这些按钮。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q140585
TITLE: PRB: Resizing CPropertySheet in OnInitDialog Does Not Work
ARTICLE-ID: Q141039
TITLE: How to Hide the Apply Button in CPropertySheet
11.在Windows 95,CPropertySheet::DoModal()导致一个first chance异常。
因为属性页设置需要对话框资源中的类型,在Windows 95上将发生一个first chance异常,。操作系统需要对此进行控制,因此消息可能被忽略。如果你用一个try/catch(...)块把DoModal()调用包起来,企图自己解决异常,那么你会得到一个堆栈错误。
12.现在属性页有一个最小化的宽度。
CPropertySheet窗口的最小化宽度是四个按钮的大小,这四个按钮将会沿着一个模态属性页的底部向上显示。这一宽度甚至也应用于非模态属性页,在这种属性页中并不沿着底部显示四个按钮。
DLLs
13.在DLL启动期间,不能创建MFC线程。
尽管不是一个好办法,在以前版本的MFC中,在MFC DLL启动期间创建一个线程是可能的。这包括在DLLMain,DLL中的RawDllMain,InitInstance或任何被他们调用的函数中调用AfxBeginThread 或 CWinThread::CreateThread。由于MFC线程启动代码的同步及DLL RPOCESS ATTACH和DLL THREAD ATTACH期间在DllMain的阻塞,将不再允许这样做。 。当被应用程序调用的MFC 4.0 DLLS试图这样做时,将会被挂起。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q142243
TITLE: PRB: Cannot Create an MFC Thread During DLL Startup
14.使用共享库中MFC的正常DLLs,在输出函数中需要AFX_MODULE_STATE。
以前,USRDLL模型要求MFC静态地链接到DLL。现在从一个正常(Regular)DLL(_USRDLLs的新概念)动态链接到Mfc40.dll是可能的。值得注意的是,为了将一个_USRDLL转化为一个“使用共享库中MFC的正常DLL”,你要确保正确地管理模块状态信息。下面一行代码:
AFX_MANAGE_STATE(AfxGetStaticModuleState());
应该被加到任何从操作MFC对象的DLL输出的函数的开始部分。
如果没有适当地转变模块状态,就可能发生下列问题:
由于丢失资源,在一个DLL中创建对话框和窗口时失败。
调用错误应用程序对象,导致堆栈溢出或不可预知的结果。
不可知的运行时间类信息.
Bad window-to-MFC 对象处理映射连接.
要想得到更多的信息,请看MFC Technical Note 58 (TN058)和下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q140850
TITLE: How to Convert DLLTRACE to Use MFC in Shared Library
15.BUG:DoModal可能在MFC扩展DLLs中失败。
当MFC 4.0创建一个对话框时,它将当前实例的句柄传递给::CreateDialogIndirect Windows API椪飧?/FONT>API为DLL产生对话框而不是资源句柄。MFC已经从正确的扩展DLL装入了对话框的模板。但是,Windows将会在实例句柄指定的.exe 文件中寻找任何模板上指示的其他资源。如果他们在DLL中, Windows将找不到他们,对话框的创建将会失败。为解决这个问题,应该在任何对DoModal的调用之前,转换当前实例的句柄。其他资源包括对话框菜单,自定义控件,或对话框上的图标。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q147384
TITLE: FIX: Icons, Bitmaps, & Menus Not Displayed in an AFXDLL
Dialog
16.CStatusBar和CToolBar
像CPropertySheet一样,这些类现在也是用来包装Win32通用控件功能的。依赖或修改这些类的私有非文档实现的代码,在为MFC 4.0编译时,都可能中断。这两个通用控件比以前的缺省MFC实现支持更大范围的通用定制,而且它们不通过重要的覆盖MFC 源就能完成诸如创建调色板条或制作调整大小的工具条之类的工作。如果需要,这两个类的旧的作为COldToolBar和COldStatusBar类的实现仍然可用。这些实现可以在OLDBARS样本对象中找到。
17.CToolbar::SetSizes和按钮的尺寸设置
现在,工具条要求按钮的宽度至少比图像的尺寸大7个像素。Visual C++ 4.0中的文档没有做相应的更新,是错误的。MFC version 4.0用来检验SetSizes中正确参数的ASSERT也不是原来的6。还有关于工具条,按钮,和图像尺寸的一些其他限制,但是这些限制已经被MFC源中的ASSERT声明包括了并且从MFC 3.x以来一直没有改变。
要想得到更多的信息,请看下列Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q141444
TITLE: DOC: Incorrect Documentation for CToolBar::SetSizes()
CFileDialog
18.不需要替换MFC提供的CFileDialog 钩子(hook)过程。
MFC总是在CFileDialog对象构建期间为Open File Dialog指定自己的钩子过程(_AfxCommDlgProc),使它能将对话框的通知正确地发送到正确的句柄。对于MFC 4.x,这个hook过程用来将CFileDialog对象的子类到Open File Dialog窗口。如果钩子过程被替换了,这个子类过程不会发生,因此任何使用CFileDialog或嵌在它上面的控件变量(如果它是一个窗口)的企图都将失败。
19.CFileDialog总是浏览器对话框窗口的产物。
当你使用浏览器风格的CFileDialog(在Windows 95中,缺省情况就是这样)时,MFC采用用户化的浏览器模型。这意味着,对File对话框的定制改进,被包含在一个分离的模板上,这个模板被加到标准浏览器对话框周围。在MFC 4.0中,实际的CFileDialog窗口是主文件共用对话框的一个子对话框,即使你没有提供一个模板来用户化这个对话框。因此,如果你需要通过移动或隐藏控件来改变标准浏览器接口,就要在所有对Explorer控件的GetDlgItem()调用的前面加上GetParent()作为前缀。例如,表达式:
GetParent()->GetDlgItem(IDOK)
将返回一个指向浏览器对话框中Open/Save按钮的指针。然而,并不建议这样做,因为如果将来浏览器的设计改变了,那些依赖标准浏览器对话框控件详细资料的代码将会中断。
可以通过去掉OFN_E
XPLORER类型改变缺省设置。
要想得到更多的信息,请看下列Microsoft Knowledge Base文章:
ARTICLE-ID: Q131225
TITLE: PRB: CFileDialog::DoModal() Does Not Display FileOpen Dialog
19.CFileDialog的成员函数GetFileName和GetFileTitle互相颠倒了。
在MFC4.0中,对于文件C:\Article.txt:
CFileDialog::GetFileName返回Article.txt。
CFileDialog::GetFileTitle返回Article。
以前版本的MFC返回的正好相反。这些函数已经变为以和同名Win32 API函数相似的方法工作。然而,包含在Visual C++ 4.0中的文档并没有做相应的更新,是错误的。
要想得到更多的信息,请看Visual C++ Readme文件和下列Microsoft Knowledge Base中的文章。
ARTICLE-ID: Q142203
TITLE: DOCERR: GetFileTitle() & GetFileName() Docs Are Switched
MFC ODBC
20.BUG:带CLongBinary域的Dynasets抛出异常。
使用带CLongBinary-bound域的dynaset recordsets 的MFC ODBC应用程序能在Visual C++ 2.x中工作,但现在Visual C++ 4.0中,当打开recordset时,它抛出一个异常。该异常是从CRecordset::InitRecord抛出的.
要想得到更多的信息,请看下面Microsoft Knowledge Base中的文章:
ARTICLE-ID: Q141303
TITLE: FIX: Dynasets w/ CLongBinary Fields Throws Incorrect
Exception
MFC OLE
21.不再有Mfcans32.dll,因此MFC应用程序中的OLE函数需要Unicode变量。
在MFC 3.x中,当调用OLE接口时,使用一个特殊的DLL(Mfcans32.dll)在Unicode和MBCS之间自动转换。MFC 4.0并不使用这个DLL;而是直接和Unicode OLE接口对话。为了处理这一改变,现在MFC应用程序必须向OLE函数传送参数的正确类型棗不管是Unicode还是MBCS。MFC 4.0已经提供了许多宏,以使这一工作更容易。
为了得到更多的信息,请看MFC Technical Note 59。
参考文献
你可以在Visual C++ CD-ROM的如下目录中找到Visual C++ InfoView中的参考MFC Technical Notes:
Visual C++ Books
MFC 4.0
MFC Technical Notes
Visual C++ Readme可以在\Msdev\Vcread.wri文件中找到,或在以下的Visual C++ InfoView中:
README for Microsoft Visual C++ Version 4.0
Microsoft Foundation Classes (MFC)"
原文转自:http://www.ltesting.net