Question

It's obviously a bug, but I cannot track down why happens. Here is a minimalistic code to reproduce. Just drop a combo box and button on a form and write the following event handlers:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ComboBox1.Items.Add('A Item');
  ComboBox1.Items.Add('B Item');
  ComboBox1.Items.Add('C Item');
  ComboBox1.Style := csDropDown;
  ComboBox1.AutoComplete := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ComboBox1.Text := 'B';
  ComboBox1.Font.Color := clRed;
  ShowMessage(IntToStr(ComboBox1.ItemIndex));
end;

When you click the button for the first time, you will see in the combo edit fully selected text of the second item, but message box will show you the item index equals to -1. When you drop down it, the second item seems to be selected. The second click will set the proper text though, but the rest will be the same as at the first click. So, combo box in this case behaves like if some weird autocompletion would be enabled.

I've tracked this down to the EditWndProc where after font change is received WM_SETTEXT message with the text of the second item, but I don't know where it comes from and why with the text of the second item.

So, my question is quite specific - what (which method) sends the WM_SETTEXT at font change and how does it know about second item text match when the autocompletion is disabled ?

So far I could reproduce this in Delphi 2009 and Delphi XE3 on Windows 7 Home Premium 64-bit with the most recent updates installed.

Était-ce utile?

La solution

I don't think this is a VCL issue, looking at the call stack, it seems that message seems is handled through comctl32.dll. You can solve the problem by setting the font color before setting the text:

procedure TForm1.Button1Click(Sender: TObject);
begin
  ComboBox1.Font.Color := clRed;
  ComboBox1.Text := 'B';
  ShowMessage(IntToStr(ComboBox1.ItemIndex));
end;

Autres conseils

You could have tracked this down yourself in a few seconds by simply enabling Debug DCUs and then stepping into the Font.Color property setter.

When the Font is changed for any reason, the TFont.OnChange event is triggered. TControl has an event handler assigned to that even so it can send itself a CM_FONTCHANGED message to allow descendant classes to react to the change. When TWinControl receives that message, it sends a WM_SETFONT message to itself, which then triggers ComCtl32 to send the WM_SETTEXT message that you are seeing.

My experiments with Delphi XE8 appear to show that it may be sufficient to force a font change request (say just by setting color to clBlack, even if it already is) as soon as you first start to use the TComboBox and before you first write text to it. Methinks the WM_SETTEXT picking the wrong text only happens the FIRST time the font color (or other font attributes) are written to. After that, everything behaves properly. Whether it is a bug in Windows or Delphi, I couldn't be bothered to find out, since this trick cured the problem for me. :) I suspect, however, that it is another case of "action before initialization" in that the coders did not account for the fact that things do not always get invoked in a convenient order when you provide your users with lots of post-construction configuration properties (such as changing fonts and text in an as-yet unused TCombobox). If this does turn out to be a "cure-all" then perhaps we should persuade the Delphi team to put it into the TCombobox (or ancestor) constructor for us. Incidentally, this same "bug" causes SelLength to change from zero - very annoying because it ends up coloring the text box in blue implying focus, when focused it is not! So if you get lots of comboboxes on your form all displaying blue and claiming to have focus - this is the source of that particular headache too!

Incidentally, I have raised this problem with Embarcadero and suggested a solution whereby the above trick is incorporated into the base constructor. They passed it down to the coders, but it remains to be seen whether newer versions of Delphi will include the necessary fix.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top