Share via


ウィンドウ クラスについて

各ウィンドウ クラスには、同じクラスのすべてのウィンドウで共有される関連付けられたウィンドウ プロシージャがあります。 ウィンドウ プロシージャは、そのクラスのすべてのウィンドウのメッセージを処理するため、動作と外観を制御します。 詳細については、「 ウィンドウ プロシージャ」を参照してください。

プロセスでは、そのクラスのウィンドウを作成する前に、ウィンドウ クラスを登録する必要があります。 ウィンドウ クラスを登録すると、ウィンドウ プロシージャ、クラス スタイル、およびその他のクラス属性がクラス名に関連付けられます。 プロセスが CreateWindow 関数または CreateWindowEx 関数でクラス名を指定すると、そのクラス名に関連付けられたウィンドウ プロシージャ、スタイル、およびその他の属性を含むウィンドウが作成されます。

このセクションでは、次のトピックについて説明します。

ウィンドウ クラスの種類

ウィンドウ クラスには、次の 3 種類があります。

これらの型は、スコープと、それらがいつどのように登録および破棄されるかによって異なります。

システム クラス

システム クラスは、システムによって登録されるウィンドウ クラスです。 多くのシステム クラスは、すべてのプロセスで使用でき、他のクラスはシステムによって内部でのみ使用されます。 システムはこれらのクラスを登録するため、プロセスでクラスを破棄することはできません。

システムは、いずれかのスレッドがユーザーまたは Windows グラフィックス デバイス インターフェイス (GDI) 関数を初めて呼び出す際に、プロセスのシステム クラスを登録します。

各アプリケーションは、システム クラスの独自のコピーを受け取ります。 同じ VDM 内のすべての 16 ビット Windows ベースのアプリケーションは、16 ビット Windows の場合と同様に、システム クラスを共有します。

次の表では、すべてのプロセスで使用できるシステム クラスについて説明します。

クラス 説明
Button ボタンのクラス。
ComboBox コンボ ボックスのクラス。
編集 編集コントロールのクラス。
ListBox リスト ボックスのクラス。
Mdiclient MDI クライアント ウィンドウのクラス。
ScrollBar スクロール バーの クラス。
静的 静的コントロールのクラス。

 

次の表では、システムでのみ使用できるシステム クラスについて説明します。 完全のためにここに記載されています。

クラス 説明
ComboLBox コンボ ボックスに含まれるリスト ボックスのクラス。
DDEMLEvent 動的データ交換管理ライブラリ (DDEML) イベントのクラス。
Message メッセージのみのウィンドウのクラス。
#32768 メニューの クラス。
#32769 デスクトップ ウィンドウのクラス。
#32770 ダイアログ ボックスのクラス。
#32771 タスク切り替えウィンドウのクラス。
#32772 アイコン タイトルのクラス。

 

アプリケーション グローバル クラス

アプリケーション グローバル クラスは、プロセス内の他のすべてのモジュールで使用できる実行可能ファイルまたは DLL によって登録されたウィンドウ クラスです。 たとえば、.dllは RegisterClassEx 関数を呼び出して、カスタム コントロールをアプリケーション グローバル クラスとして定義するウィンドウ クラスを登録して、.dllを読み込むプロセスがカスタム コントロールのインスタンスを作成できるようにします。

すべてのプロセスで使用できるクラスを作成するには、.dllにウィンドウ クラスを作成し、すべてのプロセスで.dllを読み込みます。 すべてのプロセスで.dllを読み込むには、次のレジストリ キーの AppInit_DLLs 値にその名前を追加します。

Hkey_local_machine\ソフトウェア\マイクロソフト\\ Windows NT CurrentVersion\Windows

プロセスが開始されるたびに、エントリ ポイント関数を呼び出す前に、新しく開始されたプロセスのコンテキストで指定された.dllが読み込まれます。 .dllは、初期化プロシージャ中に クラスを登録し、 CS_GLOBALCLASS スタイルを指定する必要があります。 詳細については、「 クラス のスタイル」を参照してください。

