Share via


Änderungen in ATL und MFC: ATL 7.0 und MFC 7.0

Aktualisiert: November 2007

Hinweis   Möglicherweise sind einige der unter diesem Thema erwähnten Features in der aktuellen Version von Visual C++ noch nicht verfügbar.

Seit Visual C++ 6.0 wurden zahlreiche Verbesserungen in Bezug auf die ATL- und MFC-Bibiotheken implementiert. Durch einige dieser Änderungen kann vorhandener Code möglicherweise unterbrochen werden.

DLL-Imkompatibilitäten

Die im Lieferumfang von Visual C++ .NET 2002 enthaltenen DLL-Dateien ATL und MFC wurden in ATL70.dll bzw. MFC70.dll umbenannt.

Die ATL- und MFC-Klassen von Visual C++ .NET sind nicht binärkompatibel mit denselben Klassen aus früheren Versionen. Aus diesem Grund muss mit mfc42.dll erstellter Quellcode in Visual Studio .NET neu erstellt werden. Darüber hinaus müssen alle von Ihrer Anwendung verwendeten DLL- oder LIB-Dateien mit Visual Studio .NET neu erstellt werden.

Eine Bibliothek mit einer exportierten Funktion, die CString als Parameter aufnimmt und mit Visual C++ 6.0 erstellt wurde, ergibt während der Verknüpfung mit einem Visual C++ .NET-Projekt einen nicht aufgelösten externen Verweis.

ATL-Modulklassen

ATL 3.0 enthielt die CComModule-Klasse. In ATL 7.0 wird die Funktionalität der früheren CComModule-Klassen von mehreren neuen Klassen bereitgestellt. Weitere Informationen finden Sie unter ATL-Modulklassen.

Zeichenfolgenkonvertierungen

In ATL-Versionen bis und einschließlich ATL 3.0 (Visual C++ 6.0) wurden Zeichenfolgenkonvertierungen mittels der Makros in atlconv.h immer mithilfe der ANSI-Codepage des Systems (CP_ACP) durchgeführt. Ab ATL 7.0 in Visual C++ .NET werden Zeichenfolgenkonvertierungen mit der standardmäßigen ANSI-Codepage des aktuellen Threads durchgeführt. Dies gilt nicht, wenn _CONVERSION_DONT_USE_THREAD_LOCALE definiert ist. In diesem Fall wird, wie gewohnt, die ANSI-Codepage des Systems verwendet.

Beachten Sie, dass die Zeichenfolgenkonvertierungsklassen, wie CW2AEX, Ihnen die Möglichkeit bieten, eine Codepage zu übergeben, die dann für die Konvertierung der zugehörigen Konstruktoren verwendet wird. Falls keine Codepage angegeben ist, verwenden die Klassen dieselbe Codepage wie die Makros.

Weitere Informationen finden Sie unter Makros für die ATL- und MFC-Zeichenfolgenkonvertierung.

"CException" ist jetzt eine abstrakte Basisklasse

CException ist die Basisklasse für alle Ausnahmen in der Microsoft Foundation Class-Bibliothek. Da CException nun eine abstrakte Basisklasse ist, können CException-Objekte nicht direkt erstellt werden. Sie müssen Objekte von abgeleiteten Klassen erstellen. Falls Sie trotzdem ein Objekt direkt erstellen, erhalten Sie eine Fehlermeldung. Weitere Informationen finden Sie unter CException.

Konvertieren von BSTR in "CString"

In Visual C++ 6.0 konnte der folgende Code verwendet werden:

BSTR bstr = SysAllocString(L"Hello");
CString str = bstr;
SysFreeString(bstr);

Bei neuen, unter Visual C++ .NET entwickelten Projekten wird durch diesen Code in ANSi-Builds der folgende Fehler verursacht:

error C2440: 'initializing' : cannot convert from 'BSTR' to 
'ATL::CStringT<BaseType,StringTraits>'

Inzwischen gibt es UNICODE- und ANSI-Versionen von CString (CStringW und CStringA). Um den durch implizite Konvertierungen verursachten Mehraufwand zu reduzieren, werden Konstruktoren, die den inversen Typ aufnehmen (z. B. CStringA, der ein UNICODE-Argument, oder CStringW, der ein ANSI-Argument aufnimmt) anhand des folgenden Eintrags in stdafx.h explitzit markiert:

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS

