1

Windows エクスプローラーのシェル コンテキスト メニューを実装しており、メニューの作成に成功しました。私が問題を抱えているのは、選択したメニュー項目にカーソルを合わせると、ステータス バーにヘルプ テキストを表示する IContextMenu::GetCommandString メソッドです。

各アイテムにカーソルを合わせると何も表示されませんが、奇妙なのは、作成しなかった他のアイテムの一部、たとえば開いたり印刷したりすると、ヘルプテキストがゴミに変わってしまうことです..

IContextMenu::QueryContextMenu と IContextMenu::GetCommandString のコード サンプルを次に示します。

int ShellExtLib.IContextMenu.QueryContextMenu(IntPtr hMenu, uint indexMenu, uint idCmdFirst, uint idCmdLast, uint uFlags)
{
    uint idCmd = idCmdFirst;
    StringBuilder sb = new StringBuilder(1024);

    try
    {
        if ((uFlags & 0xf) == 0 || (uFlags & (uint)ShellExtLib.CMF.CMF_EXPLORE) != 0)
        {
            uint selectedFileCount = Helpers.DragQueryFile(m_hDrop, 0xffffffff, null, 0);

            if (selectedFileCount == 1)
            {
                Helpers.DragQueryFile(m_hDrop, 0, sb, sb.Capacity + 1);
                Documents.Add(sb.ToString());
            }
            else
            {
                // MULTIPLE FILES SELECTED.
                for (uint i = 0; i < selectedFileCount; i++)
                {
                    Helpers.DragQueryFile(m_hDrop, i, sb, sb.Capacity + 1);
                    Documents.Add(sb.ToString());
                }
            }

            Helpers.InsertMenu(hMenu, indexMenu++, ShellExtLib.UFLAGS.MF_SEPARATOR | ShellExtLib.UFLAGS.MF_BYPOSITION, 0, null);

            IntPtr hSubMenu = Helpers.CreateMenu();
            if (hSubMenu != IntPtr.Zero)
            {
                Helpers.InsertMenu(hSubMenu, 0, ShellExtLib.UFLAGS.MF_STRING | ShellExtLib.UFLAGS.MF_BYPOSITION, idCmd++, "Item 1");
                Helpers.InsertMenu(hSubMenu, 1, ShellExtLib.UFLAGS.MF_STRING | ShellExtLib.UFLAGS.MF_BYPOSITION, idCmd++, "Item 2");
                Helpers.InsertMenu(hSubMenu, 2, ShellExtLib.UFLAGS.MF_SEPARATOR | ShellExtLib.UFLAGS.MF_BYPOSITION, idCmd++, null);
                Helpers.InsertMenu(hSubMenu, 3, ShellExtLib.UFLAGS.MF_STRING | ShellExtLib.UFLAGS.MF_BYPOSITION, idCmd++, "Item 3");
                Helpers.InsertMenu(hSubMenu, 4, ShellExtLib.UFLAGS.MF_SEPARATOR | ShellExtLib.UFLAGS.MF_BYPOSITION, idCmd++, null);
                Helpers.InsertMenu(hSubMenu, 5, ShellExtLib.UFLAGS.MF_STRING | ShellExtLib.UFLAGS.MF_BYPOSITION, idCmd++, "Item 4");
                Helpers.InsertMenu(hSubMenu, 6, ShellExtLib.UFLAGS.MF_STRING | ShellExtLib.UFLAGS.MF_BYPOSITION, idCmd++, "Item 5");
            }

            Helpers.InsertMenu(hMenu, indexMenu++, ShellExtLib.UFLAGS.MF_STRING | ShellExtLib.UFLAGS.MF_BYPOSITION | ShellExtLib.UFLAGS.MF_POPUP, (uint)hSubMenu, "Main Menu");

            Helpers.InsertMenu(hMenu, indexMenu++, ShellExtLib.UFLAGS.MF_SEPARATOR | ShellExtLib.UFLAGS.MF_BYPOSITION, 0, null);

            return (int)(idCmd - idCmdFirst);
        }
    }
    catch { }

    return 0;
}



void ShellExtLib.IContextMenu.GetCommandString(int idCmd, uint uFlags, int pwReserved, StringBuilder commandString, int cchMax)
    {
        switch (uFlags)
        {
            case (uint)ShellExtLib.GCS.VERB:
                commandString = new StringBuilder("x");
                break;

            case (uint)ShellExtLib.GCS.HELPTEXTA:
                commandString = new StringBuilder("y");
                break;
        }
    }

誰か提案はありますか?シェル拡張機能の作成方法に関する多くの記事を読み、MSDN も読んでいます。

ありがとう。

4

2 に答える 2

1

GetCommandString の宣言が正しくありません - GetCommandString は、文字列をコピーするはずの独自のバッファーを渡します。この場合、StringBuilder として宣言することはできないと思います。IntPtr として宣言し、Encoding.Unicode.GetBytes と Marshal.Copy を使用して文字列をバッファーにコピーします。必ず null ターミネーターを追加してください。

于 2010-03-20T05:40:46.427 に答える
1

正確に言うと、 GetCommandString フラグも確認する必要があります。pszName が LPSTR として宣言されている場合でも、GCS_... 定数が A (ansi) または W (unicode) であるかどうかを確認します。
たとえば、uFlags が GCS_VERBA の場合、pszName は LPSTR (char*) であり、ANSI 文字列から cch 文字のコピーを渡す必要があります。
uFlags が GCS_VERBW の場合、pszName は LPWSTR 型 (wchar_t*) (LPSTR として宣言されている場合でも) であり、Unicode 文字列から cch 文字をコピーする必要があります。
cchMax のドキュメントがここで正しいかどうかは覚えていません (文字数ではなくバイト数である可能性があります)。

于 2015-05-15T13:38:19.267 に答える