アプリケーション グローバル クラスを削除し、それに関連付けられているストレージを解放するには、 UnregisterClass 関数を使用します。

アプリケーション ローカル クラス

アプリケーション ローカル クラスは、実行可能ファイルまたは.dllが排他的に使用するために登録する任意のウィンドウ クラスです。 任意の数のローカル クラスを登録できますが、通常は 1 つだけを登録します。 このウィンドウ クラスは、アプリケーションのメイン ウィンドウのウィンドウ プロシージャをサポートします。

システムは、登録したモジュールが閉じると、ローカル クラスを破棄します。 アプリケーションでは、 UnregisterClass 関数を使用してローカル クラスを削除し、それに関連付けられているストレージを解放することもできます。

システムがウィンドウ クラスを検索する方法

システムは、3 種類のウィンドウ クラスごとに構造体の一覧を保持します。 アプリケーションが CreateWindow または CreateWindowEx 関数を呼び出して、指定したクラスを持つウィンドウを作成すると、システムは次のプロシージャを使用して クラスを検索します。

  1. アプリケーション ローカル クラスの一覧で、インスタンス ハンドルがモジュールのインスタンス ハンドルと一致する指定した名前のクラスを検索します。 (複数のモジュールで同じ名前を使用して、同じプロセスにローカル クラスを登録できます)。
  2. 名前がアプリケーション ローカル クラスの一覧にない場合は、アプリケーション グローバル クラスの一覧を検索します。
  3. 名前がアプリケーション グローバル クラスの一覧にない場合は、システム クラスの一覧を検索します。

アプリケーションによって作成されたすべてのウィンドウは、ダイアログ ボックスなど、アプリケーションの代わりにシステムによって作成されたウィンドウを含め、この手順を使用します。 他のアプリケーションに影響を与えることなく、システム クラスをオーバーライドできます。 つまり、アプリケーションは、システム クラスと同じ名前のアプリケーション ローカル クラスを登録できます。 これにより、アプリケーションのコンテキストでシステム クラスが置き換えられますが、他のアプリケーションでシステム クラスが使用されるのを防ぐことはありません。

ウィンドウ クラスの登録

ウィンドウ クラスは、ウィンドウのスタイル、アイコン、カーソル、メニュー、ウィンドウ プロシージャなどのウィンドウの属性を定義します。 ウィンドウ クラスを登録する最初の手順は、 WNDCLASSEX 構造体にウィンドウ クラス情報を入力することです。 詳細については、「 Window クラスの要素」を参照してください。 次に、 構造体を RegisterClassEx 関数に渡します。 詳細については、「 ウィンドウ クラスの使用」を参照してください。

アプリケーション グローバル クラスを登録するには、WNDCLASSEX 構造体のスタイル メンバーにCS_GLOBALCLASS スタイルを指定します。 アプリケーション ローカル クラスを登録するときは、 CS_GLOBALCLASS スタイルを指定しないでください。

Ansi バージョンの RegisterClassEx、RegisterClassExA を使用してウィンドウ クラスを登録すると、アプリケーションは ANSI 文字セットを使用して、作成されたクラスのウィンドウにメッセージのテキスト パラメーターを渡すよう要求します。Unicode バージョンの RegisterClassEx、RegisterClassExW を使用してクラスを登録すると、アプリケーションは Unicode 文字セットを使用して、作成されたクラスのウィンドウにメッセージのテキスト パラメーターを渡すよう要求します。 IsWindowUnicode 関数を使用すると、アプリケーションは各ウィンドウの性質を照会できます。 ANSI 関数と Unicode 関数の詳細については、「 関数プロトタイプの規則」を参照してください。

クラスを登録した実行可能ファイルまたは DLL は、 クラスの所有者です。 システムは、クラスの登録時に RegisterClassEx 関数に渡される WNDCLASSEX 構造体の hInstance メンバーからクラスの所有権を決定します。 DLL の場合、 hInstance メンバーは、.dll インスタンスへのハンドルである必要があります。

