这显然是一个错误,但我无法追查为什么会发生。这是一个重现的简约代码。只需删除表单上的组合框和按钮,然后编写以下事件处理程序:
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;
当您第一次单击该按钮时,您将在组合编辑中看到第二个项目的完全选定文本,但消息框将显示项目索引等于-1。当你下拉它时,似乎选择了第二个项目。第二次单击将设置正确的文本,但其余部分将与第一次单击时相同。因此,在这种情况下,组合框的行为就像是启用了一些奇怪的自动完成。
我已将此跟踪到EditWndProc
收到字体更改后的WM_SETTEXT
消息,其中包含第二项的文字,但我不知道它来自何处以及为什么使用第二项的文字。
所以,我的问题非常具体 - 什么(哪种方法)在字体更改时发送WM_SETTEXT
,以及在禁用自动完成时它如何知道第二项文本匹配?
到目前为止,我可以在安装了最新更新的Windows 7 Home Premium 64位上在Delphi 2009和Delphi XE3中重现这一点。
答案 0 :(得分:4)
您可以通过简单地启用调试DCU然后单步执行Font.Color
属性设置器,在几秒钟内自行跟踪。
当因任何原因更改Font
时,会触发TFont.OnChange
事件。 TControl
有一个事件处理程序,即使这样它也可以向自己发送一条CM_FONTCHANGED
消息,以允许后代类对更改作出反应。当TWinControl
收到该消息时,它会向自己发送一条WM_SETFONT
消息,然后触发ComCtl32发送您正在看到的WM_SETTEXT
消息。
答案 1 :(得分:2)
我不认为这是一个VCL问题,看着调用堆栈,似乎消息似乎是通过comctl32.dll处理的。 您可以在设置文本之前设置字体颜色来解决问题:
procedure TForm1.Button1Click(Sender: TObject);
begin
ComboBox1.Font.Color := clRed;
ComboBox1.Text := 'B';
ShowMessage(IntToStr(ComboBox1.ItemIndex));
end;
答案 2 :(得分:0)
我使用Delphi XE8进行的实验似乎表明,只要您第一次开始使用TComboBox并且在您之前强制执行字体更改请求(例如,只需将颜色设置为clBlack,即使它已经是),也可能就足够了首先写文字给它。将WM_SETTEXT选中错误文本的方法仅在第一次写入字体颜色(或其他字体属性)时发生。在那之后,一切都表现得很好。无论是Windows还是Delphi中的错误,我都无法找到答案,因为这个技巧为我解决了这个问题。 :)但是,我怀疑这是“初始化之前的动作”的另一种情况,因为当你为用户提供大量的后期构建时,编码器没有考虑到事情并不总是以方便的顺序调用的事实配置属性(例如更改尚未使用的TCombobox中的字体和文本)。如果这确实是一个“万灵药”,那么也许我们应该说服Delphi团队将它放入我们的TCombobox(或祖先)构造函数中。顺便说一句,同样的“错误”导致SelLength从零变化 - 非常烦人,因为它最终将文本框着色为蓝色暗示焦点,而焦点则不是!因此,如果你的表单上有很多组合框,都显示蓝色并声称有焦点 - 这也是特别令人头痛的根源!
顺便提一下,我已经用Embarcadero提出了这个问题,并提出了一个解决方案,将上述技巧合并到基础构造函数中。他们把它传递给了程序员,但是新版本的Delphi是否会包含必要的修复还有待观察。