次の方法で共有


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 までの ATL のバージョンでは、atlconv.h 内のマクロを使用する文字列の変換は、常にシステムの ANSI コード ページ (CP_ACP) を使用して行われていました。Visual C++ .NET の ATL 7.0 からは、文字列の変換は、現在のスレッドの既定の ANSI コード ページを使用して行われます。ただし、_CONVERSION_DONT_USE_THREAD_LOCALE が定義されている場合は、以前と同じようにシステムの ANSI コード ページが使用されます。

CW2AEX などの文字列変換クラスでは、変換に使用するコード ページをコンストラクタに渡すことができます。コード ページを指定しなかった場合は、マクロと同じコード ページが使用されます。

詳細については、「ATL と MFC の文字列変換マクロ」を参照してください。

抽象基本クラスである CException

CException は、MFC (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 に UNICODE バージョンと ANSI バージョン (CStringWCStringA) ができました。暗黙的な変換による不要なオーバーヘッドを示すため、逆のタイプ (たとえば UNICODE の引数を取る 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 クラス は、基になる __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 のアサーション

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 未解決の外部シンボル エラー

スタティック ライブラリまたは DLL にある、wchar_t 型を取る関数を呼び出すとき (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 をビルトイン型として扱う] 設定を使用します。

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_CColorPropPageCLSID_CFontPropPage を指定しました。CColorPropPage クラスと CFontPropPage クラスを指すこれらの GUID は、現在は実装されていません。代わりに、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 ライブラリ CD-ROM または https://support.microsoft.com/support で参照できます。

OLE DB コンシューマ クラスとテンプレート

一般的な注意として、アクセサ クラスは追加メンバを実装する必要があります。この処理は、独自のアクセサ クラスを手動で実装する場合にだけ必要です。アクセサ クラスが CAccessor から派生する場合、この処理は不要です。

以前の動作

新しい動作

CRowset はクラスです。

CRowset はクラス テンプレートであり、パラメータとして TAccessor アクセサ クラスを受け取ります。

CBulkRowset はクラスです。

CBulkRowset はクラス テンプレートです。

CArrayRowset の基本クラスは、テンプレート パラメータでした (既定値は CRowset)。

CArrayRowset は、常に CBulkRowset から派生します。

CDynamicAccessor::GetColumnInfo では 3 つのパラメータを使用していました。

CDynamicAccessor::GetColumnInfo には、追加のパラメータ ppStringsBuffer を受け取る新しい形式があります。このパラメータを使用すると、メモリ リークがなくなります。古いメソッドの使用は避けてください。

CAccessorRowset テンプレートの 2 番目のパラメータである Rowset は、行セット クラスです。

CAccessorRowset テンプレートの 2 番目のパラメータである TRowset は、行セット クラス テンプレートです。

CTable テンプレートの 2 番目のパラメータである Rowset は、行セット クラスです。

CTable テンプレートの 2 番目のパラメータである TRowset は、行セット クラス テンプレートです。

CCommand テンプレートの 2 番目のパラメータである Rowset は、行セット クラスです。

CCommand テンプレートの 2 番目のパラメータである TRowset は、行セット クラス テンプレートです。

DEFINE_COMMAND マクロ。

DEFINE_COMMAND マクロは使用しないでください。代わりに、DEFINE_COMMAND_EX を使用してください。

OLE DB プロバイダ クラスとテンプレート

多くのインターフェイスおよびメソッドの内部実装は、Visual C++ 6.0 から変更されました。これにより、アプリケーションがこれらのメソッドをオーバーライドするかどうかに応じて、互換性の問題が発生することがあります。

以前の動作

新しい動作

行セット/アクセサの実装は、CSimpleMap/CSimpleArray クラスを使用しました。ユーザーが指定するコレクション クラスには、CSimpleMap/CSimpleArray との互換性が必要でした。

行セット/アクセサの実装は、CAtlMap/CAtlArray クラスを使用します。ユーザーが指定するコレクション クラスには、CAtlMap/CAtlArray との互換性が必要です。また、CAtl* クラスと CSimple* クラスの間には、ランタイム エラーの原因となる大きな違い (パラメータ、戻り値など) があるため、これらのコレクション クラスのメソッドを呼び出すコードを確認する必要があります。

ICommandImpl は、ICommand から派生しました。

ICommandImpl は、テンプレートの CommandBase 引数 (既定値は ICommand) から派生するテンプレートです。

ICommandTextImpl は、ICommandImpl<ICommandImpl<T> から派生しました。

ICommandTextImpl は、ICommandImpl<ICommandImpl<T, ICommandText> から派生します。この場合、ICommandImpl は、既定の ICommand ではなく ICommandText から派生します。

参照

参照

ATL と MFC における変更点