クラスを所有する.dllがアンロードされた場合、クラスは破棄されません。 したがって、システムがそのクラスのウィンドウに対してウィンドウ プロシージャを呼び出すと、ウィンドウ プロシージャを含む.dllがメモリ内にないため、アクセス違反が発生します。 プロセスは、.dllがアンロードされ、 UnregisterClass 関数を呼び出す前に、 クラスを使用してすべてのウィンドウを破棄する必要があります。

Window クラスの要素

ウィンドウ クラスの要素は、 クラスに属するウィンドウの既定の動作を定義します。 ウィンドウ クラスを登録するアプリケーションは、 WNDCLASSEX 構造体に適切なメンバーを設定し、その構造体を RegisterClassEx 関数に渡すことによって、クラスに要素を割り当てます。 GetClassInfoEx 関数と GetClassLong 関数は、特定のウィンドウ クラスに関する情報を取得します。 SetClassLong 関数は、アプリケーションが既に登録しているローカル クラスまたはグローバル クラスの要素を変更します。

完全なウィンドウ クラスは多くの要素で構成されますが、システムでは、アプリケーションがクラス名、ウィンドウ プロシージャ アドレス、およびインスタンス ハンドルを指定することだけが必要です。 他の要素を使用して、カーソルの形状やウィンドウのメニューの内容など、クラスのウィンドウの既定の属性を定義します。 WNDCLASSEX 構造体の未使用のメンバーは、0 または NULL に初期化する必要があります。 ウィンドウ クラスの要素は、次の表に示すとおりです。

要素 目的
クラス名 クラスを他の登録済みクラスと区別します。
ウィンドウ プロシージャ のアドレス クラス内のウィンドウに送信されるすべてのメッセージを処理し、ウィンドウの動作を定義する関数へのポインター。
インスタンス ハンドル クラスを登録したアプリケーションまたは.dllを識別します。
クラス カーソル クラスのウィンドウに対してシステムが表示するマウス カーソルを定義します。
クラス アイコン 大きなアイコンと小さいアイコンを定義します。
クラスの背景ブラシ ウィンドウを開くか塗りつぶすときにクライアント領域を塗りつぶす色とパターンを定義します。
[クラス] メニュー メニューを明示的に定義しないウィンドウの既定のメニューを指定します。
クラス スタイル ウィンドウを移動またはサイズ変更した後にウィンドウを更新する方法、マウスのダブルクリックを処理する方法、デバイス コンテキストの領域を割り当てる方法、ウィンドウのその他の側面を定義します。
追加のクラス メモリ システムがクラス用に予約する必要がある余分なメモリの量をバイト単位で指定します。 クラス内のすべてのウィンドウは追加のメモリを共有し、アプリケーション定義の目的で使用できます。 システムは、このメモリを 0 に初期化します。
追加のウィンドウ メモリ クラスに属する各ウィンドウに対してシステムが予約する必要がある余分なメモリの量をバイト単位で指定します。 余分なメモリは、任意のアプリケーション定義の目的で使用できます。 システムは、このメモリを 0 に初期化します。

 

Class Name (クラス名)

すべてのウィンドウ クラスには、1 つのクラスを別のクラスと区別するためのクラス が必要です。 WNDCLASSEX 構造体の lpszClassName メンバーを、名前を指定する null で終わる文字列のアドレスに設定して、クラス名を割り当てます。 ウィンドウ クラスはプロセス固有であるため、ウィンドウ クラス名は同じプロセス内でのみ一意である必要があります。 また、クラス名はシステムのプライベート atom テーブルのスペースを占有するため、クラス名の文字列はできるだけ短くしておく必要があります。

GetClassName 関数は、特定のウィンドウが属するクラスの名前を取得します。

ウィンドウ プロシージャ のアドレス

