Установка SelectedIndex в обработчике событий DropDown ComboBox - PullRequest
3 голосов
/ 01 июля 2010

Недавно я воспроизвел странное поведение этого сообщения на своей Windows 7. Может быть, это функция, и, возможно, это не зависит от Windows 7, пожалуйста, исправьте меня, если это правильное поведение.В MSDN мы видим

Приложение отправляет сообщение CB_SETCURSEL для выбора строки в списке поля со списком.При необходимости список прокручивает строку в поле зрения.Текст в элементе управления редактирования поля со списком изменяется, чтобы отразить новый выбор, и любой предыдущий выбор в списке удаляется.

Фрагмент кода ниже описывает горячее воспроизведение:

private void ReproduceBehaviour()
{
    ComboBox comboBox = new ComboBox();
    Controls.Add(comboBox);
    comboBox.DataSource = new List<string> { "A", "b", "B", "C" };
    comboBox.DropDown += new EventHandler((o, e) => { comboBox.SelectedIndex = 2; });
}

Итак, когда мы устанавливаем SelectedIndex = 2 в раскрывающемся списке, должен быть выбран элемент «B».Но мне странно, что пункт "b" (с индексом = 1) становится выделенным!Мы можем отправить сообщение CB_SETCURCELL напрямую, ничего не изменилось:

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
private void ReproduceBehaviour()
{
    ComboBox comboBox = new ComboBox();
    Controls.Add(comboBox);
    comboBox.DataSource = new List<string> { "A", "b", "B", "C" };
    comboBox.DropDown += new EventHandler((o, e) => { SendMessage(comboBox.Handle, 0x14e, 2, 0); });
}

Эта функция (?! O_O) или что я делаю неправильно?Спасибо за ответы.

UPD.В соответствии с рекомендациями, я попытался установить выделение для списка вручную в выпадающем списке событий.Безрезультатно: (

private void ReproduceBehaviour()
{

    ComboBox comboBox = new ComboBox();
    Controls.Add(comboBox);
    comboBox.DataSource = new List<string> { "A", "b", "B", "C" };
    comboBox.DropDown += new EventHandler((o, e) =>
    {
        SendMessage(comboBox.Handle, 0x14e, 2, 0); // CB_SETCURSEL
        ComboBoxInfo pcbi = new ComboBoxInfo();
        pcbi.cbSize = Marshal.SizeOf(pcbi);
        GetComboBoxInfo(comboBox.Handle, ref pcbi);
        IntPtr result = SendMessage(pcbi.hwndList, 0x0186, 2, 0); // LB_SETCURSEL
    });
}

Мне пришлось использовать LB_SETCURSEL, потому что LB_SETSEL вернул LB_ERR (LB_SELSET доступен только для многоселективных списков, но в ComboBox используется односелективный список). Вызов метода

IntPtr result = SendMessage(pcbi.hwndList, 0x0186, 2, 0); // LB_SETCURSEL

возвращаетзначение '2', поэтому я предполагаю, что выбор был успешно установлен. Но когда раскрывающийся список полностью открыт, он обычно выбирает неверное значение :( Может быть, событие DropDown не подходит для этого? Я в замешательстве.

1 Ответ

2 голосов
/ 01 июля 2010

Это не работает так, как вы думаете. Присваивая свойство SelectedIndex, вы не выбираете элемент раскрывающегося списка, вы устанавливаете текст в части текстового поля поля со списком. Раскрывающийся список реагирует на это, выбирая элемент списка, соответствующий тексту текстового поля. Проблема в том, что это происходит без учета регистра.

Вы можете легко убедиться в этом сами, установив второй пункт, скажем, «D». Это исправляет это. Или установите для первого элемента значение «b», теперь первый элемент выбран.

Нет, это не легко исправить. Сложнее всего получить дескриптор элемента управления listbox в выпадающем событии с CB_GETCOMBOBOXINFO, а затем отправить ему сообщение LB_SETSEL. Прагматическое исправление состоит в том, чтобы элементы списка не отличались только регистром. В любом случае имеет тенденцию вводить пользователя в заблуждение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...