Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ShowContextMenu show Shell Context Menu but with no text and no icon #406

Closed
jcljb opened this issue Jun 14, 2023 · 3 comments
Closed

ShowContextMenu show Shell Context Menu but with no text and no icon #406

jcljb opened this issue Jun 14, 2023 · 3 comments

Comments

@jcljb
Copy link

jcljb commented Jun 14, 2023

To simplify, I try this simple code (W11 pro) :

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

        this.Shown += Form1_Shown;
    }

    ShellItem shellItem;

    private void Form1_Shown(object? sender, EventArgs e)
    {
        shellItem = new ShellItem(@"d:\xxx.txt");           
    }       

    private void button1_Click(object sender, EventArgs e)
    {
         shellItem.ContextMenu.ShowContextMenu(GetMousePosition());
    }
}

On button1 click, the shell context menu is show but with no text or icon...
ContextMenu

What's or or missing ?

@jcljb
Copy link
Author

jcljb commented Jun 14, 2023

Perhaps pb with IContextMenu3 interface ?
I try to call methods directly and pass Handle to main window in order to take a look to received messages (wndproc)
and it seems that some messages must be filtered too
this is poor and not complete but now the contextmenu is fully shown :

private void button1_Click(object sender, EventArgs e)
{
// shellItem.ContextMenu.ShowContextMenu(GetMousePosition(),CMF.CMF_CANRENAME);

        hmenu = Vanara.PInvoke.User32.CreatePopupMenu();
        shellItem.ContextMenu.ComInterface.QueryContextMenu(hmenu, 0, 0x8000, int.MaxValue, CMF.CMF_EXTENDEDVERBS).ThrowIfFailed();
        var command = Vanara.PInvoke.User32.TrackPopupMenuEx(hmenu, TrackPopupMenuFlags.TPM_RETURNCMD, GetMousePosition().X, GetMousePosition().Y, Handle);
        if (command > 0)
            shellItem.ContextMenu.InvokeCommand((int)command - 0x800);
    }

    protected override void WndProc(ref Message msg)
    {
        switch (msg.Msg)
        {
            case 0x11f:
            case 0x117:
            case 0x2b:
            case 0x2c:
            case 288:

                {
                    if (hmenu != null)
                    {
                        m_ComInterface3 = (IContextMenu3)Shell32.ShellUtil.QueryInterface(shellItem.ContextMenu.ComInterface, new Guid("{bcfce0a0-ec17-11d0-8d10-00a0c90f2719}"));

                        if (m_ComInterface3 is not null)
                        {
                            IntPtr lres;

                            m_ComInterface3.HandleMenuMsg2((uint)msg.Msg, msg.WParam, msg.LParam, out lres);
                        }
                    }
                    else
                        base.WndProc(ref msg);
                        break;
                }
        }
        
            base.WndProc(ref msg);
        
    }

@dahall
Copy link
Owner

dahall commented Jun 26, 2023

Have you found functional examples using IContextMenu3? I would follow those. Vanara simply exposes the interfaces. From light reading, it does appear that HandleMenuMsg and HandleMenuMsg2 must be called in the user code.

@jcljb
Copy link
Author

jcljb commented Jun 29, 2023

I rewrite to use BasicMessageWindow and it works i.e. the behavoir is correct (the context menu is correctly displayed based on selected item(s) and returned cmd id as well); the m_ComInterface3 is always returned (based on my tests) and it seems that INITMENUPOPUP is the only msg to intercept...

   private static bool WindowMessageFilter(HWND hwnd, uint msg, IntPtr wParam, IntPtr lParam, out IntPtr lReturn)
    {
        lReturn = default;
        try
        {
            Debug.WriteLine($"msg = {msg}");

            switch (msg)
            {
                case (uint)WM.INITMENUPOPUP:
                //case (uint)WM.DRAWITEM:
                //case (uint)WM.MEASUREITEM:
                //case (uint)WM.MENUCHAR:
                    {
                        var com_interface3 = (IContextMenu3)Shell32.ShellUtil.QueryInterface(ComInterfaceContextMenu, new Guid("{bcfce0a0-ec17-11d0-8d10-00a0c90f2719}"));
                        if (com_interface3 is not null)
                        {
                            Debug.WriteLine($"com_interface3 = {msg}");
                            if (com_interface3.HandleMenuMsg2(msg, wParam, lParam, out var lRet).Succeeded)
                                lReturn = lRet;
                            return true;
                        }
                        else
                        {
                            var com_interface2 = (IContextMenu2)Shell32.ShellUtil.QueryInterface(ComInterfaceContextMenu, new Guid("{000214f4-0000-0000-c000-000000000046}"));
                            if (com_interface2 is not null)
                            {
                                if (com_interface2.HandleMenuMsg(msg, wParam, lParam).Succeeded)
                                    lReturn = default;
                                return true;
                            }
                        }
                    }
                    break;
            }
        }
        catch { }

        return false;


    }

@dahall dahall closed this as completed Jul 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants