HSP3 あれこれ <メニュー編>

Last Update : 2005/12/xx

メニューバーの表示

 ウィンドウの上側、タイトルバーの真下に付いているメニューバー。一般的なアプリケーションに[ファイル]、[編集]、[表示]というような項目がよく用意されていると思います。これをHSP3でこしらえるサンプルスクリプトです。

 HSP2ではHSP拡張プラグインや llmod.as 用モジュールを利用するのが一般的でしたが、HSP3では拡張プラグインなぞもはや不要です。メニューバーの表示関連のWindows API(Win32 API)関数を直で呼び出せばOK。

 メニューバー表示に関しては、HSP2向けですがちょくとさんのページや、HSP3自体に付属している モジュール common\mod_menu.as や サンプルコード sample\new\menubar.hsp もチェックあれ〜!

;	メニューバー表示サンプルソース (by Kpan)

#uselib "user32"
#cfunc CreateMenu "CreateMenu"
#cfunc CreatePopupMenu "CreatePopupMenu"
#func AppendMenu "AppendMenuA" int, int, int, str
#func SetMenu "SetMenu" int, int
#func DrawMenuBar "DrawMenuBar" int
#func CheckMenuRadioItem "CheckMenuRadioItem" int, int, int, int, int
#func CheckMenuItem "CheckMenuItem" int, int, int

	screen , 400, 300

;	メニュー項目を選択したとき (WM_COMMANDメッセージ)
	oncmd gosub *jump, $111

;	<ポップアップメニュー>
	hMenu.3 = CreatePopupMenu ()
;		第3パラはメニュー項目ID
		AppendMenu hMenu.3, 0, $6, "XXX"
		AppendMenu hMenu.3, 0, $7, "YYY"
		AppendMenu hMenu.3, 0, $8, "ZZZ"
;		hMenu.3の$6〜$8をグループ化し、$7に黒丸チェックを入れる。
		CheckMenuRadioItem hMenu.3, $6, $8, $7, $100

	hMenu.2 = CreatePopupMenu ()
;		第2パラ$10はサブメニュー。第3パラにサブメニューのハンドル。
		AppendMenu hMenu.2, $10, hMenu.3, "AAA"
;		第2パラ$1はグレイ表示。
		AppendMenu hMenu.2, $1, $3, "BBB"
;		第2パラ$8は項目チェック。(オン/オフの処理必要)
		AppendMenu hMenu.2, $8, $4, "CCC"

	hMenu.1 = CreatePopupMenu ()
		AppendMenu hMenu.1, 0, $1, "ああああ"
;		第2パラ$800は区切り線。
		AppendMenu hMenu.1, $800, , ""
;		下にメニュー項目オン/オフ処理あり
		AppendMenu hMenu.1, 0, $2, "いいいい"

;	<メインのメニューバー>
	hMenu.0 = CreateMenu ()
;		第2パラ$10はポップアップメニュー。第3パラにポップアップ
;		メニューのハンドル。
		AppendMenu hMenu.0, $10, hMenu.1, "メニュー1"
		AppendMenu hMenu.0, $10, hMenu.2, "メニュー2"
;		第2パラ$4000を加えて以降のメニュー位置が右側に
		AppendMenu hMenu.0, $10 | $4000, hMenu.3, "メニュー3"


;	ウィンドウにメニューをつける
;	第2パラにメニューバーのハンドル
	SetMenu hwnd, hMenu.0
	DrawMenuBar hwnd

	stop


*jump
;	メニュー以外からのウィンドウメッセージ用
	if lparam != 0 : return

;	wparamの下位ワードにメニュー項目IDが入る
	wid = wparam & $FFFF

;	メニュー項目ID $1 「ああああ」
	if wid = $1 : dialog "ああああ でーす。"

;	メニュー項目ID $2 「いいいい」
	if wid = $2 {
		if checkmenu = 1 {
			uCheck = $0 : checkmenu = 0
		} else {
			uCheck = $8 : checkmenu = 1
		}
;		hMenu.1のメニュー項目ID $2のチェックをオン/オフにする
;		第3パラに$0(チェックはずす)、$8(チェックする)。
		CheckMenuItem hMenu.1, $2, uCheck
	}

