DLL のエクスポート関数のエントリ ポイント
DLL のエクスポート関数の場合は、DLL モジュールから呼び出し元アプリケーションの DLL に切り替えるときに、AFX_MANAGE_STATE マクロを使用して、適切なグローバル状態を維持します。
このマクロを呼び出すと、モジュールのグローバル データが含まれている AFX_MODULE_STATE
構造体へのポインターである pModuleState
が、関数のあるスコープの残り部分に対して有効なモジュール状態として設定されます。 マクロが含まれているスコープから出ると、以前の有効なモジュール状態が自動的に復元されます。
この切り替えは、スタックに AFX_MODULE_STATE
クラスのインスタンスを構築することで実現されます。 このクラスは、コンストラクターで現在のモジュール状態へのポインターを取得し、メンバー変数に格納します。その後、pModuleState
を新しい有効なモジュール状態として設定します。 このクラスは、デストラクターでは、メンバー変数に格納されているポインターを有効なモジュール状態として復元します。
DLL 内のダイアログ ボックスを起動する関数など、エクスポート関数がある場合は、関数の先頭に次のコードを追加する必要があります。
AFX_MANAGE_STATE(AfxGetStaticModuleState())
これにより、現在のスコープの終わりまで、現在のモジュールの状態が AfxGetStaticModuleState から返された状態と交換されます。
AFX_MANAGE_STATE
マクロを使用しない場合、DLL 内のリソースに関する問題が発生します。 既定では、MFC はメイン アプリケーションのリソース ハンドルを使用して、リソース テンプレートを読み込みます。 このテンプレートは、実際には DLL に格納されています。 根本原因は、MFC のモジュール状態情報が AFX_MANAGE_STATE
マクロによって切り替えられていないことです。 リソース ハンドルは、MFC のモジュール状態から回復されます。 モジュール状態を切り替えないと、正しくないリソース ハンドルが使用されます。
AFX_MANAGE_STATE
は、DLL 内のすべての関数に挿入する必要はありません。 たとえば、InitInstance
は、AFX_MANAGE_STATE
なしで、アプリケーション内の MFC コードによって呼び出すことができます。MFC が自動的に、InitInstance
の前にモジュール状態をシフトし、InitInstance
から戻った後で元のモジュール状態に戻すためです。 すべてのメッセージマップ ハンドラーでも同様です。 通常の MFC DLL では、実際にはメッセージをルーティングする前にモジュール状態を自動的に切り替える特別なマスター ウィンドウ プロシージャがあります。