Using Delphi 10.3:
In an owner-drawn TComboBox with Style=csOwnerDrawFixed, I want the owner drawn items in the DropDown list to be different from the static part of the combo. To discriminate between the two cases, I check for odComboBoxEdit in the State parameter, as described here:
How to draw the static part of the combobox
procedure TStylePanel.TargetArrowComboDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
if (odComboBoxEdit in State) then
begin
// Paint static control
end
else
begin
// Paint item in dropped down list
end;
end;
This works well as long as there's no custom VCL style active. However, with a custom style, this no longer works reliably. Checking the source in Vcl.StdCtrls.pas for TComboBoxStyleHook, it seems to me that the cause is in this combination:
procedure TComboBoxStyleHook.WMPaint(...)
procedure TComboBoxStyleHook.DrawItem(...)
When there's no edit handle (which is the case for csOwnerDrawFixed), DrawItem() assembles a TDrawItemStruct that will never contain ODS_COMBOBOXEDIT, as a result the CN_DRAWITEM handler will never have odComboBoxEdit set.
I could override TComboBoxStyleHook, but I'd need a way to detect if the item is the static item or an item in the list.
As a workaround, I check for Combo.DroppedDown, but that's not the same: even when dropped down, I want the static part to be painted differently than the items in the list.
So the question is, how can I detect (in the custom draw handler or in the style hook) that the custom drawn item is the static area rather than an item in the list?
I was able to get it working by adding a stylehook for TComboBox that unconditionally includes
ODS_COMBOBOXEDIT. The assumption is thatTComboBoxStyleHook.DrawItemis only called byTComboBoxStyleHook.WMPaintwhen it needs to custom draw the static item, the drop down list is not handled there. There seem to be no unwanted side effects.