;	メニュー項目ID $6〜$8 「XXX」/「YYY」/「ZZZ」
	if wid >= $6 & wid <= $89 {
;		hMenu.3の$6〜$8をグループ化し、選択したその wid に
;		黒丸チェック。他の項目は自動的にチェックが外れます。
		CheckMenuRadioItem hMenu.3, $6, $8, wid, $100
	}

	return

^

右クリックメニューの表示

 ウィンドウ上でマウスを右クリックすると、右クリックメニュー(ポップアップメニュー、ショートカットメニュー)を表示させるサンプルスクリプトです。

;	ポップアップメニューの表示サンプルソース (by Kpan)
;	(注) エディタの[HSP]メニュー→[HSP拡張マクロを使用する]を要有効。 

#uselib "user32"
#cfunc CreatePopupMenu "CreatePopupMenu"
#func AppendMenu "AppendMenuA" int, int, int, str
#func TrackPopupMenu "TrackPopupMenu" int, int, int, int, int, int
#func DestroyMenu "DestroyMenu" int

;	<サブのポップアップメニュー>
;	サブメニューを作成し、ハンドルを取得
	hMenu.0 = CreatePopupMenu ()
;		第3パラはメニュー項目ID
		AppendMenu hMenu.0, , $3, "サブメニュー項目 3"
		AppendMenu hMenu.0, , $4, "サブメニュー項目 4"

;	<メインのポップアップメニュー>
;	メインのポップアップメニューを作成し、ハンドルを取得
	hMenu.1 = CreatePopupMenu ()
		AppendMenu hMenu.1, , $1, "メニュー項目 1"
;		第2パラを$800にするとセパレータ(区切り線)になる。
		AppendMenu hMenu.1, $800, , ""
		AppendMenu hMenu.1, , $2, "メニュー項目 2"
;		第2パラメータを$10にするとサブメニューへ。
;		第3パラにサブメニューのハンドルを入れる。
		AppendMenu hMenu.1, $10, hMenu.0, "サブメニュー"

	onclick gosub *onjump ; マウスをクリックした時
;	あるいは、WM_CONTEXTMENU
;	oncmd gosub *onjump, $7B

	onexit *exit

	stop

*onjump
	if wparam = 2 { ; 右クリックされた時
;		ポップアップメニューを開く。第1パラに開くポップアップ
;		メニューのハンドルを指定してやる。
		TrackPopupMenu hMenu.1, $100, ginfo (0), ginfo (1), , hwnd

;		statにそれぞれメニュー項目IDが返ります
		if stat = $1 : dialog "項目 1 選択"
		if stat = $2 : dialog "項目 2 選択した"
		if stat = $3 : dialog "項目 3 選択です"
		if stat = $4 : dialog "項目 4 選択じゃ"
	}
	return

*exit
;	このようなどこのウィンドウにも張り付いていないメニューの
;	場合は、終了時に明示的に破棄する必要があるとのこと。
	DestroyMenu hMenu.1

	end

^

