
今回は、ツールバーのボタンの状態を取得したり設定したりしてみましょう。これらの作業はすべてツールバーにメッセージを送ることによって行なうことができます。
ツールバーのボタンの状態を取得するには、ツールバーに TB_GETSTATE メッセージを送信します。
#define TB_GETSTATE 0x0412
TB_GETSTATE
wParam = idButton;
lParam = 0;
idButton パラメータには、状態を取得するツールボタンのコマンドIDを指定します。このメッセージを送ると、戻り値として指定されたボタンの現在の状態が取得されます。ボタンの状態には例として以下のようなものがあり、状態はこれらの値の組み合わせで取得されます。
| 値 | 意味 |
|---|---|
| 0x01 (TBSTATE_CHECKED) | ボタンが TBSTYLE_CHECK スタイルを持っていて、押されている状態。 |
| 0x02 (TBSTATE_PRESSED) | ボタンが押されている状態。 |
| 0x04 (TBSTATE_ENABLED) | ボタンが使用可能な状態。この状態が指定されていない場合はボタンは灰色表示になり、使用不可になります。 |
| 0x08 (TBSTATE_HIDDEN) | ボタンが見えない状態。ユーザーからの入力を受け付けません。 |
| 0x10 (TBSTATE_INDETERMINATE) | ボタンが灰色表示の状態。 |
| 0x20 (TBSTATE_WRAP) | ボタンを次の行に表示。TBSTATE_ENABLED が同時に指定されている必要があります。 |
ボタンの状態を設定するには、ツールバーに TB_SETSTATE メッセージを送ります。
#define TB_SETSTATE 0x0411
TB_GETSTATE
wParam = idButton;
lParam = fState;
idButton パラメータには、状態を取得するツールボタンのコマンドIDを、 fState パラメータには設定する状態を指定します。状態は上の表で示した値の組み合わせで指定します。
状態の設定は、それぞれの属性に対してのみ行なうこともできます。例えば、ボタンの表示・非表示を設定したり、有効・無効を設定したりすることができます。
ボタンの表示・非表示を設定するには、ツールバーに TB_HIDEBUTTON メッセージを送ります。
#define TB_HIDEBUTTON 0x0404
TB_HIDEBUTTON
wParam = idButton;
lParam = fHide;
idButton パラメータには、表示・非表示の状態を設定するツールボタンのコマンドIDを、 fHide パラメータには、ボタンを表示する場合は 0 (FALSE) を、非表示にする場合は 1 (TRUE) をそれぞれ指定します。
ボタンを押せないように無効にしたり、逆に有効にしたりするには、ツールバーに TB_ENABLEBUTTON メッセージを送ります。
#define TB_ENABLEBUTTON 0x0401
TB_ENABLEBUTTON
wParam = idButton;
lParam = fEnable;
idButton パラメータには、有効・無効の状態を設定するツールボタンのコマンドIDを、 fEnable パラメータには、ボタンを有効にする場合は 1 (TRUE) を、無効にする場合は 0 (FALSE) をそれぞれ指定します。無効にすると、ボタンが灰色表示になってユーザーはボタンを押すことができなくなります。
ボタン追加時にボタンのスタイルに 0x0002 (TBSTYLE_CHECK スタイル) を指定してある場合、ボタンが押されている状態と押されていない状態とを切りかえることができます。この設定をするには、ツールバーに TB_CHECKBUTTON メッセージを送ります。
#define TB_CHECKBUTTON 0x0402
TB_CHECKBUTTON
wParam = idButton;
lParam = fCheck;
idButton パラメータには、状態を設定するツールボタンのコマンドIDを、 fCheck パラメータには、ボタンを押された状態にする場合は 1 (TRUE) を、押されていない状態にする場合は 0 (FALSE) をそれぞれ指定します。
さて、実際にスクリプトを書いてみます。今回のサンプルはちょっとパズルゲーム感覚のものにしてみました。
スクリプト中では、ボタンの状態を取得・変更するのに TB_GETSTATE メッセージと TB_ENABLEBUTTON メッセージを使用しています。
今回使用する画像ファイルは、前に使用したのと同じものを使います。このビットマップファイルは、それぞれのイメージサイズが 16×15 ピクセル、イメージ数が9個、背景色の白色がパレットコードの 0 になるように作られた256色ビットマップファイルです。
(toolbtn.bmp)
今回は、ビットマップオブジェクトの作成と、ツールバーの操作の部分をモジュール命令として定義してあります。
#include "llmod.as"
#include "hsgetmsg.as"
#module ;####### ビットマップオブジェクト作成モジュール #########
;===============================================================
; 描画中ウィンドウのイメージからビットマップオブジェクト作成
; CreateBitmap p1, p2, p3, p4
; p1 : HSPウィンドウx座標
; p2 : HSPウィンドウy座標
; p3 : 幅
; p4 : 高さ
; stat : ビットマップのハンドルが返る
;===============================================================
#deffunc CreateBitmap int, int, int, int
mref px, 0 ; HSPウィンドウx座標
mref py, 1 ; HSPウィンドウy座標
mref sx, 2 ; xサイズ
mref sy, 3 ; yサイズ
mref stt, 64 ; stat
mref bmscr, 67 ; 描画中ウィンドウのBMSCR構造体
; ディスプレイのデバイスコンテキストのハンドル取得
devname = "DISPLAY"
pm = 0,0,0,0
getptr pm, devname ; "DISPLAY"のアドレス
dllproc "CreateDCA", pm, 4, D_GDI@
hdcScreen = stat ; ディスプレイのデバイスコンテキスト
; ディスプレイ互換ビットマップオブジェクト作成
pm = hdcScreen, sx, sy
dllproc "CreateCompatibleBitmap", pm, 3, D_GDI@
hbitmap = stat ; ビットマップオブジェクトのハンドル
; ディスプレイ互換デバイスコンテキスト作成
pm = hdcScreen
dllproc "CreateCompatibleDC", pm, 1, D_GDI@
hdcMemory = stat ; メモリデバイスコンテキストのハンドル
; ビットマップをデバイスコンテキストに選択
pm = hdcMemory, hbitmap
dllproc "SelectObject", pm, 2, D_GDI@
; HSPウィンドウからビットマップにイメージをコピー
pm = hdcMemory, 0, 0, sx, sy, bmscr.4, px, py, $CC0020
dllproc "BitBlt", pm, 9, D_GDI@
; デバイスコンテキストを削除
dllproc "DeleteDC", hdcMemory, 1, D_GDI@
dllproc "DeleteDC", hdcScreen, 1, D_GDI@
stt = hbitmap ; ビットマップオブジェクトのハンドル
return
#global ;############# モジュール終わり ########################
#module ;########### ツールバー操作モジュール ##################
;===============================================================
; ツールバー作成
; CreateToolbar p1, p2
; p1 : ボタンイメージの幅 (0のとき16ピクセル)
; p2 : ボタンイメージの高さ (0のとき15ピクセル)
; stat : ツールバーのハンドルが返る
;===============================================================
#deffunc CreateToolBar int, int
mref sx, 0 ; ビットマップの数
mref sy, 1 ; ビットマップオブジェクトのハンドル
mref stt, 64 ; stat
; コモンコントロールライブラリ初期化
dllproc "InitCommonControls", pm, 0, D_COMCTL@
; ツールバー作成
pm = 0, 0, 0, 0 ; 座標・サイズは 0 でよい
pm.4 = 0x50000001 ; WS_CHILD | WS_VISIBLE | CCS_NORESIZE
pm.5 = 0, 0
_makewnd pm, "ToolbarWindow32"
hTool = pm ; ツールバーのハンドル
; TB_BUTTONSTRUCTSIZE メッセージ送信
pm = hTool, 0x041E, 20, 0
sendmsg pm
; ビットマップのサイズを設定
if sx == 0 : sx = 16
if sy == 0 : sy = 15
; TB_SETBITMAPSIZE メッセージ送信
pm = hTool, 0x420, 0, sx | (sy << 16)
sendmsg pm
stt = hTool ; stat にツールバーのハンドルを格納
return
;===============================================================
; 描画中ウィンドウのイメージをツールバーに加える
; (パレットモードであること・パレットインデックス 0 は透過色)
; (イメージが複数のときは横に並べられていること)
; AddToolBitmap p1, p2
; p1 : ツールバーのハンドル
; p1 : HSPウィンドウx座標
; p2 : HSPウィンドウy座標
; p3 : 幅
; p4 : 高さ
; stat : 最初のイメージのインデックスが返る
;===============================================================
#deffunc AddToolBitmap int, int, int, int, int
mref hTool, 0 ; ツールバーのハンドル
mref px, 0 ; HSPウィンドウx座標
mref py, 1 ; HSPウィンドウy座標
mref sx, 2 ; 高さ
mref sy, 3 ; 幅
mref stt, 64 ; stat
; パレット 0 をシステムカラーのボタン表面色に変更
pm = 15 ; COLOR_BTNFACE
dllproc "GetSysColor", pm, 1, D_USER@
palette 0, stat&$FF, (stat>>8)&$FF, (stat>>16)&$FF
palfade
; ビットマップオブジェクト作成
CreateBitmap 0, 0, winx, winy
hbitmap = stat ; ビットマップのハンドル
; ビットマップをボタンイメージのリストに追加
; TBADDBITMAP 構造体
tbadd.0 = 0
tbadd.1 = hbitmap ; ビットマップハンドル
;TB_ADDBITMAPメッセージを送信
pm = hTool, 0x0413
pm.2 = 9 ; ビットマップ中のボタンイメージの数
getptr pm.3, tbadd ; TBADDBITMAP 構造体のアドレス
sendmsg pm
index = stat
; ビットマップオブジェクトを削除
dllproc "DeleteObject", hbitmap, 1, D_GDI@
stt = index
return
;===============================================================
; ボタンを1個追加
; AddToolButton p1, p2, p3, p4, p5
; p1 : ツールバーのハンドル
; p2 : ボタンのイメージのインデックス
; p3 : コマンドID
; p4 : ボタンの状態(使用可能ボタンは4が必要)
; p5 : ボタンスタイル
;===============================================================
#deffunc AddToolButton int, int, int, int, int
mref hTool, 0 ; ツールバーのハンドル
mref index, 1 ; ボタンのイメージのインデックス
mref idCmd, 2 ; コマンドID
mref fsState, 3 ; ボタン状態
mref fsStyle, 4 ; ボタン
; TBBUTTON 構造体
tbb.0 = index ; ボタンのイメージのインデックス
tbb.1 = idCmd ; コマンドID
tbb.2 = fsState | (fsStyle << 8) ; ボタン状態・スタイル
tbb.3 = 0
tbb.4 = 0
; TB_ADDBUTTONS メッセージを送信
pm = hTool, 0x0414
pm.2 = 1 ; 追加するボタンの数(1個)
getptr pm.3, tbb ; TBBUTTON 構造体のアドレス
sendmsg pm
; TB_AUTOSIZE メッセージ送信
pm = hTool, 0x0421, 0, 0
sendmsg pm
return
;===============================================================
; ボタンのスタイル取得
; GetToolState p1, p2
; p1 : ツールバーのハンドル
; p2 : コマンドID
; stat : 取得したスタイルが返る
;===============================================================
#deffunc GetToolState int, int
mref hTool, 0 ; ツールバーのハンドル
mref cmdID, 1 ; ボタンのコマンドID
; TB_GETSTATE メッセージを送信
pm = hTool, 0x0412, cmdID, 0
sendmsg pm
return
;===============================================================
; ボタンの有効・無効を設定
; EnableToolButton p1, p2, p3
; p1 : ツールバーのハンドル
; p2 : コマンドID
; p3 : 1:有効 0:無効
;===============================================================
#deffunc EnableToolButton int, int, int
mref hTool, 0
mref cmdID, 1
mref fEnable, 2
; TB_TB_ENABLEBUTTON メッセージを送信
pm = hTool, 0x0401, cmdID, fEnable
sendmsg pm
return
;===============================================================
; ツールバーの高さを取得
; GetToolHeight p1
; p1 : ツールバーのハンドル
; stat : ツールバーの高さが返る
;===============================================================
#deffunc GetToolHeight int
mref hTool, 0 ; ツールバーのハンドル
mref stt, 64 ; stat
pm.0 = hTool ; ツールバーのハンドル
getptr pm.1, rect ; RECT 構造体のアドレス
dllproc "GetWindowRect", pm, 2, D_USER@
stt = rect.3 - rect.1 ; 高さを求める
return
#global ;############# モジュール終わり ########################
screen 0, 250, 130
; ツールバーの作成
CreateToolbar 16, 15 ; イメージのサイズ 16×15
hTool = stat ; ツールバーのハンドル
; ボタンイメージ
buffer 2,,,1 ; パレットモードで初期化
picload "toolbtn.bmp" ; パレットインデックス 0 が透過色
AddToolBitmap hTool, 0, 0, 16*5, 15
; 5個のボタンを追加(コマンドID = 1000〜1004)
repeat 5
AddToolButton hTool, cnt, 1000+cnt, 4
loop
; ウィンドウのサブクラス化
gsel 0
set_subclass ; サブクラス化
hwnd = stat ; メインウィンドウのハンドル
set_message 0x0111 ; WM_COMMAND を取得するように設定
; メッセージパラメータ用変数
dup msg, msgval.1 ; メッセージが格納される変数
dup wprm, msgval.2 ; wParamパラメータが格納される変数
dup lprm, msgval.3 ; lParamパラメータが格納される変数
GetToolHeight hTool ; ツールバーの高さ取得
pos 0, stat
mes {"
すべてのボタンを選択不可の状態
にしてみよう。
ボタンを押すと押されたボタンと
その両側のボタンの選択可・不可
の状態が切り替わります。
"}
cPush = 0 ; ボタンを押した回数
*mainloop
get_message msgval
if msgval == hwnd {
if msg == 0x0111 : gosub *onCommand
} else {
wait 10
}
goto *mainloop
*onCommand
; WM_COMMANDが送られたとき
; ツールバー以外から送られた場合は何もしない
if lprm != hTool : return
cmdID = wprm & 0xFFFF ; 押されたボタンのコマンドID
; ボタン3つの状態(有効・無効)を変化させる
repeat 3
cmdID2 = cmdID + cnt - 1
if cmdID2 < 1000 : cmdID2 += 5
if cmdID2 > 1004 : cmdID2 -= 5
GetToolState hTool, cmdID2
if stat & 0x04 { ; ボタンが有効の時は無効にする
EnableToolButton hTool, cmdID2, 0
} else { ; ボタンが無効の時は有効にする
EnableToolButton hTool, cmdID2, 1
}
loop
cPush++
; すべて無効になったかどうかの確認
flag = 0
repeat 5
GetToolState hTool, 1000+cnt
if stat & 0x04 : flag = 1 : break
loop
if flag == 0 {
dialog "おめでとー!!\nボタンを押した回数 : "+cPush
end
}
return
5つのボタンが最初はすべて有効な状態になっていて、ボタンを押すと、そのボタンとその両側にあるボタン(端のボタンが押された場合は反対側の端のボタンも)の有効・無効の状態が入れ替わるようになっています。すべてのボタンを無効の状態にすることができれば終了です。
最短で7回でできるはずです。