テクニカル ノート 1: ウィンドウ クラスの登録
更新 : 2007 年 11 月
このノートでは、Microsoft Windows に必要な専用 WNDCLASS を登録する MFC ルーチンについて説明します。MFC および Windows で使用する WNDCLASS の属性について説明します。
問題
CWnd オブジェクトの属性 (Windows の HWND ハンドルなど) は、ウィンドウ オブジェクトと WNDCLASS の 2 か所に格納されます。WNDCLASS の名前は、ウィンドウ作成用の一般関数 (CWnd::Create や CFrameWnd::Create など) に lpszClassName パラメータとして渡されます。
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 |
クラス名。下記参照。 |
提供される WNDCLASS
以前のバージョンの MFC (MFC 4.0 より前) では、定義済みの Window クラスがいくつか提供されていました。これらの Window クラスは、既定では提供されないことになりました。アプリケーションでは、適切なパラメータと共にAfxRegisterWndClass を使用する必要があります。
アプリケーションで特定のリソース ID (AFX_IDI_STD_FRAME など) のリソースを用意すると、MFC はそのリソースを使うようになります。それ以外の場合は、既定のリソースを使います。アイコンの場合は標準のアプリケーション アイコンを使い、カーソルの場合は標準の矢印カーソルを使います。
単一文書型の MDI アプリケーションをサポートするアイコンは 2 つあります。1 つはメイン アプリケーション用のアイコンで、もう 1 つは文書や MDIChild ウィンドウ用のアイコンです。各種のアイコンを使う複数文書型の場合は、追加の WNDCLASS を登録するか、CFrameWnd::LoadFrame 関数を使用する必要があります。
CFrameWnd::LoadFrame は、第 1 パラメータとして指定したアイコン ID と、以下に示す標準属性を使用して、 WNDCLASS を登録します。
クラス スタイル : CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
アイコン AFX_IDI_STD_FRAME
矢印カーソル
COLOR_WINDOW 背景色
CMDIFrameWnd では、背景色とカーソルの値は使用されません。これは、CMDIFrameWnd のクライアント領域が MDICLIENT ウィンドウに完全に隠れるためです。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、および CMDIChildWnd の Create 関数は、ウィンドウ クラスの lpszClassName 文字列名を第 1 パラメータとして受け取ります。登録済みのウィンドウ クラス名であれば、登録時に使用したメソッドに関係なく、どれでも使用できます。
Win32 上の DLL では、AfxRegisterClass (または AfxRegisterWndClass) を使用することが重要です。Win32 では、DLL から登録されたクラスは自動的には登録解除されないため、DLL の終了時に明示的に登録を解除する必要があります。ただし、RegisterClass の代わりに AfxRegisterClass を使用すると、この処理が自動的に行われます。AfxRegisterClass は、DLL から登録された一意のクラスのリストを保持し、DLL の終了時に自動的に登録を解除します。DLL で RegisterClass を使用する場合は、DLL の終了時に (DllMain 関数で) すべてのクラスを登録解除する必要があります。これを行わないと、別のクライアント アプリケーションが同じ DLL を使おうとしたとき、RegisterClass が予期せず失敗することがあります。