Windows のコントロールを使わず、自分で描画する「マウスでクリックするタイプのボタン」のサンプルです。
これ、 Windows コントロールのボタンと同じような挙動をさせようと思ったら案外ややこしくなるんです。ボタンをクリックし始めたかと思うと、そのままドラッグするような動作をした場合...とか。
このスクリプトの特徴は以下の通り。
oncmd を使ったイベントドリブン形式以前似たような機能をランチャーテンプレで作ったのですが、それにはちょっとした問題がありました。
まず、ボタンにホバーしたままマウスをウィンドウからはみ出させるとホバー状態が保たれたままになってしまう問題です。
これはマウスが動いたことを知らせるメッセージ WM_MOUSEMOVE が、マウスがウィンドウ内でないと送られてこないからでした。しかし、ウィンドウからはみ出たことをメッセージで取得する方法が 2ch に書き込まれていてそこで知りました。
- 371 :名前は開発中のものです。:2007/08/01(水) 23:40:12 ID:6YU1zlws
TrackMouseEvent WM_MOUSELEAVE 辺りをググればおk
#uselib "user32.dll" #func TrackMouseEvent "TrackMouseEvent" int dim tme,4 tme(0) = 16 tme(1) = 2 tme(2) = hwnd tme(3) = 0 oncmd gosub *SUB_WM_MOUSEMOVE,0x200 oncmd gosub *SUB_WM_MOUSELEAVE,0x02A3 stop *SUB_WM_MOUSEMOVE TrackMouseEvent varptr(tme) redraw 0:color 255,255,255:boxf:color:pos 320,240:line mousex,mousey:redraw 1 return *SUB_WM_MOUSELEAVE redraw 0:color 255,255,255:boxf:color:pos 320,240:mes "外に出たよ":redraw 1 return
ゲーム製作技術@2ch掲示板 HSP - Hot Soup Processor [15]より引用。マークアップは作者( fujidig )による。
もう一つの不具合は、カーソルを変更しても実際に変更されるのは「次にマウスが動いたとき」と一テンポ遅れることです。これは原因はよく分かりませんでしたが、カーソルを変更直後に mouse 命令を使えば解決できます。HSP3のスクリプトを垂れ流すブログ: ドラッグできる矩形の表示 に掲載されたスクリプトでそのことを知りました。
解決法が分かったので、モジュール変数を使ったスクリプトを書くのを兼ねて、サンプルを作ってみました。
というわけで、前置きが長くなりましたが以下がそのスクリプトです。
// マウスでクリックするタイプのボタンのサンプル
#include "user32.as"
// 定数
#const global TRUE 0 == 0
#const global FALSE 0 != 0
#const NOT_EXIST_BUTTON_INDEX -1
#module mdlButton rect, text
#modinit int _rectLeft, int _rectTop, int _rectRight, int _rectBottom, str _text
rect = _rectLeft, _rectTop, _rectRight, _rectBottom
text = _text
return
// ボタンの描画
#modfunc drawButton int isHover, int isActive
if isHover == FALSE {
// 通常
color 228, 234, 237
} else : if isActive {
color 201, 213, 219
} else {
color 255, 229, 107
}
boxf rect( 0 ), rect( 1 ), rect( 2 ), rect( 3 )
color
DrawText hDC, varptr( text ), -1, varptr( rect ), 0x0025 // DT_VCENTER | DT_SINGLELINE | DT_CENTER
return
// 座標がボタン内にあるか
#modfunc isPtInButton int x, int y
PtInRect varptr( rect ), x, y
return ( stat != 0 )
#global
if FALSE { // グローバルで命令/関数を定義
// ホバーボタンの取得(値が変更されたかを返す)
#deffunc setHoverButton local isHover, local _hoverButton
_hoverButton = NOT_EXIST_BUTTON_INDEX
foreach buttons
// ホバーしているかの条件
isPtInButton buttons( cnt ), mouseX, mouseY // マウス座標がボタン内にあること
isHover = stat
if isClicking {
// クリック中である場合は加えて、クリック開始時のホバーボタンと同じボタンであること
isHover &= ( clickingStartButton == cnt )
}
if isHover {
_hoverButton = cnt
}
loop
if hoverButton != _hoverButton {
hoverButton = _hoverButton
return TRUE
}
return FALSE
}
// TRACKMOUSEEVENT 構造体
dim tme, 4
tme( 0 ) = 16 // cbSize
tme( 1 ) = 2 // dwFlags = TME_LEAVE
tme( 2 ) = hWnd // hwndTrack
tme( 3 ) = 0 // dwHoverTime
// ウィンドウメッセージの割り当て
oncmd gosub *onLButtonDown, 0x0201 // WM_LBUTTONDOWN
oncmd gosub *onLButtonUp, 0x0202 // WM_LBUTTONUP
oncmd gosub *onMouseMove, 0x0200 // WM_MOUSEMOVE
oncmd gosub *onMouseLeave, 0x02A3 // WM_MOUSELEAVE
hoverButton = NOT_EXIST_BUTTON_INDEX
isClicking = FALSE
clickingStartButton = NOT_EXIST_BUTTON_INDEX
cursor = 0x7F00 // IDC_ARROW
// ボタンの作成
newmod buttons, mdlButton, 100, 100, 200, 120, "ほげ"
newmod buttons, mdlButton, 100, 130, 200, 150, "ぴよ"
newmod buttons, mdlButton, 100, 160, 200, 180, "ふが"
newmod buttons, mdlButton, 300, 80, 500, 300, "でか"
newmod buttons, mdlButton, 580, 180, 680, 250, "はみ"
gosub *drawScreen
stop
// クリック開始
*onLButtonDown
isClicking = TRUE
clickingStartButton = hoverButton
if hoverButton != NOT_EXIST_BUTTON_INDEX {
gosub *drawScreen
}
return
// クリック終了
*onLButtonUp
isClicking = FALSE
if hoverButton != NOT_EXIST_BUTTON_INDEX {
gosub *drawScreen
if clickingStartButton == hoverButton {
dialog str( hoverButton )+"番のボタンを押した"
}
}
return
// ウィンドウ内でのマウスの移動
*onMouseMove
TrackMouseEvent varptr( tme ) // ウィンドウ外に出たときに通知する
getkey isClicking, 1
setHoverButton
if stat { // ホバーボタンの値が変更されていたら
gosub *changeCursor
gosub *drawScreen
}
return
// マウスがウィンドウの外に出た
*onMouseLeave
if hoverButton != NOT_EXIST_BUTTON_INDEX {
hoverButton = NOT_EXIST_BUTTON_INDEX // 無条件でホバー中のボタンはなしに
gosub *changeCursor
gosub *drawScreen
}
return
// 画面の描画
*drawScreen
redraw 0
color 128, 128, 128 : boxf
foreach buttons
drawButton buttons( cnt ), ( hoverButton == cnt ), isClicking
loop
redraw 1
return
// カーソルの変更
*changeCursor
if hoverButton == NOT_EXIST_BUTTON_INDEX {
// IDC_ARROW
if cursor == 0x7F00 : return
cursor = 0x7F00
} else {
// IDC_HAND
if cursor == 0x7F89 : return
cursor = 0x7F89
}
LoadCursor 0, cursor
SetClassLong hWnd, -12, stat
mouse // カーソル変更を即座に反映
return
eseobj/imgbtn - HSP開発wiki の関連リンクにこの記事が載りました。ありがとうございます。