2

一部の機能に 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の場合は呼び出されず、呼び出されませんが、呼び出されることがわかります。CustomEditingControlOnKeyDownProcessCmdKey

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) がProcessCmdKeyWndProcメソッドの間のメッセージをキャプチャしています。

4

4 に答える 4

0

関数 ProcessDialogKey をオーバーライドしてみてください

リファレンスを参照してください.. http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.processdialogkey(v=vs.85).aspx

于 2013-06-27T01:50:52.027 に答える
-1

ユーザー コントロール (たとえば、Panel から派生したもの) が KeyDown メッセージを受け取るようにするには、最初にキーボード フォーカスを設定する必要があります。

これは、数行で実行できます。次のコードは、Tab キーまたはマウスを使用してコントロールをフォーカスします。

public Constructor() 
{
    SetStyle(ControlStyles.Selectable, true);
    TabStop = true;
}
protected override void OnMouseDown(MouseEventArgs e) 
{
    Focus();
    base.OnMouseDown(e);
}
于 2016-12-13T03:52:58.890 に答える