主持人 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);
}