Some approaches were suggested by moderator Ryan on MSDN. The VS Shell is passing Winform messages to the ToolWindow, so the current approach is to override PreProcessMessage in the ToolWindow, handle the key combinations such as Ctrl+N that would map to WPF commands, and then translate those messages and pass to ComponentDispatcher.RaiseThreadMessage.
This approach is error prone in that the mapping to WPF commands could get out of sync, plus it doesn't incorporate whether or not the WPF command can execute. If anyone has a more ideal approach, please let me know, or if I find one, will post.
Perhaps there is a way for the WPF control to pass back whether the command was executed, and then only if the command was executed would the message be handled. Then, all this mapping business could be avoided.
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);
}