3

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

在此处输入图像描述

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

如果此用户控件托管在 VSPackage ToolWindow 中,则New在用户按下 时执行创建新文件的 VS Shell 级别命令Ctrl+N,而不管焦点是否位于TreeView.

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

4

1 回答 1

0

主持人 Ryan 在MSDN上提出了一些方法。VS Shell 将 Winform 消息传递给 ToolWindow,因此当前的方法是覆盖 ToolWindow 中的 PreProcessMessage,处理诸如Ctrl+N映射到 WPF 命令的组合键,然后翻译这些消息并传递给 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);
    }
于 2011-06-29T01:29:42.250 回答