今日は雪が降ってかなり寒いのですが、こんばんはぺろりです。
今回はREAPERのメインメニューにあるExtensionメニューの実装について書いていきます。
まずはDLLのエントリポイントで以下のようなコールバック登録とExtensionMenu作成を行います。
また、呼ばれるタイミングはメニュー生成時とメニュー呼び出し時の2種類があります。
呼び出し元はExtensionメニューだけでなく、あらゆるMainメニュー項目から呼び出されるのですが、どこから呼ばれたかは上の例だと HookCustomActionMenu() の引数 menustr を見ると分かります。
(MainメニューのExtensionsをクリックすると"Main extensions"という文字列がやってきます)
■Menu生成時の処理
例えば、MainメニューのExtensionsを初めてクリックした時、Extensions以下のメニュー項目の作成を行うため、コールバック(HookCustomActionMenu)が呼ばれます。
この時、引数の flag=0 になっていますので、以下のような実装でメニュー項目を追加します。
(ちなみにこれはWindows版の場合です。何をやっているか意味不明な方はWin32APIのメニューまわりを調べてください。Mac版とかの方はよく知りませんごめんなさい)
■Menu呼び出し時の処理
Extensionsメニューなどをクリックすると、今度は flag=1 になって HookCustomActionMenu() が呼ばれますが、今のところはここで特に何もする必要はありません。
そして HookCustomActionMenu() の次に HookToggleAction() コールバックが呼び出されます。
これはメニュー項目のチェック表示をON/OFFするために、ActionIDに対する有効・無効状態をREAPERが問い合わせてくるというものです。
ここで 1 を返すと、以下の画像のようにチェックが付きます。

そして、今回メニューに追加した"Test Action"をクリックすると、ここに登録したActionIDのアクションが実行されます。具体的には以下のコールバックが呼び出されます。
・plugin_register()に "hookcommand2" で登録したコールバック
まだ特に触れていませんでしたが、↑のコールバックでfalseを返すと、以下のコールバックも順に呼び出されたりします(ここでは不要なので割愛します)
・plugin_register()に "hookcommand" で登録したコールバック
・plugin_register()に "hookpostcommand" で登録したコールバック
REAPERのあらゆるメインメニュー選択時のActionIDは"hookcommand2"コールバックに飛んでくるので、Extension以外のビルトインメニューに反応して何かする、といったことも出来ちゃいます。
いやもうなんというかやりたい放題できますなぐひひ便利なツールですね。
今回はMainメニュー拡張方法について説明しましたがいかがでしたでしょうか。
ではまた次の記事でお会いしましょう。
今回はREAPERのメインメニューにあるExtensionメニューの実装について書いていきます。
まずはDLLのエントリポイントで以下のようなコールバック登録とExtensionMenu作成を行います。
// Menuに反応するコールバック void HookCustomActionMenu(const char* menustr, HMENU hMenu, int flag); // Actionの有効・無効の問い合わせでMenu意外でもあちこちから呼ばれるコールバック int HookToggleAction( int actionID, int flag );これでMainMenuの仕組みからコールバックが呼ばれるようになります。
// REAPER_PLUGIN_ENTRYPOINT()でのコールバック登録 plugin_register( "toggleaction", (void*)HookToggleAction ); plugin_register( "hookcustommenu", (void*)HookCustomActionMenu );
// ExtensionMenuを作成
// (SWSなど他のExtensionが先に行っているという場合もあるがかぶっても問題なし)
AddExtensionsMainMenu();
また、呼ばれるタイミングはメニュー生成時とメニュー呼び出し時の2種類があります。
呼び出し元はExtensionメニューだけでなく、あらゆるMainメニュー項目から呼び出されるのですが、どこから呼ばれたかは上の例だと HookCustomActionMenu() の引数 menustr を見ると分かります。
(MainメニューのExtensionsをクリックすると"Main extensions"という文字列がやってきます)
■Menu生成時の処理
例えば、MainメニューのExtensionsを初めてクリックした時、Extensions以下のメニュー項目の作成を行うため、コールバック(HookCustomActionMenu)が呼ばれます。
この時、引数の flag=0 になっていますので、以下のような実装でメニュー項目を追加します。
// Extensionメニューにセパレータ、サブメニュー、メニュー項目を追加してみるテスト if ( 0 == flag ) { if ( 0 == strcmp( menustr, "Main extensions" ) ) { MENUITEMINFO mi = { sizeof(MENUITEMINFO), }; // まずセパレータ追加 mi.fType = MFT_SEPARATOR; mi.fMask = MIIM_TYPE; InsertMenuItem( hMenu, GetMenuItemCount( hMenu ), true, &mi ); // サブメニューを追加 HMENU hSubMenu = CreatePopupMenu(); mi.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE; mi.fState = MFS_UNCHECKED; mi.fType = MFT_STRING; mi.hSubMenu = hSubMenu; mi.dwTypeData = L"Pelori"; InsertMenuItem( hMenu, GetMenuItemCount( hMenu ), true, &mi ); // メニュー項目追加 const int cmdID = 0; // ここは自分で事前に登録したActionIDをセット mi.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; mi.fType = MFT_STRING; mi.dwTypeData = L"Test Action"; // Menuに表示されるテキスト mi.fState = MFS_UNCHECKED; mi.wID = cmdID; // このメニュー項目で実行するActionIDを指定 InsertMenuItem( hSubMenu, GetMenuItemCount( hSubMenu ), true, &mi ); } }これでメニュー項目の登録が完了。次はこれを使う時の処理です。
(ちなみにこれはWindows版の場合です。何をやっているか意味不明な方はWin32APIのメニューまわりを調べてください。Mac版とかの方はよく知りませんごめんなさい)
■Menu呼び出し時の処理
Extensionsメニューなどをクリックすると、今度は flag=1 になって HookCustomActionMenu() が呼ばれますが、今のところはここで特に何もする必要はありません。
そして HookCustomActionMenu() の次に HookToggleAction() コールバックが呼び出されます。
これはメニュー項目のチェック表示をON/OFFするために、ActionIDに対する有効・無効状態をREAPERが問い合わせてくるというものです。
int HookToggleAction( int actionID, int flag ) { // 戻り値の仕様 // -1: 自分のExtensionと関係ない、もしくはON/OFFといったトグルを行わない // 0: actionIDに対応するアクションは無効状態です // 1: actionIDに対応するアクションは有効状態です return -1; }今回の例では上のコードのように -1 を返してスルーで問題ありません。
ここで 1 を返すと、以下の画像のようにチェックが付きます。

そして、今回メニューに追加した"Test Action"をクリックすると、ここに登録したActionIDのアクションが実行されます。具体的には以下のコールバックが呼び出されます。
・plugin_register()に "hookcommand2" で登録したコールバック
まだ特に触れていませんでしたが、↑のコールバックでfalseを返すと、以下のコールバックも順に呼び出されたりします(ここでは不要なので割愛します)
・plugin_register()に "hookcommand" で登録したコールバック
・plugin_register()に "hookpostcommand" で登録したコールバック
REAPERのあらゆるメインメニュー選択時のActionIDは"hookcommand2"コールバックに飛んでくるので、Extension以外のビルトインメニューに反応して何かする、といったことも出来ちゃいます。
いやもうなんというか
今回はMainメニュー拡張方法について説明しましたがいかがでしたでしょうか。
ではまた次の記事でお会いしましょう。