views:

394

answers:

4

I derived a class from ComboBox, made it an owner drawn list box (DrawMode.OwnerDrawVariable style), and by overriding OnMeasureItem and OnDrawItem I add special items to the drop-down list (separators, for example) which are of a smaller/larger size than the normal items that inhabit the control.

Now, the problem I'm having and can't seem to effectively remedy is the sizing of the drop-down list: there's an ugly empty space at the end of the list when it drops down. I thought I tackled this by setting the DropDownHeight property of the ComboBox to the sum of all the items' height, but this doesn't seem to work all the time. Sometimes, on a random number of items, the Empty White Space of Doom returns. This is an unusual problem, but hopefully a common and easily fixed one.

How can I get the ComboBox's drop-down list to size precisely to the size occupied by the items inside of it?

+1  A: 

I guess the problem in the way how you're calculating your dropdown list height, I guess it's smth like this:

comboBox.DropDownHeight = N_of_items * item_height;

the total height of the dropdown list should also include its top and bottom border height, so if you would do smth like this:

comboBox.DropDownHeight = N_of_items * item_height + SystemInformation.BorderSize.Height*2;

it should do the trick and show the dropdown list without white areas

hope this helps, regards

serge_gubenko
+2  A: 

I'm seeing a pretty silly bug in the ComboBox.UpdateDropDownHeight() method. When the DropDownHeight property matches the default value, it calculates a custom height to fit the dropdown to the number of items. It does this even when you changed the DrawMode, that's plain wrong.

The workaround:

  int height = ...; // Your code here
  if (height == 106) ++height;
  comboBox1.DropDownHeight = height;

You'll get a one pixel gap, you should be able to hide that in your OnDrawItem() overload.

Hans Passant
This bug extends a little deeper than that. The default value of DropDownHeight is based on the font size of the item(s) in the combobox. Any alteration in the height of an individual item that is not based on a change in font size will cause a problem with the DropDownHeight property.
Stewbob
No, the default size is hardcoded in a constant, have a look-see in the Reference Source. It is named "DefaultDropDownHeight". If your theory is correct, you should see this much more frequently. Especially since you implement OnMeasureItem, the item height will always be nonstandard. I'm forced to guess here, your question has no hint what might trigger the gap's appearance.
Hans Passant
@nobugz: Yeah, you're right. I typed faster than I thought. The Item Height is based on the font size. Which, in certain cases, is what is used to determine the maximum value of the DropDownHeight.
Stewbob
Good job figuring this out. I guess the gap isn't so random, it only reappears when the height equals 106 as you showed. Thanks!
Siege
Whooptidoo, score one for psychic debugging. This has to byte a lot of people using DrawMode.OwnerDrawVariable. Hopefully they'll find this post. Thanks for letting us know.
Hans Passant
+1  A: 

I spent a long time battling this same problem.

When you are adding custom items to the combobox, the DropDownHeight will not set properly. In order to guarantee that you get it set right every time, you need to hijack a Windows Message.

This post shows how. Just keep track of the height of all the items (standard and custom) in your combobox, and then set the total height of the dropdown portion like shown in the example.

Stewbob
A: 

Your writing is very elegant, very vivid and lively, I really like you, wish you continued to write better articles, I will often try to concern, oh!

ugg boots