一部の機能に Enter キーを使用するカスタム DataGridView 編集コントロールがあります。IDataGridViewEditingControl
次のコードを使用して、インターフェイス メソッド '`EditingControlWantsInputKey' を実装します。
public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Left:
case Keys.Right:
case Keys.Up:
case Keys.Down:
case Keys.Home:
case Keys.End:
case Keys.Enter:
case Keys.Delete:
return true;
default:
return !dataGridViewWantsInputKey;
}
}
ただし、Enter キーの KeyDown イベントは受け取りません。メソッドに条件付きブレークポイントを配置してEditingControlWantsInputKey
、データ グリッド ビューがそれを呼び出していたかどうかを確認し、Enter キーに応答して呼び出されないかどうかを確認しました。
私の編集コントロールでは、ProcessCmdKey
メソッドをオーバーライドMessage
して、次のコードで基になるものがコントロールに送信されているかどうかを確認しました。
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if ((msg.Msg == User32.WM_KEYDOWN) &&
((Keys)msg.WParam == Keys.Enter))
{
Console.WriteLine("GOT HERE");
}
return base.ProcessCmdKey(ref msg, keyData);
}
実際にはメッセージを取得していますが、OnKeyDown
メソッドに送信されることはありません。
ある時点で、 がキー自体を処理するために をDataGridView
登録している可能性があると考えましたIMessageFilter
が、その場合、コントロールは への呼び出しを取得しますProcessCmdKey
(独自の を追加して、これを自分で確認しましたIMessageFilter
)。
カスタム編集コントロールが呼び出されないようにするために DataGridView が何をしているのか、またOnKeyDown
その動作を変更する方法があるかどうかを知っている人はいますか?
私が考えることができる唯一のことは、ProcessCmdKey
メソッドからのメッセージのルーティングを自分で処理することですが、それはハックのように感じます.
[編集]
King King のコメントに答えるには:
編集コントロールは、 のカスタム サブクラスですTextBox
。カスタム サブクラスは、より高度なオートコンプリート機能を追加するだけで機能します (組み込みの a のサポートよりも優れていますTextBox
)。カスタム テキスト ボックスは、KeyDown イベントを使用して、ユーザーが提案されたオートコンプリート項目をいつ選択したいかを認識します。アプリケーションの他のいくつかの場所で使用されており、本番コードで数か月間使用されています (したがって、それが原因ではないと確信しています)。
[編集 - サンプルコード付き]
これが起こっていることを示すように見える最小限のプログラムを作成しました。新しい WinForms プロジェクトを作成し、フォームに DataGridView を配置します。コードの壁で申し訳ありませんが、これは効果を確認するために必要な最小限のものです。
実行すると、キー コードが EnterEditingControlWantsInputKey
の場合は呼び出されず、呼び出されませんが、呼び出されることがわかります。CustomEditingControl
OnKeyDown
ProcessCmdKey
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView.EditingControlShowing += this.DataGridView_EditingControlShowing;
}
private void DataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
// Must remove first to avoid adding the same event handler twice.
e.Control.KeyDown -= this.EditingControl_KeyDown;
e.Control.KeyDown += this.EditingControl_KeyDown;
}
private void EditingControl_KeyDown(object sender, KeyEventArgs e)
{
Console.WriteLine(e.KeyData);
}
}
public class CustomEditingControl : DataGridViewTextBoxEditingControl
{
public override bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
{
if ((Keys.KeyCode & keyData) == Keys.Enter)
{
Console.WriteLine("EditingControlWantsInputKey: Enter");
}
else
{
Console.WriteLine("EditingControlWantsInputKey: Other");
}
return base.EditingControlWantsInputKey(keyData, dataGridViewWantsInputKey);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x0100;
if ((msg.Msg == WM_KEYDOWN) &&
((Keys)msg.WParam == Keys.Enter))
{
Console.WriteLine("ProcessCmdKey: Enter");
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
Console.WriteLine("OnKeyDown: Enter");
}
else
{
Console.WriteLine("OnKeyDown: Other");
}
base.OnKeyDown(e);
}
}
public class CustomDataGridViewTextBoxCell : DataGridViewTextBoxCell
{
public override Type EditType
{
get
{
return typeof(CustomEditingControl);
}
}
}
public class CustomDataGridViewColumn : DataGridViewTextBoxColumn
{
public CustomDataGridViewColumn()
{
this.CellTemplate = new CustomDataGridViewTextBoxCell();
}
}
[編集 - より多くの調査結果を含む]
メッセージ チェーンにできるだけ多くのログを追加しました。通常のテキスト ボックスの場合、Enter キーを押すと、次のようなメッセージ トレイルが表示されます。
PreFilterMessage: Return
PreProcessMessage: Return
ProcessCmdKey: Return
WndProc: Return
ProcessKeyPreview: Return
OnKeyDown: Return
編集コントロールで「1」キーを押すと (たとえば)、次のトレイルが生成されます。
PreFilterMessage: D1
PreProcessMessage: D1
ProcessCmdKey: D1
WndProc: D1
EditingControlWantsInputKey: D1
ProcessKeyPreview: D1
OnKeyDown: D1
EditingControl_KeyDown: D1 (This is from the hooked up event handler)
編集コントロールの場合、「Enter」キーを押すと、次のトレイルが生成されます
PreFilterMessage: Return
PreProcessMessage: Return
ProcessCmdKey: Return
したがって、何か (おそらく DataGridView) がProcessCmdKey
とWndProc
メソッドの間のメッセージをキャプチャしています。