自定义屏幕键盘和过滤下拉菜单播放效果不佳

Custom on-screen keyboard and filtered dropdown not playing nicely

我的 winforms 应用程序中有一个自定义的屏幕十键键盘,它似乎在任何地方都可以正常工作,除了具有一些自定义过滤代码的单个下拉菜单。我竭尽全力让这个键盘以我能想象到的所有方式成为非交互式的。这是代码隐藏(numpad0、numpad1 等都是标签,如果重要的话)

public partial class TenKeyForm : Form
{
    private const int WM_NCLBUTTONDOWN = 0xA1;
    private const int HT_CAPTION = 0x2;
    private const int WM_MOUSEACTIVATE = 0x0021, MA_NOACTIVATE = 0x0003;
    private const int WS_EX_NOACTIVATE = 0x08000000;

    protected override bool ShowWithoutActivation { get { return true; } }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_MOUSEACTIVATE)
        {
            m.Result = (IntPtr)MA_NOACTIVATE;
            return;
        }
        base.WndProc(ref m);
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams createParams = base.CreateParams;
            createParams.ExStyle |= WS_EX_NOACTIVATE;
            return createParams;
        }
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern bool ReleaseCapture();

    public TenKeyForm()
    {
        InitializeComponent();
        MouseDown += MouseDownHandler;

        numpad0.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("0"); });
        numpad1.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("1"); });
        numpad2.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("2"); });
        numpad3.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("3"); });
        numpad4.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("4"); });
        numpad5.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("5"); });
        numpad6.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("6"); });
        numpad7.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("7"); });
        numpad8.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("8"); });
        numpad9.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("9"); });
        numpadDot.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("."); });
        numpadBack.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("+{TAB}"); });
        numpadForward.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("{TAB}"); });
        numpadBackspace.MouseUp += new MouseEventHandler(delegate (object o, MouseEventArgs e) { SendKeys.Send("{BS}"); });

        SetStyle(ControlStyles.Selectable, false);
    }

    private void MouseDownHandler(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            ReleaseCapture();
            SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
        }
    }
}

同样,这对各种文本框、屏蔽输入等都适用,但单个组合框除外。这个 ComboBox 有一些额外的验证,以防止输入无效的选择。基本上,如果它有一个条目“500”和“550”,键入“5”会跳转到列表中的“500”,并留下除您键入的“5”之外的所有内容突出显示,以便下一次击键将替换它,即 500。此时它将拒绝除“5”或“0”以外的任何内容。输入另外 5 个突出显示 550 等等。这是该位的隐藏代码:

    private void ValidateDropDown(object sender, KeyPressEventArgs e)
    {
        ToolStripComboBox tcb = (ToolStripComboBox)sender;
        ComboBox cb = tcb.ComboBox;
        cb.DroppedDown = true;
        string strFindStr = "";
        if (e.KeyChar == (char)8)
        {
            if (cb.SelectionStart <= 1)
            {
                cb.Text = "";
                return;
            }

            if (cb.SelectionLength == 0)
                strFindStr = cb.Text.Substring(0, cb.Text.Length - 1);
            else
                strFindStr = cb.Text.Substring(0, cb.SelectionStart - 1);
        }
        else
        {
            if (cb.SelectionLength == 0)
                strFindStr = cb.Text + e.KeyChar;
            else
                strFindStr = cb.Text.Substring(0, cb.SelectionStart) + e.KeyChar;
        }
        int intIdx = -1;
        // Search the string in the ComboBox list.
        intIdx = cb.FindString(strFindStr);
        if (intIdx != -1)
        {
            cb.SelectedText = "";
            cb.SelectedIndex = intIdx;
            cb.SelectionStart = strFindStr.Length;
            cb.SelectionLength = cb.Text.Length;
            e.Handled = true;
        }
        else
            e.Handled = true;
    }

现在十键在任何地方都可以正常工作,但这个组合框除外,如果您使用实际键盘打字,这个组合框可以完美工作。屏幕键盘甚至可以在第一次按键时正常工作,但 tenkey 表单上的任何后续 mousedown 事件似乎都会在 ComboBox 上执行类似 SelectAll() 的操作,从而否定精心设置的选择。在上面的示例中键入“55”,不会导航到 550,而是导航到 500 两次,每次单击都会替换整个文本。

是什么导致了这种奇怪的行为,我该如何阻止它?

更新: 这似乎是 ToolStrip ComboBoxes 特有的问题,应该考虑将其包含在此处。另外:AutoCompleteMode = AutoCompleteMode.SuggestAppend

如何设置AutoCompleteMode

我做了测试,设置了:

AutoCompleteMode = AutoCompleteMode.Suggest;

已解决所描述的问题。

编辑 1

我已经找到解决该问题的方法,您可以添加:

toolStripComboBox1.SelectionLength=0;

SendKey 功能之前。