すべてのクラスには、クラス内のウィンドウのすべてのメッセージを処理するために使用されるウィンドウ プロシージャのエントリ ポイントを定義するためのウィンドウ プロシージャ アドレスが必要です。 クライアント領域の描画やユーザーからの入力への応答など、ウィンドウでタスクを実行する必要がある場合、システムはメッセージをプロシージャに渡します。 プロセスは、WNDCLASSEX 構造体の lpfnWndProc メンバーにそのアドレスをコピーすることによって、ウィンドウ プロシージャをクラスに割り当てます。 詳細については、「 ウィンドウ プロシージャ」を参照してください。

インスタンス ハンドル

すべてのウィンドウ クラスには、クラスを登録したアプリケーションまたは.dllを識別するためのインスタンス ハンドルが必要です。 システムでは、すべてのモジュールを追跡するためにインスタンス ハンドルが必要です。 システムは、実行中の実行可能ファイルまたは.dllの各コピーにハンドルを割り当てます。

システムは、各実行可能ファイルのエントリ ポイント関数にインスタンス ハンドルを渡します ( WinMain を参照)、.dllします ( DllMain を参照)。 実行可能ファイルまたは.dllは、このインスタンス ハンドルを WNDCLASSEX 構造体の hInstance メンバーにコピーしてクラスに割り当てます。

クラス カーソル

クラス カーソルは、クラス内のウィンドウのクライアント領域にある場合のカーソルの形状を定義します。 システムは、カーソルがウィンドウのクライアント領域に入ると、指定された図形にカーソルを自動的に設定し、その図形がクライアント領域に残っていることを確認します。 ウィンドウ クラスにカーソル図形を割り当てるには、LoadCursor 関数を使用して定義済みのカーソル図形を読み込み、返されたカーソル ハンドルを WNDCLASSEX 構造体の hCursor メンバーに割り当てます。 または、カスタム カーソル リソースを指定し、 LoadCursor 関数を使用してアプリケーションのリソースから読み込みます。

システムにはクラス カーソルは必要ありません。 アプリケーションで WNDCLASSEX 構造体の hCursor メンバーを NULL に設定した場合、クラス カーソルは定義されません。 システムは、カーソルがウィンドウに移動するたびに、ウィンドウがカーソルの形状を設定することを前提としています。 ウィンドウは、ウィンドウがWM_MOUSEMOVE メッセージを受信するたびに SetCursor 関数を呼び出すことによって、カーソルの図形を設定できます。 カーソルの詳細については、「 カーソル」を参照してください。

クラス アイコン

クラス アイコンは、システムが特定のクラスのウィンドウを表すために使用する画像です。 アプリケーションには、2 つのクラス アイコン (大きいアイコンと小さいアイコン) を含めることができます。 ユーザーが Alt キーを押しながら Tab キー を押すと表示されるタスク スイッチ ウィンドウと、タスク バーとエクスプローラーの大きなアイコン ビューに、ウィンドウの大きなクラス アイコンが表示されます。 小さなクラス アイコンは、ウィンドウのタイトル バーと、タスク バーとエクスプローラーの小さなアイコン ビューに表示されます。

ウィンドウ クラスに大小のアイコンを割り当てるには、WNDCLASSEX 構造体の hIcon メンバーと hIconSm メンバーのアイコンのハンドルを指定します。 アイコンのサイズは、大小のクラス アイコンに必要なディメンションに準拠している必要があります。 大きなクラス アイコンの場合は、GetSystemMetrics 関数の呼び出しでSM_CXICON値とSM_CYICON値を指定することで、必要なディメンションを決定できます。 小さなクラス アイコンの場合は、 SM_CXSMICONSM_CYSMICON の値を指定します。 詳細については、「 アイコン」を参照してください。

