Пользовательская экранная клавиатура и раскрывающийся список с фильтрами не работают должным образом

В моем приложении 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. Этот 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;
    }

Теперь десятиклавишный текст отлично работает везде, кроме этого ComboBox, и этот ComboBox отлично работает, если вы печатаете на настоящей клавиатуре. Экранная клавиатура работает корректно даже при первом нажатии клавиши, но любое последующее событие mousedown в форме с тенкей, кажется, выполняет что-то вроде SelectAll() в поле со списком, тем самым сводя на нет тщательно установленный выбор. Ввод «55» в приведенном выше примере не приводит к переходу к 550, а вместо этого дважды переходит к 500, заменяя весь текст при каждом щелчке.

Что вызывает это странное поведение и как я могу его остановить?

Обновление: похоже, это проблема, связанная с выпадающими списками ToolStrip ComboBox, и ее следовало включить сюда. Также: AutoCompleteMode = AutoCompleteMode.SuggestAppend


person David Perry    schedule 03.01.2017    source источник


Ответы (1)


Как установить AutoCompleteMode?

Я сделал тест и установил его:

AutoCompleteMode = AutoCompleteMode.Suggest;

решена описанная проблема.

ИЗМЕНИТЬ 1

Я нашел обходной путь для этой проблемы, вы можете добавить:

toolStripComboBox1.SelectionLength=0;

перед функцией SendKey.

person mjpolak    schedule 03.01.2017
comment
SuggestAppend — моя текущая настройка. Установка его в Suggest вообще не меняет поведение. Имеет ли значение, что это поле со списком инструментов? - person David Perry; 03.01.2017
comment
Может быть, это случай! Я добавил поле со списком в панель инструментов, и происходит то же самое. Ищем обходной путь. - person mjpolak; 03.01.2017
comment
Ну, по крайней мере, я не сумасшедший. Ничего более неудовлетворительного, чем не удалось воспроизвести. - person David Perry; 03.01.2017
comment
Хм, кажется, этот обходной путь не работает с моей стороны. Является ли ваша форма tenkey дочерней формой MDI с помощью toolstripcombobox? - person David Perry; 04.01.2017
comment
Можете ли вы добавить toolStripComboBox1.Focus(); перед SelectionLength=0; ? - person mjpolak; 04.01.2017
comment
Я мог бы, но тогда это сломало бы ключ для каждого элемента формы, ИСКЛЮЧАЯ поле со списком. :( - person David Perry; 04.01.2017
comment
Я думаю, что я просто переработаю свой пользовательский интерфейс, чтобы я мог использовать обычное поле со списком, и в этот момент ваш ответ работает. Очевидно, что что-то в элементе управления ToolStripComboBox странное/сломанное, поэтому я просто не буду его использовать. - person David Perry; 04.01.2017