次の方法で共有


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

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

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

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

ウィンドウ クラスの種類

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

これらの型は、スコープと、それらが登録および破棄されるタイミングと方法によって異なります。

システム クラス

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

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

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

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

クラス 説明
ボタン ボタンのクラス。
ComboBox コンボ ボックスのクラス。
[編集] エディット コントロールのクラス。
リストボックス リスト ボックスのクラス。
MDIClient MDI クライアント ウィンドウのクラス。
スクロールバー スクロール バーのクラス。
スタティック 静的コントロールのクラス。

 

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

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

 

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

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

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

HKEY_LOCAL_MACHINE\ソフトウェア\Microsoft\Windows NT\CurrentVersion\ウィンドウズ

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

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

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

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

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

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

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

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

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

Window クラスの登録

ウィンドウ クラスは、スタイル、アイコン、カーソル、メニュー、ウィンドウ プロシージャなど、ウィンドウの属性を定義します。 ウィンドウ クラスを登録する最初の手順は、 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 構造体の未使用のメンバーをゼロまたは NULL に初期化する必要があります。 ウィンドウ クラスの要素は、次の表に示すとおりです。

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

 

Class Name (クラス名)

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

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 に初期化する必要があります。