Как сделать комбо-бокс для измерения высоты элемента? - PullRequest
1 голос
/ 20 января 2010

Я создаю пользовательский комбинированный список, который может рисовать разделители.Итак, я переопределяю методы OnDrawItem () и OnMeasureItem ().
Проблема в том, что OnMeasureItem () вызывается только один раз при изменении источника данных.Поэтому, если я хочу указать элемент-разделитель позже, мне нужно измерить его высоту (потому что элементы с разделителем должны быть выше), но кажется, что все методы, которые могут привести к измерению высоты элемента, являются частными, поэтому я не могу вызвать их.
Я не знаю, легко ли понять то, что я написал выше, поэтому я повторю то, что мне нужно:
Мне нужно пересматривать высоту элемента (OnMeasureItem () должен вызываться) каждый раз, когда яукажите, что элемент должен быть нарисован с разделителем.

separatorableComboBox.DataSource = customers;
// and now I want the third customer in the list to be drawn with a separator, 
// so it needs to be taller and therefore OnMeasureItem() should be called
separatorableComboBox.SpecifySeparatorItem(customers[2]);

UPD. Парни, вызывающие RefreshItems (), работают, но работают очень медленно (> 20 мс на моем компьютере)есть более быстрые методы?
UPD2. Прямо сейчас я использую SendMessage (..., CB_SETITEMHEIGHT, ...);метод, как советовал serge_gubenko.Но мне просто любопытно, есть ли быстрый способ выполнить задачу с помощью .NET (или, точнее, с помощью самого класса ComboBox)?

Ответы [ 2 ]

4 голосов
/ 20 января 2010

Вы можете позвонить ComboBox.RefreshItems(), чтобы набрать MeasureItem() вызовов, либо внутри вашего SpecifySeparatorItem() вашего класса CustomCombo:

public void SpecifySeparatorItem(object arg)
{
    //do some stuff

    this.RefreshItems();

    //do some more stuff
}

Или выставив ComboBox.RefreshItems() через публичный метод, который можно вызвать в другом месте

public partial class CustomCombo : ComboBox
{
    public CustomCombo ()
    {
        InitializeComponent();
    }

    protected override void OnMeasureItem(MeasureItemEventArgs e)
    {
        base.OnMeasureItem(e);
    }

    public void RaiseOnMeasureItem()
    {
        this.RefreshItems();
    }
}
3 голосов
/ 20 января 2010

Просто чтобы прояснить, я предполагаю, что вы используете стиль OwnerDrawVariable для своего комбинированного списка. Если я правильно понял ваш вопрос, есть несколько способов сделать то, что вам нужно:

  • Вызовите RefreshItems метод комбинированного списка, который воссоздает элементы и вызывает событие onMeasureItem для каждого элемента. Этот метод защищен для класса ComboBox, поэтому ниже приведен пример того, как вы можете сделать это с помощью отражения:
    MethodInfo method = comboBox1.GetType().GetMethod(
        "RefreshItems", BindingFlags.Instance | BindingFlags.NonPublic);
    if (method != null) method.Invoke(comboBox1, null);
  • Отправьте сообщение CB_SETITEMHEIGHT на элемент управления с новой высотой элемента, если вы хотите изменить его:
    public const int CB_SETITEMHEIGHT = 0x0153;
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
    ...
    // this will set height to 100 for the item with index 2 
    SendMessage(comboBox1.Handle, CB_SETITEMHEIGHT, 2, 100); 

Надеюсь, это поможет, с уважением

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