自 Visual C++ 6.0 以來 ATL 7.0 和 MFC 7.0 中的重大更改
自 Visual C++ 6.0 以來 ATL 7.0 和 MFC 7.0 中的重大更改
自從 Visual C++ 6.0 以來,已經對 ATL 和 MFC 庫進行了許多改進。這些更改中某些可能會破壞現有的代碼,下面列舉了一些樣本:
- DLL 不相容性(ATL 和 MFC)
- ATL 模組類 (ATL)
- 字串轉換 (ATL)
- 從 BSTR 轉換到 CString(ATL 和 MFC)
- CException 現在是抽象基類 (MFC)
- CComEnumImpl::Skip 更改 (ATL)
- CWnd::DestroyWindow 斷言 (MFC)
- LNK2001 無法解析的外部符號錯誤 (MFC)
- Boolean 運算式現在類型為 bool,而非 BOOL (MFC)
- CColorPropPage 和 CFontPropPage 已被移除 (MFC)
DLL 不相容性
作為 Visual C++ .NET 2003 的一部分提供的 ATL 和 MFC DLL 檔案已分別被重新命名為 ATL71.dll 和 MFC71.dll。
Visual C++ .NET ATL 和 MFC 類與早期版本的相同類之間沒有二進位相容性,因此任何使用 mfc42.dll 產生的原始碼必須用 Visual Studio .NET 重建。應用程式使用的任何 DLL 或 LIB 檔案也必須用 Visual Studio .NET 重建。
例如,使用 Visual C++ 6.0 產生的、包含匯出函數(該函數將 CString 用作參數)的庫在與 Visual C++ .NET 項目連結時將產生無法解析的外部連結。
ATL 模組類
ATL 3.0 提供了 CComModule 類。在 ATL 7.1 中,以前由 CComModule 提供的功能由若干新類處理。有關更多資訊,請參見 ATL 模組類。
字串轉換
Visual C++ 6.0 中 ATL 3.0 和 ATL 3.0 以前的 ATL 版本中,使用 atlconv.h 中的宏的字串轉換始終是使用系統 (CP_ACP) 的 ANSI 字碼頁執行的。從 Visual C++ .NET 中的 ATL 7.0 開始,字串轉換將使用當前線程的預設 ANSI 字碼頁執行,除非定義了 _CONVERSION_DONT_USE_THREAD_LOCALE(此情況下,如以前一樣使用系統的 ANSI 字碼頁)。
請注意,字串轉換類(如 CW2AEX)使您得以將用於轉換的字碼頁傳遞給它們的建構函式。如果未指定字碼頁,這些類使用與宏相同的字碼頁。
有關更多資訊,請參見 ATL 和 MFC 字串轉換宏。
CException 現在是抽象基類
CException 在 Microsoft 基礎類庫中是所有異常的基類。因為 CException 現在是抽象基類,所以您不能直接建立 CException 對象;必須建立衍生類別的對象。如果您確實直接建立了對象,將會收到錯誤。有關更多資訊,請參見 CException。
從 BSTR 轉換到 CString
在 Visual C++ 6.0 中,使用下面的代碼是可以接受的:
BSTR bstr = SysAllocString(L"Hello");CString str = bstr;SysFreeString(bstr);
對於 Visual C++ .NET 下的新項目,這將在 ANSI 版本下導致下面的錯誤:
error C2440: 'initializing' : cannot convert from 'BSTR' to'ATL::CStringT<BaseType,StringTraits>'
現在有 CString 的 UNICODE 和 ANSI 版本(CStringW 和 CStringA)。若要標記任何由隱式轉換導致的不必要的系統開銷,採用反向類型(如帶 UNICODE 參數的 CStringA,或者帶 ANSI 參數的 CStringW)的建構函式現在在 stdafx.h 中被使用下面的項標記為顯式的:
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
若要避免此錯誤,請執行下列操作之一:
CComEnumImpl::Skip 更改
在 ATL 7.0 之前的版本中,CComEnumImpl::Skip 方法不能為輸入值 0 返回正確的錯誤碼。它還會以不一致的方式處理大的輸入值。這些行為在 ATL 7.0 中已被修複。
CWnd::DestroyWindow 斷言
當 CWnd::DestroyWindow 中顯示工具提示時,會發生斷言錯誤。因此,在 MFC 7.0 中,下列成員變數被從 AFX_THREAD_STATE 移到 AFX_MODULE_THREAD_STATE:
- CToolTipCtrl* m_pToolTip
- CWnd* m_pLastHit
- int m_nLastHit
- TOOLINFO m_lastInfo
- int m_nLastStatus
- CControlBar* m_pLastStatus
LNK2001 無法解析的外部符號錯誤
當調用採用 wchar_t 類型的靜態庫或 DLL 中的函數時(請注意,BSTR 和 LPWSTR 解析為 wchar_t*),可能會遇到“LNK2001 無法解析的外部符號錯誤”。
此錯誤由 /Zc:wchar_t 編譯器選項引起,預設情況下此選項在新的 MFC 項目中設定為開啟。此選項使編譯器將 wchar_t 當作本機類型。在 Visual C++ .NET 以前版本中,wchar_t 被當作 unsigned short。
如果主專案和庫不使用 /Zc:wchar_t 的相同設定,這將導致函數簽名不匹配。若要避免此問題,請使用 /Zc:wchar_t 編譯器選項重建該庫,或使用“屬性頁面”對話方塊中“語言”屬性頁面上的“將 wchar_t 視為內建類型”設定在主專案中將該選項關閉。
Boolean 運算式現在類型為 bool,而非 BOOL
請看下面的類:
class CMyClass : public CObject{BOOL bFlag;void Serialize (CArchive& ar)){if (ar.IsStoring())ar << (bFlag != FALSE); // breaking changeelsear >> bFlag;}};
在 Visual C++ .NET 之前,運算式 bFlag != FALSE
計算為 BOOL 並寫入四個位元組;在 Visual C++ .NET 中,它計算為 bool 並寫入一個位元組。這意味著用不同的編譯器版本編譯的程式可能會產生相互不相容的資料檔案。
若要避免該問題,請將運算式轉換為 BOOL:
ar << (BOOL)(bFlag != FALSE);
請參見
升級程式 | ATL 和 Visual C++ 版本號碼 | MFC 和 Visual C++ 版本號碼 | ATL 2.1 版的改動 | MFC 版本中的改動
CColorPropPage 和 CFontPropPage 已被移除
在以前版本的 MFC 中,ActiveX 控制項通過分別指定 GUID CLSID_CColorPropPage 或 CLSID_CFontPropPage 為顏色或字型屬性顯示內容頁。這些 GUID 指向類 CColorPropPage 和 CFontPropPage,現在不再實現它們。改用 GUID CLSID_StockColorPage 和 CLSID_StockFontPage。它們是通過 msstkprp.dll 實現的,因此您必須用應用程式重新發布該 DLL。
原文地址 http://msdn