【问题标题】:How to find which control called ProcessCmdKey如何找到名为 ProcessCmdKey 的控件
【发布时间】:2015-09-09 16:29:28
【问题描述】:

使用 VS2010 框架 4 VB.net。我在表单上有一个文本框和一个 datagridview 控件。在以下情况下,我需要捕获 CR(输入按键):

1) 当光标在datagridview的一个单元格中时。

2) 当光标在文本框中时。

3) 当光标(焦点)在表单上时。

问题的真正基础是需要覆盖 datagridview 的 CR 行为,因为它本身会吞下 CR(使其难以捕获)并将光标移动到下面的单元格(按下回车键时)。 使用此处发布的一些捕获 CR 的所有实例的代码时,我取得了一些成功:

Detecting Enter keypress on VB.NET

这是上述帖子中公认的解决方案,并添加了 debug.print:

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, _
                                       ByVal keyData As System.Windows.Forms.Keys) _
                                       As Boolean

If msg.WParam.ToInt32() = CInt(Keys.Enter) Then
    'deal with enter key presses here......
     Debug.Print("Active: " & ActiveControl.Name.ToString & " " & Len(ActiveControl.Name.ToString))
    Return True
End If
    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

上述解决方案会捕获表单上的所有按键,即使它们来自文本框、表单本身或 datagridview 控件。但我需要确定 CR 源自哪个控件。我看到 HWnd 在 ProcessCmdKey 函数(msg.HWnd)中传递,但它返回的值似乎与任何原始控件(textbox1.handle 或 me.handle 或 datagridview1)的 .handle 值不对应。处理)。经过进一步阅读,这似乎不是一个有效的比较。

我也尝试过使用activecontrol.name方法来获取当前激活的控件并推断出哪个控件发送了CR。但是,即使将光标放置在 datagridview 的单元格中并从单元格发送 CR,activecontrol.name 也会返回零长度字符串。但是,当我从文本框中输入 CR 时,它会返回文本框的名称。

如何确定是哪个控件发送了消息?

非常感谢!

【问题讨论】:

  • 如果 Me.ActiveControl 是 DataGridView1 或 Me.ActiveControl 是 TextBox1
  • Hans...您的建议适用于文本框,但不适用于 datagridview 控件

标签: vb.net winforms datagridview


【解决方案1】:

使用msg.HWnd 属性获取对Control 的引用。例如

public class MyForm2 : Form {
    TextBox tb = new TextBox();
    Button btn = new Button { Text = "Button" };
    DataGridView dgv = new DataGridView() { Dock = DockStyle.Fill };

    public MyForm2() {
        dgv.Columns.Add("Column1", "Col1");
        dgv.Rows.Add("AAA");
        FlowLayoutPanel p = new FlowLayoutPanel { FlowDirection = FlowDirection.TopDown, Dock = DockStyle.Fill };
        p.Controls.Add(tb);
        p.Controls.Add(btn);
        p.Controls.Add(dgv);
        Controls.Add(p);
    }
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        Control c = Control.FromHandle(msg.HWnd);
        if (keyData == Keys.Enter) {
            if (c == tb)
                MessageBox.Show("TextBox");
            else if (c == btn)
                MessageBox.Show("Button");
            else if (c == dgv || c == dgv.EditingControl) {
                MessageBox.Show("DGV");
            }
        }

        return base.ProcessCmdKey(ref msg, keyData);
    }
}

【讨论】:

  • 从文本框发送按键时,msg.HWnd 数据匹配大小写(.handle),但从 datagridview 控件发送按键时,msg.HWnd 数据与 .handle 不匹配.当从 datagridview 控件内部按下一个键时,msg.HWnd 值与在窗体本身上按下键时相同。
  • 如果dgv当前处于编辑模式,那么您需要将控件与dgv.EditingControl进行比较。以上代码已更新。
  • 使用 .EditingControl 句柄有效。再次感谢!
  • 控制focusedControl = FindFocusedControl(this);
【解决方案2】:

处理此问题的一种方法是创建一个继承 datagridview 的自定义控件,并将 ProcessCmdKey 覆盖函数添加到该控件。然后它只会返回 datagridview 击键。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-05
    • 2021-01-22
    • 1970-01-01
    • 2022-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-16
    相关资源
    最近更新 更多