Um diesen Fehler zu umgehen, führen Sie einen der folgenden Schritte aus:

  • Verwenden Sie CStringW, eine Konvertierung zu vermeiden:

    BSTR bstr = SysAllocString(L"Hello");
    CStringW str = bstr;
    SysFreeString(bstr);
    
  • Rufen Sie den Konstruktor explizit auf:

    BSTR bstr = SysAllocString(L"Hello");
    CString str = CString(bstr);
    SysFreeString(bstr);
    
  • Entfernen Sie die Zeile #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS aus stdafx.h.

CTime-Änderungen

CTime Class verwendet den zugrunde liegenden __time64_t-Datentyp. In MFC 6.0 wurde der time_t-Datentyp von CTime verwendet, bei dem es sich um einen 32-Bit-Typ handelte. Der Grund für diese Änderung ist die Unterstützung von Zeiten nach 19. Januar 2038, 3:14:07.

Änderungen bezüglich "CComEnumImpl::Skip"

Die CComEnumImpl::Skip-Methode in Versionen vor ATL 7.0 gab für den Eingabewert 0 nicht den richtigen Fehlercode zurück. Außerdem wurden hohe Eingabewerte von der Methode inkonsistent behandelt. Dieses Verhalten wurde in ATL 7.0 korrigiert.

Assertionen bezüglich "CWnd::DestroyWindow"

Beim Anzeigen einer QuickInfo in CWnd::DestroyWindow wurde ein Assertionsfehler angezeigt. Aus diesem Grund wurden die folgendenMembervariablen in MFC 7.0 von AFX_THREAD_STATE in AFX_MODULE_THREAD_STATE verschoben:

  • CToolTipCtrl* m_pToolTip

  • CWnd* m_pLastHit

  • int m_nLastHit

  • TOOLINFO m_lastInfo

  • int m_nLastStatus

  • CControlBar* m_pLastStatus

LNK2001-Fehler: Nicht aufgelöstes externes Symbol

Beim Aufrufen einer Funktion in einer statischen Bibliozthek oder DLL, , die einen wchar_t-Typ aufnimmt, kann ein LNK2001-Fehler über ein nicht aufgelöstes externes Symbol ausgegeben werde (beachten Sie, dass BSTR und LPWSTR in wchar_t* aufgelöst werden).

Dieser Fehler wird durch die /Zc:wchar_t-Compileroption verursachht, die in neuen MFC-Projekten standardmäßig aktiviert ist. Durch diese Option wird der Compiler veranlasst, wchar_t als systemeigenen Typ zu behandeln. Vor Einführung von Visual C++ .NET wurde wchar_t als unsigned short behandelt.

Wenn im Hauptprojekt und in der Bibliothek nicht dieselbe Einstellung für /Zc:wchar_t verwendet werden, stimmen die Funktionssignaturen nicht überein. Um dieses Problem zu vermeiden, erstellen Sie die Bibliothek mit der /Zc:wchar_t-Compileroption neu oder deaktivieren sie auf der Eigenschaftenseite Sprache im Dialogfeld Eigenschaftenseite über die Einstellung wchar_t als built-in Typ behandeln.

Boolesche Ausdrücke haben jetzt den Typ "bool" und nicht "BOOL"

Betrachten Sie die folgende Klasse:

class CMyClass : public CObject
{
   BOOL bFlag;

   void Serialize (CArchive& ar))
   {
      if (ar.IsStoring())
         ar << (bFlag != FALSE); // breaking change
      else
         ar >> bFlag;
   }
};

Vor Einführung von Visual C++ .NET wurde der bFlag != FALSE-Ausdruck als BOOL ausgewertet, und es wurden vier Byte geschrieben. In Visual C++ .NET wird er als bool ausgewertet, und es wird ein Byte geschrieben. Dies bedeutet, dass Programme, die mit unterschiedlichen Compilerversionen kompiliert wurden, Datendateien erzeugen können, die nicht miteinander kompatibel sind.

Um das Problem zu vermeiden, wandeln Sie den Ausdruck in den Typ BOOL um:

ar << (BOOL)(bFlag != FALSE);

"CColorPropPage" und "CFontPropPage" wurden entfernt

In früheren MFC-Versionen wurden Eigenschaftenseiten für Farb- oder Schriftarteigenschaften in einem ActiveX-Steuerelement angezeigt, indem die GUID CLSID_CColorPropPage bzw. CLSID_CFontPropPage angegeben wurde. Diese GUIDs zeigten auf die Klassen CColorPropPage und CFontPropPage, die nicht mehr implementiert sind. Verwenden Sie stattdessen die GUIDs CLSID_StockColorPage und CLSID_StockFontPage. Da diese durch msstkprp.dll implementiert werden, müssen Sie diese DLL mit Ihrer Anwendung weitergeben.

