OK、アプリだけでカスタムメニュー項目をWindowsシェルのコンテキストメニューに追加できるようです(Windowsシステム全体に影響を与えることは何もする必要はありません)。以下は私がしたことです。この回答は、最初に述べたMSDNコードのコンテキストで解釈する必要があることに注意してください。ここに再びリンクがあります:
MSDNのShellContextMenuクラス
そのクラスでは、具体的には、メソッドShowContextMenu
はへの呼び出しですQueryContextMenu
。その目的は、メニューに項目を追加することです。この場合、コンテキストメニューが表示されるファイル/フォルダーに適切なWindowsシェルメニュー項目です。その呼び出しの後、サブメニューとセパレーターを追加するために次のコードを追加しました。
var mii = new MENUITEMINFO();
mii.fMask = MIIM.SUBMENU | MIIM.STRING | MIIM.FTYPE | MIIM.ID | MIIM.STATE | MIIM.BITMAP;
mii.fState = MFS.ENABLED;
mii.fType = MFT.STRING;
mii.wID = 0; // Application-defined value that identifies the menu item.
mii.hSubMenu = **subMenu**.Handle;
mii.dwTypeData = Program.ShortTitle;
mii.cch = mii.dwTypeData.Length;
var bmp = new System.Drawing.Icon(ac.Properties.NeutralResources.MyAppIcon, 16, 16).ToBitmap();
this.hMyAppSubmenuIcon = bmp.GetHbitmap();
mii.hbmpItem = this.hMyAppSubmenuIcon;
mii.cbSize = Marshal.SizeOf(typeof(MENUITEMINFO));
var success = InsertMenuItem(pMenu, 0, true, ref mii);
mii = new MENUITEMINFO();
mii.fMask = MIIM.FTYPE;
mii.fType = MFT.SEPARATOR;
mii.cbSize = Marshal.SizeOf(mii);
success = InsertMenuItem(pMenu, 1, true, ref mii);
subMenuはタイプSystem.Windows.Forms.ContextMenu
です。このように、コンテキストメニュー全体は、管理されたメニュー項目と管理されていないメニュー項目の両方で構成される、いくぶんハイブリッドです。これまでのところ、これに問題はありません。これは、以下に説明するように、2種類のメニュー項目の選択の処理を異なる方法で実行する必要があることを意味します...
管理項目をメニューに挿入した後、ShowContextMenu
メソッドはを呼び出しますTrackPopupMenu
。シェルメニュー項目の場合、すでに作成されているクラスがそれらの選択を処理します。私自身のメニュー項目については、Windows API関数であるため、追加の手順を実行する必要 がありました。これは、管理対象サブメニュー項目のイベントTrackPopupMenu
ではうまく機能しません。Click
イベントハンドラーをサブメニュー項目に接続できClick
ますが、シェルコンテキストメニューから選択した場合、Click
イベントは発生しません。Click
管理メニューを単独で表示することもあるので、私はまだそれらを接続しました。
シェルのコンテキストメニューからの管理対象メニュー項目の選択に応じてアクションを実行するために、選択TrackPopupMenu
されたメニュー項目のリソースIDである戻り値のを使用しました。それは物事が少し回り道をしたところです。管理コンテキストメニューを作成する場合、各メニュー項目にはインデックスがあります。これは、メニュー項目のリソースIDを返すWindowsAPI関数GetMenuItemIDで使用できます。管理対象クラスから継承し、ContextMenu
をカプセル化しDictionary
て、このリソースIDからメニュー項目にマップし、後でを呼び出した直後に使用できるようにしましたTrackPopupMenu
。私の目的では、ハンドラーを呼び出すために必要なのはこれだけです。これは、アプリでコマンドパターンを使用し、コマンドオブジェクトをメニュー項目のに保存したためです。Tag
メニューを作成するときのプロパティ。(辞書から正しいメニュー項目が表示されたら、からコマンドオブジェクトを抽出することで、対応するハンドラーを実行できましたTag
)。
これは数日間正常に実行されています。管理されていないリソースのように、クリーンアップする必要のある穴を誰かが見つけた場合は、そのことを伝えてください。