いくつかのアプローチは、MSDNのモデレーターRyanによって提案されました。VSシェルはWinformメッセージをToolWindowに渡しているため、現在のアプローチは、ToolWindowでPreProcessMessageをオーバーライドし、Ctrl+NWPFコマンドにマップされるようなキーの組み合わせを処理してから、それらのメッセージを変換して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);
}