HSP3 あれこれ <オブジェクト編 1>

Last Update : 2006/10/xx

◇ ボタン (button命令) / チェックボックス (chkbox命令)

 button命令とchkbox命令。見た目はぜんぜん違いますが、どちらも「ボタンコントロール」に分類されてます。ボタンの見た目を変えただけなのがチェックボックスであり、他にもラジオボタンやグループボックスがこのグループに含まれてます。

 このオブジェクトに関する基礎的な情報は、button命令の解説chkbox命令の解説のページを参照してください。

^

ボタンのウィンドウスタイル変更

 Win32 API関数を利用して、button命令で設置できるボタンオブジェクトの見た目(=ウィンドウスタイル)を変更してみるサンプルです。通常は、ボタンの中央にある文字列の表示位置を変更したり、文字列を複数行で表示することが可能です。(ウィンドウスタイルについては、ちょくとさんのページを参照)

 現在のボタンのウィンドウスタイルをGetWindowLong関数で取得し、それにプラスした新たなウィンドウスタイルを SetWindowLong関数で指定してやります。ボタンのウィンドウハンドルを取得するのにobjinfo関数を利用します。

#uselib "user32"
#cfunc GetWindowLong "GetWindowLongA" int, int
#func SetWindowLong "SetWindowLongA" int, int, int

	objsize 200, 40

	button "枠強調ボタン", *a
	hButton = objinfo(stat, 2)

;	ウィンドウスタイルの変更
;	太枠の強調ボタン($1)
	SetWindowLong hButton, -16, GetWindowLong (hButton, -16) | $1

*a

 さて、厳密にやると上のようになりますが、HSPに登場するボタンのウィンドウスタイルは、あらかじめ「WS_CHILD + WS_VISIBLE = $50000000」と分かっているので、GetWindowLong関数の部分は省略しても問題ないでしょう。

;	ボタンのウィンドウスタイル変更サンプル (by Kpan)

#uselib "user32"
#func SetWindowLong "SetWindowLongA" int, int, int

	objsize 200, 40

;	これは標準のボタン
	button "ふつーのボタン", *jump

;	太枠強調ボタン (BS_DEFPUSHBUTTON)
	button "枠強調ボタン (SetWindowLong)", *jump
	SetWindowLong objinfo(stat, 2), -16, $50000000 | $1

;	太枠強調はsendmsg命令だけで実現可
	button "枠強調ボタン (sendmsg)", *jump
	sendmsg objinfo(stat, 2), $F4 , $1

;	テキスト表示位置の変更 (BS_LEFT/BS_RIGHT/BS_TOP/BS_BOTTOM)
;	$100=左寄り、$200=右寄り、$400=上寄り、$800=下寄り
;	複数個組み合わせれば「左下」に表示
	button "テキスト位置変更ボタン", *jump
	SetWindowLong objinfo(stat, 2), -16, $50000000 | $100 | $800

;	複数行テキスト・縦書き表示風にも (BS_MULTILINE)
;	ボタンに収まるよう文字列を自動改行 (「\n」で手動改行)
	button "複数行\nボタン", *jump
	SetWindowLong objinfo(stat, 2), -16, $50000000 | $2000

;	フラットスタイルのボタン (BS_FLAT)
;	Windows XP以降のビジュアルスタイル時は変化なし
	button "フラットボタン", *jump
	SetWindowLong objinfo(stat, 2), -16, $50000000 | $8000

	stop

