井の中の蛙、大海を知ろう
初めは鼻で笑うことの出来るほど短く単純なスクリプトでページ自体も非常に短かったです。
グングン講座は伸びていつの間にやらプログラム初めての方には
読んで頂いても理解できない内容(いろんな意味で)となったかもしれません。
このページからは『HSP』という枠組みから抜け出しさらに難解になって行きます。
できるだけ噛み砕いて説明していくつもりですけど分かりづらいところが多々出てくると思われます。
そういった場合言って頂ければ私の知っている出来る限りのところまで紐解いて解説いたします。
この章で解説することは新命令は1つも出てきません。HSPは使い始めて日が浅いが
多言語をやったことがあると言う方々にはお分かりいただけると内容だと思います。

さてソレでは始めます。
初めに説明すべきことはやはり変数のデータ型についてでしょう。
C言語等の別言語では変数を使用する際にはまず変数の型を宣言しなければならないものが大半です。
型の指定には、基本型、サイズ・符号・性質の型修飾子、列挙型、ポインタ型、構造を持つ型を使います。
型を決めることでそのデータの性格や数値の表記範囲が規定されます。
基本的なデータ型はint,char,float,doubleと特殊な型なしvoidからなります。
符号・サイズ・基本形の組み合わせは、
呼称データ型ビット幅例
型なしvoid-
文字型char8
signed char8
符号なし文字型unsigned char8
整数型int16 or 32
signed int16 or 32
符号なし整数型unsigned int16 or 32
短長整数型short int16
signed short int16
符号なし短長整数型unsigned short int16
倍長整数型long int32
signed long int32
符号なし倍長整数型unsigned long int32
実数型float32
倍精度実数型double64
拡張精度実数型long double80
上記を見ていただければ分かりますが基本データ型とソレの符号付(signed)は同じ呼称です。 また呼称だけでなく表記範囲も同じとなっています。 ビット幅例が「16 or 32」となっているのは処理系の違いです。 現在のWindowsやUNIX環境のCでの幅は32ビットが主流となっていますが 従来の、MS−DOS用処理系では16ビット幅となってます。 なぜこの様な話が出るかといいますと、既に書いたようにHSP以外の言語の変数には型があります。 HSP用ではないDLLなどに含まれる関数等を使用する場合、この型が重要になってくるのです。 型を合わせなければ使用できないのですから…。 合わせるも何もHSPには文字列型と数値型しかないじゃないか、となります。 文字列型は1バイトからなり、数値型は4バイトからなることは既にご存知ですね。
	sdim buf, 256 // 1バイトである半角文字を256文字分(256バイト)確保する
	dim num, 5    // 1つ4バイトの数値型を5つ分(20バイト)確保する
	stop
デバックウィンドウを表示させ変数の「メモリサイズ」を見ていただければお分かりいただけると思います。 余談ですが文字列型の確保は4の倍数分確保しなくてもメモリサイズは4の倍数分確保されます。 ですので例えば5バイト分確保した場合、8文字(厳密には7文字)まで扱えることとなります。 話を戻します。 文字列型は1バイトなので8ビットの「char」型と同じで問題はありません。 「1バイト = 8ビット」について知らない方はビット演算のページをご覧ください。 数値型は4バイトなので32ビットの「long int , int(32ビット版)」と同じです。 コレも問題ないでしょう。 では他のサイズの違う型を指定しなければならない場合はどのように指定するのでしょう? 例えば64バイトの「double」型の指定等ですね。 ココでのポイントはHSPがメモリを確保する時の確保の仕方です。 メモリ確保はすべて繋がってまとまったアドレスを確保しようとします。 ├────┤ 0x00001000│    │ ├────┤ 0x00001001│    │ ├────┤ 0x00001002│    │ ├────┤ 0x00001003│    │ ├────┤ 0x00001004│    │ ├────┤ 0x00001005│    │ ├────┤ 0x00001006│    │ ├────┤ 0x00001007│    │ ├────┤ 例えば上のようなメモリでアドレス「0x000010000」までが全部埋まっている時に3つ分確保しようとすると 「0x00001000」「0x00001001」「0x00001003」と間が飛ぶように確保するのではなく、 「0x00001003」「0x00001004」「0x00001005」というように繋がるようにして確保する…はず。 それでソレがどうしたのかと言うと、配列用に確保するのも上記イメージと同じです。 つまり、1ブロック1バイトとして「dim buf, 16」とすると、 buf用に16×4の64ブロック連続して確保することになります。 そうすると変数bufのメモリサイズは「double」型とに必要なサイズと同じですね。 型は所詮、扱いがどうであれ、メモリサイズの問題だけなので、 メモリさえ確保すれば「double」型や「long double」型も使用できることになります。 では16ビットの「short int , int(16ビット版)」はどうでしょう? 文字列型を2バイト確保する、としますか? 上記余談でも解説しましたが2バイトとしても4バイト分確保されますけどね。 問題はソコではなく代入の仕方・データの取り出し方です。 例えば、555と言う数値を「short int」型用に入れなければならないときはどうしますか? 「buf=555」とすると、数値型は4バイトなので上記型は「555,0」と言うデータを指定したことになります。 2バイトのみの場合は特に問題ないでしょう。 それでは、555,444,333と言う数値を2バイトの型に入れる必要が出て来た場合はどうでしょう? 先ほど555だけで2バイトの型は「555」「0」という2つのデータを指定したことになると書きました。 普通に配列の要素を3つ分確保してそれぞれの要素にデータを入れていたのでは 「555」「0」「444」「0」「333」「0」というデータを6個指定することになります。 間の0が邪魔ですね。 どのようにして1つ4バイトの変数に4バイト未満のデータ複数入れる・取り出すのかと言うと、 peekwpeekpokewpoke命令を使用することで出し入れができます。 ●バイト目の文字をチェックしたりする時にpeek命令で取り出しアスキーコードを見ていましたね。 ソレと同じように●バイト目の数値を取り出す・入れるということも出来ます。
	wpoke buf.0, 0, 555 // bufの0バイト目に入れる
	wpoke buf.0, 2, 444 // bufの2バイト目に入れる
	wpoke buf.1, 0, 333 // buf.1の0バイト目に入れる
