今回は、右クリックをしたときなどに表示されるショートカットメニューを表示させてみましょう。前回までのことが分かっているならば、さほど難しいことはありません。
ショートカットメニューを作成するには、前回ドロップダウンメニューの作成に使用したのと同じ CreatePopupMenu 関数を呼び出します。そのあと、やはり前回と同様に AppendMenu 関数でメニューにメニューアイテムを追加しましょう。
前回では、作成されたメニューオブジェクトをアイテムとして追加すれば、ドロップダウンメニュー・サブメニューとして使えましたが、今回は作成した作成されたメニューオブジェクトをショートカットメニューとして任意の場所に表示させる必要があります。ショートカットメニューを表示させるには、 TrackPopupMenuEx 関数を呼び出します。
BOOL TrackPopupMenuEx( HMENU hMenu, // メニューハンドル UINT fuFlags, // オプションフラグ int x, // x座標 int y, // y座標 HWND hWnd, // ウィンドウハンドル LPTPMPARAMS ptpm // オーバーラップ禁止範囲 );
第2引数(fuFlags パラメータ)には、どのように表示するかのオプションを指定します。通常は 0 を指定しておけば大丈夫でしょう。
第3、第4引数(x, y パラメータ)にはショートカットメニューを表示する座標を指定します。この座標はスクリーン座標の x, y 位置を指定しなければなりません。
第6引数(ptpm パラメータ)はオーバーラップ禁止範囲を指定しますが、特に何も指定する必要がない場合には 0 (NULL) を指定します。
この関数によってショートカットメニューが表示されると、第5引数(hWnd パラメータ)で指定されたウィンドウにメッセージが送られます。これは前回までと同様に WM_COMMAND メッセージです。
ショートカットメニューを表示する場合、 WM_COMMAND メッセージを取得する以外にも、どのアイテムが選択されたのかを取得する手段があります。第2引数(fuFlags パラメータ)に 0x0100 (TPM_RETURNCMD) を指定すると、この関数の戻り値として、選択されたアイテムのIDが返されることになっています。また、何も選択されなれば戻り値が 0 になります。
この場合、アイテムが選択されたことで WM_COMMAND メッセージが発生してしまうので、関数呼び出し時に同時に 0x0080 (TPM_NONOTIFY) も組み合わせて指定しておきましょう。このようにすると、 WM_COMMAND メッセージが発生しないようになります。
以前に一度説明しましたが、作成されたメニューオブジェクトは、他のWindowsオブジェクトの場合と同様、必要なくなった時点で削除しなければならないのでしたね。ただ、前回までのスクリプトで作成されていたメニューはすべてウィンドウに関連付けられたものであったため、それらはウィンドウが破棄されるときに同時に削除されていたのでした。しかし、今回はそうではないので、明示的に削除しておかなければならないのです。
メニューオブジェクトを削除することを、一般的に「メニューを破棄する」と呼びます。メニューを破棄するには DestroyMenu 関数を使います。
BOOL DestroyMenu( HMENU hMenu // メニューハンドル );
この関数にメニューハンドルを渡すことで、そのメニューが破棄されます。メニューを破棄したら、それ以降はそのメニューハンドルは無効なものになるので、そのハンドルをメニュー操作関数に渡したりしてはいけません。
さて、実際にスクリプトを書いてみましょう。
メニューを作成しておいて、右クリックされた時にマウスの位置に表示すればいいでしょう。今回は、上で説明した WM_COMMAND メッセージを受け取らない方法を使ってみることにします。そして、マウスクリックを検出するのには onclick 命令を使ってみることにしましょう。
メニュー表示位置にはスクリーン座標を指定するので、マウスの座標を求めるのに ginfo 命令を使うことになります。
#include "llmod.as" ; メニューアイテムIDを定義 #define CMD_OPEN 1 ;「開く」アイテムのID #define CMD_SAVE 2 ;「保存」アイテムのID #define CMD_QUIT 3 ;「終了」アイテムのID ; ショートカットメニューの作成 dllproc "CreatePopupMenu", pm, 0, D_USER hpopup = stat ; ショートカットメニューのハンドル mesbuf = "開く(&O)" pm = hpopup, 0, CMD_OPEN getptr pm.3, mesbuf dllproc "AppendMenuA", pm, 4, D_USER mesbuf = "保存(&S)" pm = hpopup, 0, CMD_SAVE getptr pm.3, mesbuf dllproc "AppendMenuA", pm, 4, D_USER pm = hpopup, $800, 0, 0 ; 区切り線を指定 dllproc "AppendMenuA", pm, 4, D_USER mesbuf = "終了(&Q)" pm = hpopup, 0, CMD_QUIT getptr pm.3, mesbuf dllproc "AppendMenuA", pm, 4, D_USER onclick goto *lb_on_click ; マウスクリック時ジャンプ onexit goto *lb_on_quit ; 終了時ジャンプ stop *lb_on_click ; マウスクリックされたときの処理 if iparam == 3 { ; 右クリックのとき ginfo 0 ; マウスカーソル座標取得 mref bmscr, 67 ; ウィンドウのBMSCR構造体取得 pm.0 = hpopup ; ショートカットメニューのハンドル pm.1 = $182 ; TPM_RIGHTBUTTON | TPM_RETURNCMD ; | TPM_NONOTIFY pm.2 = prmx ; スクリーンx座標 pm.3 = prmy ; スクリーンy座標 pm.4 = bmscr.13 ; ウィンドウハンドル pm.5 = 0 ; NULL dllproc "TrackPopupMenuEx", pm, 6, D_USER if stat { itemid = stat ; 選択されたメニューアイテムID goto *lb_on_command } } stop *lb_on_command ; メニューアイテムが選択されたときの処理 if itemid == CMD_OPEN { dialog "*", 16 if stat { dialog refstr+"を開きました" } } if itemid == CMD_SAVE { dialog "*", 17 if stat { dialog refstr+"を保存しました" } } if itemid == CMD_QUIT { goto *lb_on_quit } stop *lb_on_quit ; 終了処理 dialog "終了します", 0 ; ポップアップメニューの破棄 dllproc "DestroyMenu", hpopup, 1, D_USER end