Why does the combo box change text to element text when the font changes?

This is obviously a mistake, but I can’t track why this is happening. Here is the minimalist code to play. Just clear the combo box and button in the 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 press the button for the first time, you will see in the combined editing the fully selected text of the second element, but in the message box you will see that the index of the element is -1. When you lower it, the second element is selected. A second click will set the correct text, but the rest will be the same as the first click. Thus, the combo box in this case behaves as if some strange autocompletion was involved.

I traced this to EditWndProc , where after receiving a font change, the message WM_SETTEXT with the text of the second element, but I do not know where it came from and why with the text of the second paragraph.

So, my question is quite specific - what (which method) sends WM_SETTEXT when the font changes and how does it know about the coincidence of the text of the second element when auto-completion is disabled?

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

+4
source share
3 answers

I don’t think this is a VCL problem, looking at the call stack, it seems that the message seems to be processed 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; 
+2
source

You could track this in a few seconds just by turning on the debug DCU, and then go to the Font.Color property Font.Color .

When the Font value is changed for any reason, the TFont.OnChange event is TFont.OnChange . TControl has an event handler assigned to this, even if it can send the CM_FONTCHANGED message CM_FONTCHANGED to allow descendant classes to respond to the change. When TWinControl receives this message, it sends the WM_SETFONT message to itself, which then runs ComCtl32 to send the WM_SETTEXT message you see.

+4
source

My experiments with Delphi XE8 show that it might be enough to force a request to change the font (say, just setting the color in clBlack, even if it already exists), as soon as you first start using TComboBox and write the text in front of you first. It is clear that WM_SETTEXT selects the wrong text, this only happens the first time a font is written (or other font attributes). After that, everything behaves correctly. Whether this is a bug in Windows or Delphi, I couldn’t bother to find out, since this trick cured the problem for me. :) I suspect, however, that this is another case of the “pre-initialization action” that encoders didn’t take into account the fact that things are not always called in a convenient manner when you provide your users with a lot of post-constructs (for example, changing fonts and text in an unused TCombobox). If this proves to be a “cure”, then perhaps we should convince the Delphi team to put it in the TCombobox (or ancestor) constructor for us. By the way, this same “mistake” leads to the fact that SelLength changes from scratch - it’s very annoying because it finishes coloring the text field in blue, which implies focus when it does not focus on it! Therefore, if you get a lot of comboboxes in your form, everyone appears in blue and claims that you have a focus - this is also the source of this particular headache!

By the way, I raised this problem with Embarcadero and proposed a solution in which the above trick is included in the base constructor. They passed it to the coders, but it remains to be seen whether new versions of Delphi will include the necessary fix.

0
source

Source: https://habr.com/ru/post/1438746/


All Articles