こんな命令を使用しなくても下記のようにすれば大丈夫です。
	buf = 555 // 2バイト単位で見るとbuf=555,0
	buf += 444 << 16 // 1バイト=8ビットなので2バイト=16ビット 16ビット左シフト(512倍)したものを足す
	buf.1 = 333 // 上のbufは2つに分けなくてもbuf=555+(444<<16)としてもよい
取り出しは
	wpeek num.0, buf.0, 0 // bufの0バイト目取り出し
	wpeek num.1, buf.0, 2 // bufの2バイト目取り出し
	wpeek num.2, buf.1, 0 // buf.1の0バイト目取り出し
命令を使用せずに取り出すなら、
	num.0 = buf.0 & $ffff
	num.1 = buf.0 >> 16 & $ffff
	num.2 = buf.1 & $ffff // この場合は2バイト目に入ってないので「num.2=buf.1」でもよい
初めての方にはちょっとわかりづらいですかね…? ビット演算(ってか論理演算?)を知らないとサッパリだと思いますが AND演算でマスク処理(特定ビットの数値を取り出すもの)をしているのですね。 頭に「?」マークが回っている方はビット演算のページへ。 さて、これから(と言ってもまだ大分先?)使用していくApplicationProgramInterface(API)を いろいろな場所で調べていくことと思いますがAPIではデータ型を別名で書かれていると思います。 全部書き出すと非常に多いのでよく出てくるものだけ少し書いておきます。(32bit処理系)
SHORT2バイト-32768〜32767
INT4バイト-2147483648〜2147483647
LONG4バイト-2147483648〜2147483647
CHAR1バイト0〜255
BYTE1バイト0〜255
WORD2バイト0〜65535
DWORD4バイト0〜4294967295
UINT4バイト0〜4294967295
FLOAT4バイト10-38〜1038(有効桁7桁)
DOUBLE8バイト10-308〜10308(有効桁15桁)
VOID
未知の型・型なし
BOOL4バイト-2147483648〜2147483647,真偽等を返す時に利用
HWND(HANDLE)4バイトウィンドウハンドル
COLORREF4バイトRGB輝度が入る
この他に実に様々な型があるわけですが、適当に付けられているわけではなく、 接頭語・接尾語をつけることでその型の××と言うものが多いと思います。 例えば「H〜」は大半が「〜のハンドル」です。(ハンドル以外はHOOKPROCというものしか知りません) ハンドルと言うのは車などについているレバーのことです。ココでいうハンドルはまた違いますが。 何らかの要素を識別するための重複しない固有の(個別に割り当てられた)識別子のことです。 「LP〜」,「P〜」は私の知る限りでは全部「ポインタ型の〜」。LPはfar、Pはnearポインタだと思います。 ポインタはプログラムを始めた人が躓くことの多い難関のことです。 データが格納された位置(アドレス)を示す変数のことです。スクリプト内のラベルのような役割ですね。 ポインタ型はデータのアドレスだけを入れておくのでデータ型に関係なくすべて4バイトです。 つまりBYTEやLONGのポインタ型のサイズは同じである、と言うことです。 「U〜」はすべて「符号なし(unsigned)の〜型」。コレも自分の知っている限りのものでは、の話です。 「〜STR」は「〜の文字列を指す(ポインタ)」だと思います。 コレや後述のPROCに付くポインタはオマケですがポインタばかりでしたので…。 「〜PROC」は「〜プロシージャ(procedure)を指す(ポインタ)」かと…。 先ほどのデータ取得・設定は2バイト(SHORT等)の例でしたが BYTE等の1バイトのものでもやり方は同じでビットシフト量が変わるだけですね。 Tipsにあるバッテリ情報の取得モジュールでは、 Kernel32.dllの「GetSystemPowerStatus」というAPI関数が使用されています。 その関数は下記の方法で取得が出来ると書かれています(APIのページ等での話)。 APIの書式は「GetSystemPowerStatus( lpSystemPowerStatus As SYSTEM_POWER_STATUS )」で 「SYSTEM_POWER_STATUS」というのが引数(パラメータ)の型なのですが、 コレはパラメータ1つを指定するのではなくデータ型が複数集まったモノ(構造体)を指定します。 この「SYSTEM_POWER_STATUS」構造体を紹介しているページを見ると次のように書かれています。
Type SYSTEM_POWER_STATUS ACLineStatus As Byte BatteryFlag As Byte BatteryLifePercent As Byte Reserved1 As Byte BatteryLifeTime As Long BatteryFullLifeTime As Long End Type
で、この引数が戻り値にもなり、構造体に取得したデータが入ります。 と、何やら難しそうなことが書かれています。 ココで見ていただきたいものは各行の「〜 As」と書かれた後の文字列です。 「Byte,Byte,Byte,Byte,Long,Long」と先ほど解説した型が並んでいますね。 ソコで少し前に説明した1つの変数に複数データを入れるやり方が必要となって来るわけです。 Longは4バイトでHSPでの数値型変数と同じサイズですので複数入れることはありませんが、 Byteは1バイトで、その型が4つ並んでいますので4つのByte型で1つの数値型変数を使用します。 バッテリ情報の取得モジュールを見ていただければ載っているのですがココにも書いておきます。 まず、上記6つのデータ型をまとめた構造体分のメモリサイズを確保します。 「Byte(1バイト)4つ×Long(4バイト)2つ=12バイト=数値型変数3つ分」ですので、
	dim prm,3 // 宣言しなくても要素数16なのでなくても問題ないがメモリ節約のため
