Как остановить открытие ComboBox по Ctrl-Enter? - PullRequest
0 голосов
/ 10 марта 2019

Winforms C #. Попытка заставить Ctrl-Enter на ComboBox выполнять специфические для программы вещи, а не что-нибудь еще.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        ComboBox cb = new ComboBox();
        cb.DropDownStyle = ComboBoxStyle.DropDownList;
        cb.AutoCompleteSource = AutoCompleteSource.ListItems;
        cb.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        cb.Location = new System.Drawing.Point(20,50);
        cb.KeyDown += new System.Windows.Forms.KeyEventHandler(CBKeyDown);
        cb.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(CBPreviewKeyDown);
        cb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(CBKeyPress);
        this.Controls.Add(cb);

        List<string> someThings = new List<string>();
        someThings.Add("An item");
        someThings.Add("Another item");

        cb.DataSource = someThings; 
    }

    private void CBPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.Enter:
                if (e.Control)
                { 
                    e.IsInputKey = true;
                }

                break;
        }
    }

    private void CBKeyDown(object sender, KeyEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.Enter:
                if (e.Control)
                {
                    //Do application specific stuff
                    e.Handled = true;
                }

                break;
        }
    }

    private void CBKeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == '\n')
        {
            e.Handled = true;
        }
    }
}

Когда ComboBox имеет фокус, и я нажимаю Ctrl-Enter, раскрывающееся меню ComboBox появляется в ответ на нажатие клавиши, даже если я установил e.handled = true. Я подтвердил, что проблема связана с функцией ComboBox AutoCompleteMode Suggest. Если эта строка закомментирована или изменена на «Добавить», она прекращает это делать. Но мне нравится функция автозаполнения, и я хочу сохранить ее, если смогу.

Я прошел с отладчиком и убедился, что раскрывающийся список появляется после того, как код прошел через e.handled = true в событии KeyDown, но до того, как событие KeyPress произойдет.

Как я могу заставить ComboBox не отвечать на Ctrl-Enter, за исключением случаев, когда я прямо указываю?

Ответы [ 2 ]

2 голосов
/ 10 марта 2019

Вы можете обработать это в производном ComboBox путем переопределения ProcessCmdKey Method .

Добавьте это определение класса в ваш проект и выполните встроенную операцию. Элемент управления отобразится на панели инструментов (при условии, что VS настроен на добавление пользовательских элементов управления) в верхней части раздела «Имя вашего проекта». Этот класс предоставляет событие ControlEnterPressed, чтобы облегчить выполнение желаемого действия по нажатию клавиши.

public class CB : ComboBox
{
    public event Action<CB> ControlEnterPressed;

    protected virtual void OnControlEnterPressed()
    {
        ControlEnterPressed?.Invoke(this);
    }

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        System.Diagnostics.Debug.Print(keyData.ToString());
        // runs before ProcessDialogKey, ProcessDialogKey is called if this method returns false
        bool ret = false;
        if ((keyData.HasFlag(Keys.Control) || keyData.HasFlag(Keys.ControlKey)) && (keyData.HasFlag(Keys.Return) || keyData.HasFlag(Keys.Enter)))
        {
            BeginInvoke(new Action(OnControlEnterPressed)); //let message processing finish before raising the event
            ret = true;   // indicate key handled
        }
        else
        {
            ret = base.ProcessCmdKey(ref msg, keyData);
        }
        return ret;
    }

}
1 голос
/ 10 марта 2019

Альтернативный подход - установить высоту выпадающего меню на 1.

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    ComboBox cb = new ComboBox();
    cb.DropDownStyle = ComboBoxStyle.DropDownList;
    cb.AutoCompleteSource = AutoCompleteSource.ListItems;
    cb.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
    cb.Location = new System.Drawing.Point(20, 50);
    cb.KeyDown += new System.Windows.Forms.KeyEventHandler(CBKeyDown);
    cb.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(CBPreviewKeyDown);
    cb.KeyPress += new System.Windows.Forms.KeyPressEventHandler(CBKeyPress);
    this.Controls.Add(cb);

    List<string> someThings = new List<string>();
    someThings.Add("An item");
    someThings.Add("Another item");

    cb.DataSource = someThings;
}

private void CBPreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
    switch (e.KeyCode)
    {
        case Keys.Enter:
            if (e.Control)
            {
                e.IsInputKey = true;
            }

            break;
    }

    // Return back drop down height, in case ctrl + enter keys were pressed
    (sender as ComboBox).DropDownHeight = 100;
}

private void CBKeyDown(object sender, KeyEventArgs e)
{
    switch (e.KeyCode)
    {
        case Keys.Enter:
            if (e.Control)
            {
                // Do application specific stuff
                e.Handled = true;

                // Set drop down height to 1, in order to set height
                // that looks like drop down is not showed at all (only 1 pixel)
                (sender as ComboBox).DropDownHeight = 1;
            }

            break;
    }
}


private void CBKeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == '\n')
    {
        e.Handled = true;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...