如何防止VS Shell在VSPackage ToolWindow中获得密钥/命令绑定的优先级?

时间:2011-06-28 17:57:25

标签: wpf key-bindings commandbinding vs-extensibility vspackage

我有一个用户控件,它接受输入手势来执行各种命令。在下面的示例图中,用户可以按 Ctrl + N 执行New命令以在TreeView中创建新项目。

enter image description here

当此用户控件托管在WPF应用程序中时,当焦点位于TreeView时,用户可以使用 Ctrl + N 创建新项目kbd> Ctrl + N 当焦点位于应用程序的其他位置时,将执行应用程序级New命令。

当此用户控件托管在VSPackage ToolWindow中时,当用户按下 Ctrl + N 时,将执行用于创建新文件的VS Shell级别New命令,而不管是否关注TreeView

如何防止VS Shell获得密钥/命令绑定的优先级?

1 个答案:

答案 0 :(得分:0)

主持人Ryan在MSDN上提出了一些方法。 VS Shell将Winform消息传递给ToolWindow,因此当前的方法是覆盖ToolWindow中的PreProcessMessage,处理将映射到WPF命令的 Ctrl + N 等组合键,然后翻译这些组合。消息并传递给ComponentDispatcher.RaiseThreadMessage。

这种方法容易出错,因为到WPF命令的映射可能会失去同步,而且它不会包含WPF命令是否可以执行。如果有人有更理想的方法,请告诉我,如果我找到,将发布。

也许WPF控件有一种方法可以传回命令是否已执行,然后只有在执行命令时才会处理消息。然后,可以避免所有这些映射业务。

    private bool isControlKeyDepressed = false;
    private bool isShifKeyDepressed = false;
    private bool isOtherKeyDepressed = false;
    private bool isCommandCombinationDepressed = false;

    protected override bool PreProcessMessage(ref Message msg)
    {
        // trap keyboard messages if window has focus
        if (msg.Msg == 256)
        {
            if (msg.WParam == (IntPtr)17)
            {
                isControlKeyDepressed = true;
                isOtherKeyDepressed = false;
            }
            else if (msg.WParam == (IntPtr)16)
            {
                isShifKeyDepressed = true;
                isOtherKeyDepressed = false;
            }
            else
            {
                if (isOtherKeyDepressed == true)
                {
                    isControlKeyDepressed = false;
                    isShifKeyDepressed = false;
                }
                isOtherKeyDepressed = true;
                if (isControlKeyDepressed == true)
                {
                    if (isShifKeyDepressed == true)
                    {
                        switch (msg.WParam.ToInt64())
                        {
                            case 65: // Ctrl+Shift+A command
                            case 67: // Ctrl+Shift+C command
                            case 78: // Ctrl+Shift+N command
                            case 79: // Ctrl+Shift+O command
                            case 83: // Ctrl+Shift+S command
                            case 85: // Ctrl+Shift+U command
                            case 88: // Ctrl+Shift+X command
                                isCommandCombinationDepressed = true;
                                break;
                            default:
                                isCommandCombinationDepressed = false;
                                break;
                        }
                    }
                    else
                    {
                        switch (msg.WParam.ToInt64())
                        {
                            case 69: // Ctrl+E command
                            case 78: // Ctrl+N command
                            case 79: // Ctrl+O command
                            case 83: // Ctrl+S command
                                isCommandCombinationDepressed = true;
                                break;
                            default:
                                isCommandCombinationDepressed = false;
                                break;
                        }
                    }
                }
                else
                {
                    isCommandCombinationDepressed = false;
                }
            }

            if (isCommandCombinationDepressed == true)
            {
                // send translated message via component dispatcher
                MSG dispatchMsg = new MSG();
                dispatchMsg.hwnd = msg.HWnd;
                dispatchMsg.lParam = msg.LParam;
                dispatchMsg.wParam = msg.WParam;
                dispatchMsg.message = msg.Msg;
                ComponentDispatcher.RaiseThreadMessage(ref dispatchMsg);
                msg.Result = (IntPtr)1;
                return true;
            }
        }
        return base.PreProcessMessage(ref msg);
    }