コレで構造体分のメモリは確保できました。 簡単ですね。 それでは戻り値として構造体に入ると書かれていますので入っているとしてデータを取り出してみましょう。 初めの4バイトに4つ入ってますので取得にはpeek命令を使用します(構造体変数名をdataとします)。
	peek aclinestatus, data.0 & $ff // 1つ目のByte
	peek batteryflag,data.0 >> 8 & $ff // 2つ目のByte
	peek batterylifepercent, data.0 >> 16 & $ff // 3つ目のByte
	peek reserved, data.0 >> 24 & $ff // 4つ目のByte
	batterylifetime = data.1 // 1つ目のLong
	batteryfulllifetime = data.2 // 2つ目のLong
1バイト=8ビットなので、0〜7,8〜15,16〜23,24〜31にそれぞれが入るわけですね。 5バイト(8バイト)以上の型を指定することがありますけど指定する機会があるのはほぼ構造体だけです。 先ほどのように1が4つ、4が2つという順番で並んでいるのならやりやすいのですけど、 例えば配列変数dataに「Byte,Byte,Long,Long,Byte,Byte」の順番だと取得・設定が少し面倒ですね。 初めの4バイト内の下位2バイトは1バイト2つで、上位2バイトが4バイトの型の下位2バイト分だけ、 そして次の4バイトの下位2バイトが先ほどの4バイトの型の上位2バイト分で…となっているわけです。 早口言葉みたいになってしまいます。面倒ですけどこんな方法しかないので頑張ってください。 イメージ的には下記のような感じでしょうか。
data.0data.1data.2
B
Y
T
E
B
Y
T
E
L
O
N
G
L
O
N
G
B
Y
T
E
B
Y
T
E