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