HSP3 あれこれ <メニュー>

Last Update : 2008/08/xx

XREA.COMのs206サーバー内のサイトは、Yahoo!検索からペナルティを受け、検索結果で常に下位にランク付けされてしまうので、Yahoo!経由向けに用意したHSPミニ講座内のページです。このページは「http://lhsp.s206.xrea.com/hsp_menu.html」の昔のものです。

メニューバーの表示

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

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

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

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

#include "user32.as"

#define ctype LOWORD(%1) (%1 & $FFFF)

#enum IDM_XXX = 1
#enum IDM_YYY
#enum IDM_ZZZ
#enum IDM_BBB
#enum IDM_CCC
#enum IDM_KOUMOKU1
#enum IDM_KOUMOKU2


;	WM_COMMANDメッセージ
	oncmd gosub *command, $111

;	<ポップアップメニュー>
	CreatePopupMenu
	hMenu.3 = stat
;		第3パラはメニュー項目ID
		AppendMenu hMenu.3, 0, IDM_XXX, "XXX"
		AppendMenu hMenu.3, 0, IDM_YYY, "YYY"
		AppendMenu hMenu.3, 0, IDM_ZZZ, "ZZZ"

;		hMenu.3の$6〜$8をグループ化し、$7に黒丸チェックを入れる
		CheckMenuRadioItem hMenu.3, IDM_XXX, IDM_ZZZ, IDM_YYY, $100

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

	CreatePopupMenu
	hMenu.1 = stat
		AppendMenu hMenu.1, 0, IDM_KOUMOKU1, "項目1"
		AppendMenu hMenu.1, 0, IDM_KOUMOKU2, "項目2"
		AppendMenu hMenu.1, $800, 0, ""	// 第2パラ$800は区切り線
		AppendMenu hMenu.1, 0, IDM_EXIT, "終了"

;	<メインのメニューバー>
	CreateMenu
	hMenu.0 = stat
;		第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"


;	ウィンドウにメニューを付ける
	SetMenu hwnd, hMenu.0
	DrawMenuBar hwnd

	stop


//	WM_COMMAND
*command
;	メニューからのウィンドウメッセージ
	if lparam = 0 {
;		wparamの下位ワードにメニュー項目ID
		wID = LOWORD(wparam)

;		メニュー項目 「項目1」
		if wID = IDM_KOUMOKU1 {
			dialog "項目1 でーす"

			return
		}

;		メニュー項目 「項目2」
		if wID = IDM_KOUMOKU2 {
			if checkmenu {
				uCheck = $0 : checkmenu = 0
			} else {
				uCheck = $8 : checkmenu = 1
			}

;			チェックのオン/オフ
;			第3パラに$0(チェックはずす)、$8(チェックする)
			CheckMenuItem hMenu.1, IDM_KOUMOKU2, uCheck

			return
		}

		if wID = IDM_EXIT {
			gosub *exit

			return
		}

;		メニュー項目 「XXX」/「YYY」/「ZZZ」
		if wID >= IDM_XXX & wID <= IDM_ZZZ {
;			hMenu.3の$6〜$8をグループ化し、選択したそのwIDに黒丸
			CheckMenuRadioItem hMenu.3, IDM_XXX, IDM_ZZZ, wID, $100

			return
		}

		return
	}

	return

*exit
	dialog "終了しますか?", 2
	if stat = 7 : return

	end

^

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

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

;	ポップアップメニューの表示サンプルソース (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 © Kpan. All rights reserved.