*jump

 このサンプルを元にしたボタンのウィンドウスタイルを変更するモジュールは、このページの最下部よりダウンロードできます。モジュールにしなければならないほど複雑なスクリプトではありませんが・・・ (^^;

^

チェックボックスのウィンドウスタイル変更

 Win32 API関数を利用して、chkbox命令で設置できるチェックボックスのウィンドウスタイルを変更してみるサンプルです。ボタンのウィンドウスタイル変更処理と同じです。

 上のボタンのウィンドウスタイル変更にもあるように、現在のチェックボックスのウィンドウスタイルを取得し、それにプラスした新たなウィンドウスタイルを適用してやるわけですが、HSPに登場するチェックボックスのウィンドウスタイルは、「WS_CHILD + WS_VISIBLE + BS_AUTOCHECKBOX = $50000003」となっているので、GetWindowLong関数は省略します。

;	チェックボックスのウィンドウスタイル変更サンプル (by Kpan)

#uselib "user32"
#func SetWindowLong "SetWindowLongA" int, int, int

	objsize 150, 40

	chkbox "ふつー", x

	chkbox "右側にチェック項目", x
	SetWindowLong objinfo(stat, 2), -16, $50000003 | $20

;	$100=左寄り、$200=右寄り、$400=上寄り、$800=下寄り。
;	複数個組み合わせて「右上」に。
	chkbox "位置変更", x
	SetWindowLong objinfo(stat, 2), -16, $50000003 | $200 | $400

;	チェックボックスに収まるよう文字列を自動改行 (「\n」で手動改行)
	chkbox "複数行\nですー", x
	SetWindowLong objinfo(stat, 2), -16, $50000003 | $2000

;	フラットスタイル (Windows XP以降のビジュアルスタイル適用時は変化なし)
	chkbox "フラット", x
	SetWindowLong objinfo(stat, 2), -16, $50000003 | $8000

 このサンプルを元にしたチェックボックスのウィンドウスタイルを変更するモジュールは、このページの最下部よりダウンロードできます。モジュールにしなければならないほど複雑なスクリプトではありませんが・・・ (^^;

^

チェックボックスの監視

 チェックボックスというのは、内部的にはボタンオブジェクトです。HSPのbutton命令は、押した時にラベルにジャンプする機能を持っています。これをうまく利用して、チェックボックスのチェックの有無をリアルタイムで監視してみることにしましょう。

 下のサンプルは、チェックボックスにチェックが入っていると、他のオブジェクトが使用可能な状態(有効)になり、入っていないと、グレー表示の使用不可な状態(無効)になる、というスイッチ処理が行われます。

 オブジェクトの有効/無効の切り替えは、Win32 API関数のEnableWindow関数を使います。HSP2のllmod.asモジュール(obj.as)に「objgray命令」が用意されてましたが、この関数を呼び出していただけです。HSP3でも common\obj.as モジュール内に同じ命令が用意されています。

;	チェックボックス監視サンプル (by Kpan)

#uselib "user32"
#func EnableWindow "EnableWindow" int, int

;	普通にボタンを作成
	button "チェック", *check
	hButton.0 = objinfo(stat, 2)

;	ボタンのウィンドウスタイルを変更してチェックボックス化
	sendmsg hButton.0, $F4, $3

;	チェックボックスにチェックを入れる (BM_SETCHECK)
;	第3パラに 0=チェックあり、1=チェックなし
;	標準のobjprm命令は利用できません
	sendmsg hButton.0, $F1, 1

	pos , 50
	input x
	combox y, , "HSP\n講座\nプログラミング\nサンプル"

	stop

*check
;	チェックボックスの状態を取得 (BM_GETCHECK)
;	statに 0=チェックなし、1=チェックあり が返ります
	sendmsg hButton.0, $F0
	title ""+stat

;	オブジェクトの使用可/使用不可の切り替え
	if stat {
;		第2パラが1だとオブジェクトが有効に
		EnableWindow objinfo(1, 2), 1
		EnableWindow objinfo(2, 2), 1
	} else {
;		第2パラが0だとオブジェクトが無効に
		EnableWindow objinfo(1, 2)
		EnableWindow objinfo(2, 2)
	}

 ちなみに、入力ボックスとメッセージボックスについては、EnableWindow関数を使わず、sendmsg命令だけで有効無効の切り替えが可能です。(→入力ボックスの編集無効 を参照)

^

3ステートチェックボックス の作成

 chkbox命令には、「チェックあり」と「チェックなし」の2つの状態が存在しますが、ここにもう1つ「不確定」の状態を加えた3つの状態を持つチェックボックスの作成です。sendmsg命令でウィンドウスタイルを変更してやります。

 3つ目の状態は、チェックありのグレー表示(Windows XP以降のビジュアルスタイル適用時は四角いチェックマーク)で表現されます。注意点として、チェックボックスのデフォルト状態を指定するのに、通常ではあらかじめchkbox命令の状態保持変数に1を指定しておきますが、グレー表示の状態は指定できないのでsendmsg命令を使います。

;	3ステートチェックボックス作成サンプルソース (by Kpan)

;	a = 1 ; OK チェックあり、になります
;	a = 2 ; × グレー表示チェックありにならず

	chkbox "3ステート", a

;	3ステートチェックボックス化
	sendmsg objinfo(stat, 2), $F4, $6

;	objprm 0, 1 ; OK
;	objprm 0, 2 ; ×
;	なので、グレー表示に変更したい場合 (BM_SETCHECK)
//	sendmsg objinfo(0, 2), $F1, 2
//	a = 2 ; これも必要

	button "チェック!", *check
	stop

*check
;	0=チェックなし、1=チェックあり、2=グレー表示チェックあり が返る
	mes a

^

トグルボタン の作成

 button命令で作成したボタンは、マウスをクリックするとへこんで、離すと元の状態に戻る、という動きをします。ここでは、押した直後にへこんだまま、それを押すと元の状態に戻る、という2段階の動きをするトグルボタンを作成してみます。

 で、実際使うのはボタンではなく、チェックボックスを利用します。チェックボックスに「チェックが入っている=ボタンがへこんでいる」、「チェックが入っていない=ボタンが膨らんでいる」、という考え方です。

 Win32 API関数のSetWindowLong関数を利用して、チェックボックスのウィンドウスタイルを変更(BS_PUSHLIKE)してやります。

;	トグルボタン作成サンプルソース1 (by Kpan)

#uselib "user32"
#func SetWindowLong "SetWindowLongA" int, int, int

;	チェックボックスの状態保持変数に1を入れるとチェックが入る、つまり
;	へこみボタンになります。設置後のオン/オフ制御は、普通にobjprm命令を利用。
	c2 = 1

	chkbox "第壱番", c1
	SetWindowLong objinfo(stat, 2), -16, $50000003 | $1000

	chkbox "第弐番", c2
	SetWindowLong objinfo(stat, 2), -16, $50000003 | $1000

	pos , 100

	button "御確認", *check
	stop

;	状態の確認。普通にチェックボックスの状態保持変数を確認しませう。
;	0=チェックなし(膨らんでいる)、1=チェックあり(へこんでいる)
*check
	title ""+c1+" / "+c2

 このサンプルを元にしたトグルボタンの作成モジュールは、このページの最下部よりダウンロードできます。モジュールにしなければならないほど複雑な処理は必要ありませんが。(^ー^;

;	トグルボタン作成サンプルソース2 (by Kpan)
;	button命令を利用した手法 (リアルタイムで動きを確認したい場合)

#uselib "user32"
#func SetWindowLong "SetWindowLongA" int, int, int

	button "OFF", *jump
	SetWindowLong objinfo(stat, 2), -16, $50000003 | $1000

	stop

*jump
	if check {
		data = "OFF"
	} else {
		data = "ON"
	}
	objprm 0, data

	check ^ 1
	title ""+check

^

画像ボタン の作成

 ボタンにビットマップを貼り付ける画像ボタン(イメージボタン)の作成です。HSP2では、llmod.asモジュールを利用してビットマップを貼り付けるbtnimg命令を利用する、あるいはマウスの動きを監視して、擬似的なボタン風処理を自分で作ってしまう方法があります。(→参照、llmod3HSP開発wiki)

 ここではボタンに貼り付けるビットマップファイルを実行ファイル内にリソースとして埋め込むという、HSP的には特殊な手法で行います(めんどくさい!&イレギュラー!)。リソースエディタ「Resource Hacker」を別途用意してください。

  1. 後に実行ファイルとなる hsprt、または runtime フォルダの *.hrt をリソースエディタで読み込みます。[アクション]メニューの[新しいリソースを追加する]を選択し、ビットマップファイル(*.bmp)を1つ選択します。
  2. [リソースの種類]には自動的に「BITMAP」が入ります。[リソース名]は適当な任意の数値(例として1)を、[リソースの言語]は適当に「1033」と入力します。そして、[リソースを追加する]ボタンを押します。
  3. [ファイル]メニューの[名前を付けて保存する]で、必ず任意のファイル名で保存します。拡張子は *.hrt で、例として hogehoge.hrt とします。このファイルは runtimeフォルダ に置いておいてください。

 これで下準備が完了。1つのボタン用に1つのビットマップファイルを用意することになります。HSPのPACKFILE機能は利用しません。下が埋め込んだ画像を利用するためのコードです。モジュール+サンプルの形式になっています。

;	ボタンにビットマップを貼り付けるモジュール (by Kpan)
#module

#uselib "user32"
#cfunc LoadImage "LoadImageA" int, int, int, int, int, int
#func SetWindowLong "SetWindowLongA" int, int, int

#uselib "gdi32"
#func DeleteObject "DeleteObject" int

;	SetBitmap p1, p2
;		p1=ボタンのオブジェクトID
;		p2=[リソース名]で指定した任意の数値
#deffunc SetBitmap int p1, int p2
	hButton = objinfo (p1, 2)
	SetWindowLong hButton, -16, $50000000 | $80

	hBitmap.i = LoadImage (hinstance, p2, , , , )
	if hBitmap.i = 0 : return
	sendmsg hButton, $F7, , hBitmap.i

	i++
	return

;	ビットマップの開放
;		(※自動的に行われるので呼び出し不要)
#deffunc DelBitmap onexit
	repeat i
		DeleteObject hBitmap.cnt
	loop
	return

#global

;	以下、サンプル

;	画像を埋め込んだランタイムファイルをパックオプションで指定
#packopt runtime "hogehoge.hrt"

	objsize 200, 100

;	表示文字列は指定しても意味ないので無指定
	button "", *dummy

;	貼り付け。ボタンのオブジェクトID、「リソース名」の数値を指定。
	SetBitmap stat, 1

	stop

*dummy

 で、これをスクリプトエディタ上でコンパイル実行しても、ボタンに何の変化も現れません。これは実行ファイルにならないと効果を確認できない代物です。また、ビットマップの貼り付けに失敗しても別にエラーはでません。[実行ファイル自動作成]で実行ファイルを出力して、動作確認してください。

※注意: ビットマップを貼り付けたボタンは、Windows XP環境のXPスタイル適用下でも必ずクラシックスタイルで表示される仕様になっています。

^

ラジオボタンの作成

 ラジオボタン(別名、オプションボタン/ラジオボックス)の作成です。ラジオボタンというのは、複数用意されている丸い形状の項目から1つだけ選択できるものです。HSPの標準命令には存在しないオブジェクトですが、内部的にはボタンコントロールの見た目を変えたにすぎません。

 ここでは、HSPでのラジオボタン作成法としてよく紹介されていたbutton命令を使わず、chkbox命令のウィンドウスタイルを変更する新手法を紹介します。

;	状態保持変数に1を入れたチェックボックス(ラジオボタン)に
;	黒丸チェックが入ります。ここでは2番目。
	s2 = 1

	chkbox "あ", s1
	sendmsg objinfo(stat, 2), $F4, $9

	chkbox "い", s2
	sendmsg objinfo(stat, 2), $F4, $9

	chkbox "う", s3
	sendmsg objinfo(stat, 2), $F4, $9

 さて、上のようにサクっと表示できたスクリプトですが、これはウィンドウ上にラジオボタンのグループが1つしか存在しない時だけ有効で、このまま同じ処理を繰り返しても、ただ単に選択肢がどんどん増えていくだけです。

 もし、ラジオボタンのグループが複数ある場合は、1つの方法として「グループ化」という処理を利用します。グループの1番最初のチェックボックスは、ラジオボタン化($50000000+$9)するついでに、グループ化宣言($20000)を行う必要があるので、SetWindowLong関数を呼びます。それ以降は、普通にsendmsg命令でラジオボタン化($9)します。

 グループ化を宣言したオブジェクトから、次にグループ化を宣言するオブジェクトの直前までを1つのグループと判断してくれます。

;	ラジオボタン表示サンプルスクリプト (by Kpan)

#uselib "user32"
#func SetWindowLong "SetWindowLongA" int, int, int

;	1番目のグループ
	x1 = 1

	chkbox "あ", x1
	SetWindowLong objinfo(stat, 2), -16, $50000009 | $20000

	chkbox "い", x2
	sendmsg objinfo(stat, 2), $F4, $9

	chkbox "う", x3
	sendmsg objinfo(stat, 2), $F4, $9

;	2番目のグループ
;	これにより、上とは別動作になるのであーる
	pos , 80
	y3 = 1

	chkbox "I", y1
	SetWindowLong objinfo(stat, 2), -16, $50000009 | $20000

	chkbox "II", y2
	sendmsg objinfo(stat, 2), $F4, $9

	chkbox "III", y3
	sendmsg objinfo(stat, 2), $F4, $9

;	3番目のグループ
;	トグルボタン型($1000)ラジオボタン(チェックあり=へこみボタン)
	pos , 160
	z2 = 1

	chkbox "A", z1
	SetWindowLong objinfo(stat, 2), -16, $50000009 | $1000 | $20000

	chkbox "B", z2
	SetWindowLong objinfo(stat, 2), -16, $50000009 | $1000

	chkbox "C", z3
	SetWindowLong objinfo(stat, 2), -16, $50000009 | $1000

	pos , 250
	button "チェック!", *check

	stop

;	チェックのあるラジオボタンを取得 (もっとスマートな確認手段は・・・)
;	1つ1つのオブジェクトのチェックの有無を確認。
;	statに1が返ると「チェックあり」ということで、そのオブジェクトIDを表示。
*check
;	グループ1用
	repeat 3, 0
		sendmsg objinfo(cnt, 2), $F0
		if stat : mes cnt
	loop

;	グループ2用
	repeat 3, 3
		sendmsg objinfo(cnt, 2), $F0
		if stat : mes cnt
	loop

;	グループ3用 (トグルボタン型)
	repeat 3, 6
		sendmsg objinfo(cnt, 2), $F0
		if stat : mes cnt
	loop

 このサンプルを元にしたHSP3向けラジオボタンの作成モジュールを、このページの一番下にて公開中。

^

グループボックスの作成?

 グループボックス(四角い枠)の作成です。HSPの標準命令にはありませんが、グループボックスというのはボタンの見た目を変えただけです。以下のサンプルは、あくまでグループボックス自体が表示されるだけです。HSPにはグループボックスのサンプルコード (sample\basic\groupbox.hsp) が一応用意されていますが、オブジェクト内の表示が化けるバグ(?)があります。

※注意!!!
 以下のサンプルは、OSやら環境やらで表示の挙動が異なり、オブジェクトが置くとおかしくなるためダメダメ。HSP2時代からグループボックスはどーもこーもいかない・・・? (*_*;

;	まったく使えーんよ。。。失敗例

#uselib "user32"
#cfunc GetWindowLong "GetWindowLongA" int, int
#func SetWindowLong "SetWindowLongA" int, int, int

;	ポイント!? 表示化けの原因であるウィンドウの 「WS_CLIPCHILDREN」
;	スタイル を取り除く処理を Windows API 使って行います。
	SetWindowLong hwnd, -16, GetWindowLong (hwnd, -16) ^ $2000000

;	普通にグループボックスの位置と大きさ
	pos 10, 10
	objsize 200, 100

;	ボタンではなくチェックボックスを使う。(xはダミー変数)
	chkbox "グループボックスでっせ!", x
;	グループボックスに変更。objinfo関数 の第1パラにオブジェクトID。
	sendmsg objinfo(stat, 2), $F4, $7

;	[おまけ] グループボックスの表示文字列の位置を変更したものを作成
;	したい場合は、sendmsg命令 は使えません。$200=右端、$300=中央。
	chkbox "ここの位置ね", x
	SetWindowLong objinfo(stat, 2), -16, $50000007 | $200

 というわけで、オブジェクトではないですが、グループボックス「風」の枠を描画するモジュールをこのページ最下部からダウンロードできます。(素直にline命令で、線を1本1本描画してもいいところを、わざわざWin32 API関数で・・・ ^ー^;

^

☆ 関連HSP用モジュール

 このページで紹介しているいくつかのサンプルスクリプトに基づいたモジュールです。ボタンとチェックボックスのウィンドウスタイル変更、トグルボタン作成、ラジオボタン作成、グループボックス「風」の枠表示、の4ファイルを含んでいます。(HSP 3.x用)

ダウンロード (オブジェクト編 1)

^

<< オブジェクト編 9 | HSP3 オブジェクト | オブジェクト編 2 >>

Copyright © 2005-2008 Kpan. All rights reserved.