ON_MESSAGE-Änderungen

Der Funktionsparameter im Makro ON_MESSAGE muss dem Typ afx_msg LRESULT (CWnd::*)(WPARAM, LPARAM) entsprechen.

Änderungen der OLE DB-Vorlagen

Weitere Informationen zu Änderungen an den OLE DB-Vorlagen finden Sie im Knowledge Base-Artikel "INFO: Porting Issues with Visual Studio .NET OLE DB Provider Template Classes" (Q321743, nur auf Englisch verfügbar). Knowledge Base-Artikel finden Sie auf der MSDN Library-CD-ROM oder unter https://support.microsoft.com/support.

OLE DB-Consumerklassen und -vorlagen

Allgemein ist anzumerken, dass die Accessorklasse zusätzliche Member implementieren muss. Dies ist jedoch nur erforderlich, wenn Sie manuell eine eigene Accessorklasse implementieren. Wenn die Accessorklasse von CAccessor abgeleitet wird, ist dies nicht erforderlich.

Altes Verhalten

Neues Verhalten

CRowset ist eine Klasse.

CRowset ist eine Klassenvorlage und akzeptiert einen Parameter, nämlich die Accessorklasse TAccessor.

CBulkRowset ist eine Klasse.

CBulkRowset ist eine Klassenvorlage.

Die Basisklasse für CArrayRowset war ein Vorlagenparameter (mit dem Standardwert CRowset).

CArrayRowset wird immer von CBulkRowset abgeleitet.

CDynamicAccessor::GetColumnInfo akzeptierte drei Parameter.

CDynamicAccessor::GetColumnInfo wird in neuer Form bereitgestellt, die den zusätzlichen Parameter ppStringsBuffer akzeptiert. Durch Verwendung dieses Parameters wird ein Speicherverlust eliminiert. Die bis dahin verwendete Methode ist veraltet.

Rowset, der zweite Parameter der CAccessorRowset-Vorlage, ist eine Rowset-Klasse.

TRowset, der zweite Parameter der CAccessorRowset-Vorlage, ist eine Rowset-Klassenvorlage.

Rowset, der zweite Parameter der CTable-Vorlage, ist eine Rowset-Klasse.

TRowset, der zweite Parameter der CTable-Vorlage, ist eine Rowset-Klassenvorlage.

Rowset, der zweite Parameter der CCommand-Vorlage, ist eine Rowset-Klasse.

TRowset, der zweite Parameter der CCommand-Vorlage, ist eine Rowset-Klassenvorlage.

DEFINE_COMMAND-Makro

Das DEFINE_COMMAND-Makro ist veraltet. Verwenden Sie stattdessen DEFINE_COMMAND_EX.

OLE DB-Anbieterklassen und -vorlagen:

Die interne Implementierung zahlreicher Schnittstellen und Methoden wurde seit Visual C++ 6.0 geändert. Je nachdem, ob diese Methoden von Ihrer Anwendung überschrieben werden, können hierdurch Kompatibilitätsprobleme auftreten.

Altes Verhalten

Neues Verhalten

Für die Rowset/Accessor-Implementierung wurden CSimpleMap/CSimpleArray-Klassen verwendet. Vom Benutzer bereitgestellte Auflistungsklassen mussten mit CSimpleMap/CSimpleArray kompatibel sein.

Für die Rowset/Accessor-Implementierung werden CAtlMap/CAtlArray-Klassen verwendet. Vom Benutzer bereitgestellte Auflistungsklassen müssen mit CAtlMap/CAtlArray kompatibel sein. Darüber hinaus sollte Code, in dem Methoden dieser Auflistungsklassen aufgerufen werden, überprüft werden, da zwischen den Klassen CAtl* und CSimple* signifikante Unterschiede bestehen (Parameter, Rückgabewerte usw.), die Laufzeitfehler verursachen können.

ICommandImpl wurde von ICommand abgeleitet.

ICommandImpl ist eine Vorlage, die vom CommandBase-Argument der Vorlage abgeleitet wird (der Standardwert lautet ICommand).

ICommandTextImpl wurde von ICommandImpl<ICommandImpl<T> abgeleitet.

ICommandTextImpl wird von ICommandImpl<ICommandImpl<T, ICommandText> abgeleitet. Beachten Sie, dass ICommandImpl hier von ICommandText (und nicht vom Standard ICommand) abgeleitet wird.

Siehe auch

Referenz

Änderungen in ATL und MFC