[level4] [ウィンドウ] [ HWND ] [ HINSTANCE ] [ MSG構造体] [Win32 データ型] [コールバック関数]


Win32 API の 構造体と32ビット値

 

 

 [はじめに]

 HWND も HINSTANCE も、MSG も、単に 「型」 ともいいますが、言葉を延ばすと 「データ型」 です。これら大文字で独特なデータ型は、Windows API 固有のものです。C 言語の例を一つ挙げれば、char 型は 8 ビットの整数を意味するデータ型です。

 「データ型」 は、文法上は、変数や識別シンボル(※)を宣言するために使う、宣言シンボルです。( 型宣言子の役割 ) 。

 ※ MSG msg ; の msg は、「構造」を持ったデータ だから、変「数」 とは呼べませんね。こうなると、コンパイラーのレベルの言葉で識別シンボルや、識別子、識別名、などと呼ばざるを得ません。変数も識別子です。

 Windows API のプログラミングでは、これら独特に大文字の 「データ型」 が沢山あります。

 

 [Win32 API の データ型(宣言シンボル) 〜: Simple Types と構造型]

 HWND や HINSTANCE が 32 ビットの値であることを知っていれば、構造体である MSG 型との区別から、「データ型」 といっても2つあるな、ということに気づくはずです。構造を持たない Simple Types (単純型)と、構造型の2種類あります。HWND のようなデータ型は、結局は 「単純な数値」 を表し、「単純な数値」 が2つ以上あって「データ構造」をなす「構造型」 とは違います(Simple Type : 単純型)。

 

 C 言語一般でも、"基本データ型" には "単純型" と "ポインタ型" がある・・・ のように分類がありますが、Windows API(Win32 API) の説明には、HWND や HINSTANCE も Simple Types (単純型) であると述べられています。意識することはなくても、HWND は 32 ビット値であると同時に ポインタ型で、また、文字列へのポインタ型の LPSTR なども Simple types として述べられています。だから、Windows API(Win32 API) の Simple types 「単純型」 は、「構造を持たない単純な数値(Win32の単純型)」と「構造型」 との区別 のためにあって、C 言語でのそれとは少し異なります 。

 これら Windows API の単純型は、typedef 文 により定義された、型の別名です。そして、定義を展開すればすべて C 言語のキーワードとなります。対比として述べるならば、構造型は typedef と struct 文で定義されます。

 

 あまり大切な区別というわけではありません。そして、あまり害があるとも思いませんが、「HWND は構造体だ」 のようなありがちな勘違い (見間違い) は、いちおう避けておきたいものです。

 


 

Simple Types (Win32の単純型)

 

 [色んな Simple Types がある意味]

 HWND や HINSTANCE は、同じ 32 ビット値です。だから、理屈としては long 型 (32 ビット) で表してしまえば事足りることになりますが、そんなことをすれば実際はコンパイルエラーになります。

 このように、Simple Types のうちで、同じ 32 ビット値でも、新たなそれぞれの型があって区別されているのは、数値の意味や役割を明確にするためです。

 

 それによって、関数のプロトタイプを見たときも関数のことがより理解しやすいし、また、コンパイル時には厳しい「型チェック」 があるので、プログラム中のミスやバグが大幅に防げることも、見逃せない大きな利点です。(個人的にはつくづくありがたいと思うのです)

 また、例えば 「WORD 型」 は 16 ビット値をあらわすデータ型です。32 ビットに限らず、16 ビット、8 ビットを表す Simple types もあります。

 

 [Simple Types と ハンドル]

 [ハンドル以外のもの]
 Simple Types のうち、ハンドル(型)を除くと、BOOL、UINT、WPARAM、LPARAM などが挙げられます。

 これらは「役割」を持つというよりは半ば「意味」だけで、いろいろなときに使う汎用の整数型です。

 更に WNDPROC も Simple Types のうちです。オリジナルのプロシージャを、自分で記述したプロシージャで独自に処理させる、「サブクラス化」 の手法を用いる場合は、WNDPROC 型の変数 (関数ポインタ)を、宣言して用意し、オリジナルのプロシージャの "関数アドレス" (一応 32 ビット値) を格納してとっておく場合があります。WNDPROC 型は平たく言えば 「関数アドレス型」さらに "関数ポインタ"型 です。

 [ハンドル]
 Simple Types のうち、頭文字 「H」 ではじまる 「データ型」 は、ほとんどが 「ハンドル(型)」 です。そして、「リソース」 (やオブジェクト) を管理する、という 「役割」 があります。

 HWND 型自体は構造体ではありませんが、HWND 型のウィンドウハンドルの値(これはデータ「構造」への"アドレス"なのです) が指し示す先には、実は構造体が広がっています。

 例えばウィンドウは、作成されたすぐあとから、その高さや幅、位置などのデータを持つことになるから、そのデータはどこかに収めておかなくてはならないのです。それは、 OS が管理しています。ウィンドウハンドルの値はそのデータ(へ)のアドレスを表しています(ポインタ)。このように見るとウィンドウハンドルに関してはわかりやすいのですが、ほかにハンドルによって管理されるものに、描画するときに線を描く「ペン : HPEN 型」とか、背景を塗りつぶすための「ブラシ : HBRUSH 型」 などもあります。なんでペンとかブラシも?という疑問は最もだと思うのですが、ペンも、ペンの太さ・色・パターンなど、結局は一つでない複数のパラメータを持ったデータ (構造体) として管理しないわけにはいきません。ブラシも、色、パターンといった要素があり同様です。ぎょうぎょうしく構造体なんて使わなくても、と思ったところで、2つ以上パラメータがあったらデータ構造体に頼らざるを得ないのです。

 ハンドルはみんなこのようで、Windows API の説明では、「リソース」 へのポインタだと、述べられています。だから、システムがメモリ領域を割いて管理(ロード)しているこれら、なにかのデータは、みんな 「リソース」 なのです。

 HANDLE 型、というのもあります。どのハンドルを表すのにもつかえるような、「ハンドルの総元締め」 かどうか、普通ハンドルはそれぞれ種類別に使うから、そんなふうに(乱暴に)は使う例を見ることがないので、よくわからないところですが、実際は、ファイルを扱うときの 「ファイルハンドル」 として使われることが多いです。(しばしばグローバルメモリオブジェクトや他のオブジェクト)。ファイルもやっぱり、位置指示子やファイルの属性などのパラメータを取りまとめて扱わなければならないということです。

 ここまで述べておいてなんだけれども、ハンドルという言葉にはこだわることが目的ではありません。なんとかハンドル、はたくさんありますが、やりたい処理にしたがってその都度付き合っていればいいものです。ハンドルはハンドルとして扱っていればいいので、ポインタとかはどうでも良いのです。あとは関数がやってくれるし、ハンドルとはそのように、関数に使えばよくまた、アドレスを意識させないようにデザインされているものだと言うこともできます。

 

 Win32 のデータ型から広がる薀蓄は個人的には以上のようなところです。

 

 

[トップ] [戻る]