テクニカル ノート 1: ウィンドウ クラスの登録
ここでは、Microsoft Windows で必要な特殊な WNDCLASSes を登録する MFC ルーチンについて説明します。 MFC と Windows によって使用される特定の WNDCLASS 属性について説明します。
問題
CWnd オブジェクトの属性 (Windows の HWND ハンドルなど) は、ウィンドウ オブジェクトと WNDCLASS という 2 つの場所に格納されます。 WNDCLASS の名前は、lpszClassName パラメーターの CWnd::Create や CFrameWnd::Create などの一般的なウィンドウ作成関数に渡されます。
この WNDCLASS は、次の 4 つの方法のいずれかを使用して登録する必要があります。
MFC で提供されている
WNDCLASSを使用して暗黙的に行う。Windows コントロール (または他のコントロール) をサブクラスにすることで暗黙的に行う。
MFC の AfxRegisterWndClass または AfxRegisterClass を呼び出して、明示的に行う。
Windows ルーチンの RegisterClass を呼び出して、明示的に行う。
WNDCLASS フィールド
WNDCLASS 構造体は、ウィンドウ クラスを記述するさまざまなフィールドで構成されています。 以下の表には、各フィールドと、MFC アプリケーションでそれらがどのように使用されるかが示されています。
| フィールド | 説明 |
|---|---|
| lpfnWndProc | ウィンドウのプロセッサ。AfxWndProc である必要があります |
| cbClsExtra | 使用されません (0 である必要があります) |
| cbWndExtra | 使用されません (0 である必要があります) |
| hInstance | AfxGetInstanceHandle で自動的に入力されます |
| hIcon | フレーム ウィンドウのアイコン。以下を参照してください |
| hCursor | マウスがウィンドウの上に置かれているときのカーソル。以下を参照してください。 |
| hbrBackground | 背景色。以下を参照してください |
| lpszMenuName | 使用されません (NULL である必要があります) |
| lpszClassName | クラス名。以下を参照してください |
提供される WNDCLASSes
MFC の以前のバージョン (MFC 4.0 より前) では、事前定義された複数のウィンドウ クラスが提供されていました。 それらのウィンドウ クラスは、既定では提供されなくなりました。 アプリケーションでは、適切なパラメーターを指定して AfxRegisterWndClass を使用する必要があります。
アプリケーションで、指定されたリソース ID を持つリソースが提供される場合 (AFX_IDI_STD_FRAME など)、MFC はそのリソースを使用します。 それ以外の場合は、既定のリソースが使用されます。 アイコンの場合は標準のアプリケーション アイコンが使用され、カーソルの場合は標準の矢印カーソルが使用されます。
2 つのアイコンが、1 つのドキュメントの種類を持つ MDI アプリケーションをサポートします。一方のアイコンは、メイン アプリケーション用であり、もう一方のアイコンは、アイコン化ドキュメント/MDIChild ウィンドウ用です。 異なるアイコンを持つ複数のドキュメントの種類がある場合、さらに WNDCLASSes を登録するか、CFrameWnd::LoadFrame 関数を使用する必要があります。
CFrameWnd::LoadFrame は、最初のパラメーターとして指定したアイコン ID と、次の標準属性を使用して、WNDCLASS を登録します。
クラス スタイル:
CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;icon AFX_IDI_STD_FRAME
矢印カーソル
COLOR_WINDOW 背景色
CMDIFrameWnd の背景色とカーソルは、CMDIFrameWnd のクライアント領域が MDICLIENT ウィンドウによって完全にカバーされているため、使用されません。 Microsoft では MDICLIENT ウィンドウのサブクラス化を推奨していないため、可能な場合は標準の色とカーソルの種類を使用してください。
コントロールのサブクラス化とスーパークラス化
Windows コントロール (CButton など) をサブクラス化またはスーパークラス化すると、クラスは、そのコントロールの Windows 実装で提供される WNDCLASS 属性を自動的に取得します。
AfxRegisterWndClass 関数
MFC では、ウィンドウ クラスを登録するヘルパー関数を使用できます。 一連の属性 (ウィンドウ クラス スタイル、カーソル、背景ブラシ、およびアイコン) を指定すると、合成名が生成され、結果のウィンドウ クラスが登録されます。 たとえば、
const char* AfxRegisterWndClass(UINT nClassStyle,
HCURSOR hCursor,
HBRUSH hbrBackground,
HICON hIcon);
この関数は、生成された登録済みウィンドウ クラス名の一時文字列を返します。 この関数の詳細については、「AfxRegisterWndClass」を参照してください。
返される文字列は、静的文字列バッファーへの一時ポインターです。 これは、AfxRegisterWndClass への次の呼び出しまで有効です。 この文字列を保持する場合は、次の例のように CString 変数に格納します。
CString strWndClass = AfxRegisterWndClass(CS_DBLCLK, ...);
...
CWnd* pWnd = new CWnd;
pWnd->Create(strWndClass, ...);
...
AfxRegisterWndClass は、ウィンドウ クラスの登録に失敗した場合、CResourceException をスローします (パラメーターが適切ではないか、Windows メモリが不足していたことが原因)。
RegisterClass 関数と AfxRegisterClass 関数
AfxRegisterWndClass で提供されるものよりも、より高度なことを行う必要がある場合、Windows API RegisterClass または MFC 関数 AfxRegisterClass を呼び出すことができます。 CWnd、CFrameWnd、および CMDIChildWndCreate 関数は、最初のパラメーターとしてウィンドウ クラスの lpszClassName 文字列名を受け取ります。 登録に使用したメソッドに関係なく、登録されている任意のウィンドウ クラス名を使用できます。
Win32 上の DLL で AfxRegisterClass (または AfxRegisterWndClass) を使用することが重要です。 Win32 では DLL によって登録されたクラスの登録は自動的には解除されないため、DLL が終了するときに明示的にクラスの登録を解除する必要があります。 RegisterClass の代わりに AfxRegisterClass を使用することで、これは自動的に処理されます。 AfxRegisterClass では、DLL によって登録された一意のクラスの一覧を保持し、DLL が終了すると自動的に登録が解除されます。 DLL で RegisterClass を使用する場合、DLL の終了時にすべてのクラスの登録が解除されている必要があります (DllMain 関数内)。 解除しなければ、別のクライアント アプリケーションが DLL を使用しようとすると、RegisterClass が予期せず失敗する可能性があります。