如何使组合框重新测量物品高度?

时间:2010-01-20 02:45:05

标签: c# .net winforms custom-controls

我正在创建一个可以绘制分隔符的自定义组合框。所以,我重写了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 个答案:

答案 0 :(得分:4)

您可以致电ComboBox.RefreshItems(),以便在您的CustomCombo课程MeasureItem()内提出SpecifySeparatorItem()来电:

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();
    }
}

答案 1 :(得分:3)

为了澄清,我假设您使用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); 

希望这有帮助,尊重