ボタン脇にポップアップメニューの表示

 上の「右クリックメニューの表示」ではマウスの右クリックでメニューが表示されますが、ボタン(button命令)を押した時に、オブジェクト脇にポップアップメニュー表示させるサンプルスクリプトです。(ドロップダウンメニュー「風」?

 GetWindowRect関数でボタンの表示されている座標位置を取得し、それをポップアップメニューの表示位置として反映してやればOK。(ボタンオブジェクトのハンドル取得はobjinfo関数を利用。

;	ボタン脇ポップアップメニュー表示サンプルソース (by Kpan)

#uselib "user32"
#cfunc CreatePopupMenu "CreatePopupMenu"
#func AppendMenu "AppendMenuA" int, int, int, str
#func TrackPopupMenu "TrackPopupMenu" int, int, int, int, int, int
#func DestroyMenu "DestroyMenu" int
#func GetWindowRect "GetWindowRect" int, int

;	RECT構造体
	dim RECT, 4

	hMenu.0 = CreatePopupMenu ()
		AppendMenu hMenu.0, , $10, "は(&A)"
		AppendMenu hMenu.0, , $20, "ひ(&I)"
		AppendMenu hMenu.0, , $30, "ふ(&U)"
		AppendMenu hMenu.0, , $40, "へ(&E)"
		AppendMenu hMenu.0, , $50, "ほ(&O)"
		AppendMenu hMenu.0, , $60, "ー(&X)"

	pos 50, 50
	objsize 55, 24

	button ">>>", *openmenu
	hButton = objinfo (stat, 2) ; ボタンのハンドルを取得。

	onexit *exit
	stop


*openmenu
;	オブジェクトの外側サイズを取得するGetWindowRect関数
;	RECT構造体として左上XY座標、右下XY座標が返る
	GetWindowRect hButton, varptr (RECT)

;	ボタンの右側にメニュー表示
;	第3、第4パラにボタンの右上XY座標を指定
;	(RECT.0、RECT.3を指定すると、ボタンの真下にメニューが表示されます。)
	TrackPopupMenu hMenu.0, $100, RECT.2, RECT.1, , hwnd

	if stat = $10 : mes "は"
	if stat = $20 : mes "ひ"
	if stat = $30 : mes "ふ"
	if stat = $40 : mes "へ"
	if stat = $50 : mes "ほ"
	if stat = $60 : goto *exit

	stop


*exit
;	このようなどこのウィンドウにも張り付いていないメニューの
;	場合は、終了時に明示的に破棄する必要があるとのこと。
	DestroyMenu hMenu.0

	end

^

システムメニューに新たな項目追加

 システムメニューというのは、ウィンドウのタイトルバー上で右クリックした時とか、そのバーにあるアイコンをクリックした時に表示されるメニューです。[元のサイズに戻す]、[移動]、[サイズ変更]・・・、[閉じる]というような感じの項目が用意されていると思います。そこに自前のメニュー項目を用意してやるサンプルスクリプトです。

;	システムメニューに新規項目追加サンプルコード (by Kpan)

#uselib "user32"
#cfunc GetSystemMenu "GetSystemMenu" int, int
#func InsertMenu "InsertMenuA" int, int, int, int, str

;	WM_SYSCOMMAND (システムメニューが選択された時)
	oncmd gosub *syscommand, $112

;	システムメニューのハンドルを取得
	hSystemMenu = GetSystemMenu (hwnd, )

;	第2パラメータに挿入位置(一番上が0)、第4パラがメニュー項目ID、
;	第5パラにメニュー項目に表示する文字列
	InsertMenu hSystemMenu, 0, $400, 1, "追加したー(&M)"
;	+$800 で区切り線
	InsertMenu hSystemMenu, 1, $400 | $800, , ""
	InsertMenu hSystemMenu, 5, $400, 2, "も一つ追加(&O)"

	stop


*syscommand
;	wparam にメニュー項目IDが返ります。
	if wparam = 1 : dialog "追加したものだー"
	if wparam = 2 : dialog "も一つ追加したものでアール"

	return

^

システムメニューの項目削除 (移動できないウィンドウ)

 システムメニューにあらかじめ用意されているメニュー項目を削除することで、たとえばタイトルバーをドラッグしてもウィンドウ位置を変更させることをできなくなります。ちなみに、[閉じる]項目を削除してしまうと、普通のプログラム終了ができなくなってしまうので注意。

#uselib "user32"
#cfunc GetSystemMenu "GetSystemMenu" int, nullptr
#func DeleteMenu "DeleteMenu" int, int, nullptr

;	システムメニューのハンドルを取得
	hSystemMenu = GetSystemMenu (hwnd)

;	メニュー項目削除。第2パラに削除するメニュー項目を指定
;	$F000=サイズ変更、$F010=移動、$F020=最小化、$F030=最大化、
;	$F060=閉じる、$F120=元のサイズに戻す、$0=区切り線
	DeleteMenu hSystemMenu, $F010

^

システムメニューの監視

 システムメニュー内の項目を監視する。HSP3から登場のoncmd命令でチェック。

;	WM_SYSCOMMAND (システムメニューが選択された時)
	oncmd gosub *syscommand, $0112

	stop

*syscommand
;	$F010=ウィンドウが移動した
;	$F020=ウィンドウが最小化された
;	$F120=ウィンドウが元の位置に戻った
;	$F180=クエスチョンマーク?付きマウスポインタでクリックされた
	check = wparam & $FFF0
	mes "$"+strf ("%x", check)

	return

^

Copyright © 2005-2008 Kpan. All rights reserved.