다음을 통해 공유


ATL 및 MFC 변경 사항: ATL 7.0 및 MFC 7.0

업데이트: 2007년 11월

참고   이 항목에서 설명하는 기능 중 일부는 Visual C++의 현재 버전에 없을 수도 있습니다.

Visual C++ 6.0 이후 ATL 및 MFC 라이브러리의 많은 부분이 향상되었습니다. 이들 변경 내용 중 일부로 인해 기존 코드가 실행되지 않을 수도 있습니다.

DLL 비호환성

Visual C++ .NET 2002와 함께 제공되는 ATL 및 MFC DLL 파일의 이름이 각각 ATL70.dll과 MFC70.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.0에서는 이전에 CComModule에서 제공한 기능을 여러 개의 새로운 클래스에서 처리합니다. 자세한 내용은 ATL 모듈 클래스를 참조하십시오.

문자열 변환

Visual C++ 6.0의 ATL 3.0 및 그 이전 버전에서는 atlconv.h의 매크로를 사용하는 문자열 변환이 항상 시스템의 ANSI 코드 페이지(CP_ACP)를 사용하여 수행되었습니다. Visual C++ .NET의 ATL 7.0부터는 _CONVERSION_DONT_USE_THREAD_LOCALE이 정의되지 않은 경우 문자열 변환이 현재 스레드의 기본 ANSI 코드 페이지를 사용하여 수행됩니다. _CONVERSION_DONT_USE_THREAD_LOCALE이 정의된 경우에는 이전과 같이 시스템의 ANSI 코드 페이지가 사용됩니다.

CW2AEX 등의 문자열 변환 클래스를 사용하면 변환에 사용할 코드 페이지를 해당 생성자에 전달할 수 있습니다. 코드 페이지를 지정하지 않으면 해당 클래스에서는 매크로와 동일한 코드 페이지를 사용합니다.

자세한 내용은 ATL and MFC String Conversion Macros를 참조하십시오.

CException이 이제 추상 기본 클래스입니다.

CException은 Microsoft Foundation Class 라이브러리의 모든 예외에 대한 기본 클래스입니다. 이제 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의 유니코드 및 ANSI 버전인 CStringWCStringA가 있습니다. 암시적 변환으로 인해 발생하는 불필요한 오버헤드를 없애기 위해, 유니코드 인수를 사용하는 CStringA나 ANSI 인수를 사용하는 CStringW와 같이 역 형식을 사용하는 생성자는 이제 stdafx.h에서 다음 엔트리를 사용하여 명시적으로 태그가 지정됩니다.

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS

이 오류를 해결하려면 다음 중 하나를 수행하십시오.

  • CStringW를 사용하여 변환이 발생하지 않도록 합니다.

    BSTR bstr = SysAllocString(L"Hello");
    CStringW str = bstr;
    SysFreeString(bstr);
    
  • 생성자를 명시적으로 호출합니다.

    BSTR bstr = SysAllocString(L"Hello");
    CString str = CString(bstr);
    SysFreeString(bstr);
    
  • stdafx.h에서 #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS 줄을 제거합니다.

CTime 변경 내용

CTime Class는 내부 __time64_t 데이터 형식을 사용합니다. MFC 6.0에서 CTime은 32비트 형식인 time_t 데이터 형식을 사용했습니다. 이러한 변경은 2038년 1월 19일 3시 14분 07초 이후의 시간을 지원하기 위해 이루어졌습니다.

CComEnumImpl::Skip 변경 사항

ATL 7.0 이전 버전에서는 CComEnumImpl::Skip 메서드가 입력 값 0에 대해 올바른 오류 코드를 반환하지 않았으며, 또한 많은 입력 값을 일관되지 않은 방식으로 처리했습니다. ATL 7.0에서는 이러한 동작이 수정되었습니다.

CWnd::DestroyWindow 어설션

MFC 7.0 이전 버전에서는 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 형식(BSTR 및 LPWSTR은 **wchar_t***가 됨)을 사용하는 정적 라이브러리 또는 DLL에서 함수를 호출할 때는 LNK2001 확인할 수 없는 외부 기호 오류가 발생할 수 있습니다.

이 오류는 새 MFC 프로젝트에서 기본적으로 설정되는 /Zc:wchar_t 컴파일러 옵션으로 인해 발생합니다. 이 옵션을 사용하면 컴파일러에서는 wchar_t를 네이티브 형식으로 처리하게 됩니다. Visual C++ .NET 이전에는 wchar_t가 unsigned short로 처리되었습니다.

주 프로젝트 및 라이브러리에서 /Zc:wchar_t에 대해 동일한 설정을 사용하지 않는 경우에는 함수 시그니처가 일치하지 않게 됩니다. 이러한 문제가 발생하지 않도록 하려면 /Zc:wchar_t 컴파일러 옵션을 사용하여 라이브러리를 다시 빌드하거나, 속성 페이지 대화 상자의 언어 속성 페이지에 있는 wchar_t를 기본 제공 형식으로 처리 설정을 사용하여 주 프로젝트에서 이 옵션의 설정을 해제합니다.

부울 식의 형식이 이제 BOOL이 아닌 bool입니다.

다음 클래스를 참고하십시오.