アプリケーションで WNDCLASSEX 構造体の hIcon メンバーと hIconSm メンバーを NULL に設定した場合、システムはウィンドウ クラスの大小のクラス アイコンとして既定のアプリケーション アイコンを使用します。 大きなクラス アイコンを指定しても小さなクラス アイコンを指定しない場合、システムは大きなクラス アイコンに基づいて小さなクラス アイコンを作成します。 ただし、小さいクラス アイコンを指定しても大きなアイコンを指定しない場合、システムは既定のアプリケーション アイコンを大きなクラス アイコンとして使用し、指定したアイコンを小さなクラス アイコンとして使用します。

WM_SETICON メッセージを使用して、特定のウィンドウの大または小のクラス アイコンをオーバーライドできます。 WM_GETICON メッセージを使用して、現在の大小のクラス アイコンを取得できます。

クラスの背景ブラシ

クラスの背景ブラシは、アプリケーションによる後続の描画のために、ウィンドウのクライアント領域を準備します。 システムはブラシを使用してクライアント領域に単色またはパターンを塗りつぶし、ウィンドウに属しているかどうかに関係なく、その場所から以前のすべての画像を削除します。 システムは、 WM_ERASEBKGND メッセージを ウィンドウに送信することで、その背景を描画する必要があることをウィンドウに通知します。 詳細については、「 ブラシ」を参照してください。

クラスに背景ブラシを割り当てるには、適切な GDI 関数を使用してブラシを作成し、返されたブラシ ハンドルを WNDCLASSEX 構造体の hbrBackground メンバーに割り当てます。

アプリケーションでは、ブラシを作成する代わりに、 hbrBackground メンバーを標準のシステムカラー値のいずれかに設定できます。 標準のシステム カラー値の一覧については、「 SetSysColors」を参照してください。

標準のシステム色を使用するには、アプリケーションで背景色の値を 1 ずつ増やす必要があります。 たとえば、 COLOR_BACKGROUND + 1 はシステムの背景色です。 または、GetSysColorBrush 関数を使用して、標準システムの色に対応するブラシへのハンドルを取得し、WNDCLASSEX 構造体の hbrBackground メンバーでハンドルを指定することもできます。

システムでは、ウィンドウ クラスにクラスの背景ブラシは必要ありません。 このパラメーターが NULL に設定されている場合、ウィンドウは WM_ERASEBKGND メッセージを受信するたびに、独自の背景を描画する必要があります。

[クラス] メニュー

クラス メニューは、ウィンドウの作成時に明示的なメニューが指定されていない場合に、クラス内のウィンドウで使用される既定のメニューを定義します。 メニューは、ユーザーが実行するアプリケーションのアクションを選択できるコマンドの一覧です。

メニューをクラスに割り当てるには、WNDCLASSEX 構造体の lpszMenuName メンバーを、メニューのリソース名を指定する null で終わる文字列のアドレスに設定します。 メニューは、指定されたアプリケーション内のリソースであると見なされます。 必要に応じ、メニューが自動的に読み込まれます。 メニュー リソースが名前ではなく整数で識別される場合、アプリケーションは値を割り当てる前に MAKEINTRESOURCE マクロを適用することで、lpszMenuName メンバーをその整数に設定できます。

システムでは、クラス メニューは必要ありません。 アプリケーションが WNDCLASSEX 構造体の lpszMenuName メンバーを NULL に設定した場合、クラス内のウィンドウにはメニュー バーがありません。 クラス メニューが指定されていない場合でも、アプリケーションはウィンドウを作成するときにウィンドウのメニュー バーを定義できます。

クラスにメニューが指定され、そのクラスの子ウィンドウが作成された場合、メニューは無視されます。 詳細については、「 メニュー」を参照してください。

クラス スタイル

クラス スタイルは、ウィンドウ クラスの追加の要素を定義します。 ビットごとの OR (|) 演算子を使用して、2 つ以上のスタイルを組み合わせることができます。 ウィンドウ クラスにスタイルを割り当てるには、WNDCLASSEX 構造体のスタイル メンバーにスタイルを割り当てます。 クラス スタイルの一覧については、「 ウィンドウ クラス のスタイル」を参照してください。

クラスとデバイス コンテキスト

デバイス コンテキストは、アプリケーションがウィンドウのクライアント領域で描画するために使用する特別な値のセットです。 システムでは、ディスプレイ上の各ウィンドウにデバイス コンテキストが必要ですが、システムがそのデバイス コンテキストを格納および処理する方法を柔軟に行えます。

デバイス コンテキスト スタイルが明示的に指定されていない場合、システムは、各ウィンドウで、システムによって維持されるコンテキストのプールから取得されたデバイス コンテキストを使用すると想定します。 このような場合、各ウィンドウは、描画する前にデバイス コンテキストを取得して初期化し、描画後に解放する必要があります。

ウィンドウ内で描画する必要があるたびにデバイス コンテキストを取得しないようにするために、アプリケーションはウィンドウ クラスの CS_OWNDC スタイルを指定できます。 このクラス スタイルは、プライベート デバイス コンテキストを作成するようにシステムに指示します。つまり、クラス内の各ウィンドウに一意のデバイス コンテキストを割り当てます。 アプリケーションでは、コンテキストを 1 回だけ取得し、後続のすべての描画に使用する必要があります。

追加のクラス メモリ

システムは、システム内の各ウィンドウ・クラスに対して WNDCLASSEX 構造体を内部的に保守します。 アプリケーションは、ウィンドウ クラスを登録するときに、 WNDCLASSEX 構造体の末尾に多数の追加バイトのメモリを割り当てて追加するようにシステムに指示できます。 このメモリは 、余分なクラス メモリ と呼ばれ、クラスに属するすべてのウィンドウで共有されます。 クラスに関連する情報を格納するには、余分なクラス メモリを使用します。

システムのローカル ヒープから余分なメモリが割り当てられるため、アプリケーションでは余分なクラス メモリを慎重に使用する必要があります。 要求された余分なクラス メモリの量が 40 バイトを超える場合、 RegisterClassEx 関数は失敗します。 アプリケーションで 40 バイトを超える必要がある場合は、独自のメモリを割り当て、追加のクラス メモリにメモリへのポインターを格納する必要があります。

SetClassWord 関数と SetClassLong 関数は、追加のクラス メモリに値をコピーします。 追加のクラス メモリから値を取得するには、 GetClassWord 関数と GetClassLong 関数を 使用します。 WNDCLASSEX 構造体の cbClsExtra メンバーは、割り当てる余分なクラス メモリの量を指定します。 余分なクラス メモリを使用しないアプリケーションでは、 cbClsExtra メンバーを 0 に初期化する必要があります。

追加のウィンドウ メモリ

システムは、各ウィンドウの内部データ構造を保持します。 ウィンドウ クラスを登録するときに、アプリケーションは、追加のウィンドウ メモリと呼ばれる追加のメモリバイト数 指定できます。 クラスのウィンドウを作成すると、システムは、指定された量の余分なウィンドウ メモリを割り当てて、ウィンドウの構造体の末尾に追加します。 アプリケーションはこのメモリを使用して、ウィンドウ固有のデータを格納できます。

システムのローカル ヒープから余分なメモリが割り当てられるため、アプリケーションでは余分なウィンドウ メモリを慎重に使用する必要があります。 要求された余分なウィンドウ メモリの量が 40 バイトを超える場合、 RegisterClassEx 関数は失敗します。 アプリケーションで 40 バイトを超える必要がある場合は、独自のメモリを割り当て、メモリへのポインターを追加のウィンドウ メモリに格納する必要があります。

SetWindowLong 関数は、値を余分なメモリにコピーします。 GetWindowLong 関数は、余分なメモリから値を取得します。 WNDCLASSEX 構造体の cbWndExtra メンバーは、割り当てる余分なウィンドウ メモリの量を指定します。 メモリを使用しないアプリケーションでは、 cbWndExtra を 0 に初期化する必要があります。