class CMyClass : public CObject
{
   BOOL bFlag;

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

Visual C++ .NET 이전 버전에서는 bFlag != FALSE 식이 BOOL로 계산되어 4바이트가 작성되었습니다. Visual C++ .NET에서는 bool로 계산되어 1바이트가 작성됩니다. 따라서 각각 다른 버전의 컴파일러로 컴파일된 여러 프로그램에서 서로 호환되지 않는 데이터 파일을 만들 수 있습니다.

이 문제를 방지하려면 식을 BOOL로 캐스팅합니다.

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

CColorPropPage 및 CFontPropPage가 제거되었습니다.

이전 버전의 MFC에서는 ActiveX 컨트롤이 색이나 글꼴 속성에 대한 속성 페이지를 표시할 때 각각 GUID CLSID_CColorPropPage 또는 CLSID_CFontPropPage를 지정했습니다. 이러한 GUID는 CColorPropPageCFontPropPage 클래스를 가리키는데, 이 두 클래스는 이제 더 이상 구현되지 않으므로 대신 GUID CLSID_StockColorPageCLSID_StockFontPage를 사용하십시오. 이 두 클래스는 msstkprp.dll에서 구현되므로 이 DLL을 사용자의 응용 프로그램에 다시 배포해야 합니다.

ON_MESSAGE 변경 내용

ON_MESSAGE 매크로의 함수 매개 변수가 afx_msg LRESULT (CWnd::*)(WPARAM, LPARAM) 형식과 일치해야 합니다.

OLE DB 템플릿 변경 내용

OLE DB 템플릿의 변경 사항에 대한 자세한 내용은 기술 자료 문서 "INFO: Porting Issues with Visual Studio .NET OLE DB Provider Template Classes"(Q321743)를 참조하십시오. 기술 자료 문서는 MSDN Library CD-ROM이나 https://support.microsoft.com/support에 있습니다.

OLE DB 소비자 클래스 및 템플릿

일반적으로 접근자 클래스는 추가 멤버를 구현해야 합니다. 이는 사용자 고유의 접근자 클래스를 수동으로 구현하려는 경우에만 필요합니다. 접근자 클래스가 CAccessor에서 파생된 경우에는 추가 멤버를 구현할 필요가 없습니다.

이전 동작

새 동작

CRowset가 클래스입니다.

CRowset가 클래스 템플릿이며, 한 개의 매개 변수 TAccessor와 접근자 클래스를 사용합니다.

CBulkRowset가 클래스입니다.

CBulkRowset가 클래스 템플릿입니다.

CArrayRowset의 기본 클래스가 템플릿 매개 변수(기본값: CRowset)입니다.

CArrayRowset가 항상 CBulkRowset에서 파생됩니다.

CDynamicAccessor::GetColumnInfo가 세 개의 매개 변수를 사용합니다.

CDynamicAccessor::GetColumnInfo가 추가 매개 변수 ppStringsBuffer를 사용하는 새로운 형식을 취합니다. 이 매개 변수를 사용하면 메모리 누수가 일어나지 않습니다. 이전의 메서드는 사용되지 않습니다.

CAccessorRowset 템플릿의 두 번째 매개 변수인 Rowset가 행 집합 클래스입니다.

CAccessorRowset 템플릿의 두 번째 매개 변수인 TRowset가 행 집합 클래스 템플릿입니다.

CTable 템플릿의 두 번째 매개 변수인 Rowset가 행 집합 클래스입니다.

CTable 템플릿의 두 번째 매개 변수인 TRowset가 행 집합 클래스 템플릿입니다.

CCommand 템플릿의 두 번째 매개 변수인 Rowset가 행 집합 클래스입니다.

CCommand 템플릿의 두 번째 매개 변수인 TRowset가 행 집합 클래스 템플릿입니다.

DEFINE_COMMAND 매크로

DEFINE_COMMAND 매크로는 사용되지 않습니다. 대신 DEFINE_COMMAND_EX를 사용합니다.

OLE DB 공급자 클래스 및 템플릿

Visual C++ 6.0 이후 많은 인터페이스 및 메서드의 내부 구현이 변경되었습니다. 따라서 응용 프로그램이 이러한 메서드를 재정의하는지 여부에 따라 호환성 문제가 발생할 수 있습니다.

이전 동작

새 동작

행 집합/접근자 구현에서 CSimpleMap/CSimpleArray 클래스를 사용합니다. 따라서 사용자가 제공하는 컬렉션 클래스가 CSimpleMap/CSimpleArray와 호환되어야 합니다.

행 집합/접근자 구현에서 CAtlMap/CAtlArray 클래스를 사용합니다. 따라서 사용자가 제공하는 컬렉션 클래스가 CAtlMap/CAtlArray와 호환되어야 합니다. 또한 CAtl* 클래스와 CSimple* 클래스는 서로 매개 변수 및 반환 값 등이 크게 달라 이로 인해 런타임 오류가 발생할 수 있으므로 이러한 컬렉션 클래스의 메서드를 호출하는 코드를 주의 깊게 검토해야 합니다.

ICommandImplICommand에서 파생됩니다.

ICommandImpl이 템플릿의 CommandBase 인수(기본값은 ICommand)에서 파생되는 템플릿입니다.

ICommandTextImplICommandImpl<ICommandImpl<T>에서 파생됩니다.

ICommandTextImplICommandImpl<ICommandImpl<T, ICommandText>에서 파생됩니다. ICommandImpl이 기본값 ICommand가 아닌 ICommandText에서 파생된다는 점에 유의하십시오.

참고 항목

참조

ATL 및 MFC 변경 내용