Interesting issue in Delphi's TDBComboBox

Core business of our company is creating Client-Server database applications and we decided to migrate all of our projects from a bit obsolete Delphi XE to Delphi 10.2. To be frank, whole migration took a very significant piece of time because we had to replace discontinued FIB Plus components set from Devrace with modern Devart IBDAC suite, especially to assure working with new versions of Firebird database server which FIBPlus does not handle any longer.

Alongside with checking and testing behavior of migrated projects in general, we found several issues when behavior of the same component was different between XE and 10.2 version but with a collaboration of suppliers of those components, we sorted out all this cases successfuly.

The last - and probably most difficult task - was to wait whether we miss some bugs or behavior changes and if and when our users will report such strange difficulties and issues. What a surprise - one quite ugly and unpleasant problem had been found and reported to us recently - it relates to common TDBComboBox component.

Let's have a typical TDBComboBox connected through DataSource and DataField to database table. As you can see on the screenshot of Object Inspector and in DFM file too, nothing strange or ambiguous is set. Note that Style property is set to csDropDown because we need to use values from attached Items list but we must also allow user to enter his custom values.

Delphi Bug Delphi Bug


object DBComboBox21: TDBComboBox
          Left = 24
          Top = 360
          Width = 145
          Height = 21
          DataField = 'NAZEV1'
          DataSource = FaktDataModule1.DataSource1
          Items.Strings = (
            'item1'
            'item2'
            'item3')
          TabOrder = 54
        end

If you navigate through the dataset using First, Last, Next or Previous method, field values are displayed correctly regardless of the fact if actual value is contained in Items property or was entered manually and differs from Items. This approach worked like a charm under Delphi XE and I expected the same in Delphi 10.2.

Alas, our customers warned us and complained that "some field values are gone while navigating among records, appear again if user navigates back, some of them are displayed always correctly". At this point I realized that there was something wrong and started to examine and debug my code together with our major components supplier. Together, we found certain ambiguous and suspicious code in TDBComboBox.SetComboText in Vcl.DBCtrls unit.


procedure TDBComboBox.SetComboText(const Value: string);
var
  I: Integer;
  Redraw: Boolean;
begin
  if Value <> GetComboText then
  begin
    if Style <> csDropDown then
    begin
      Redraw := (Style <> csSimple) and HandleAllocated;
      if Redraw then SendMessage(Handle, WM_SETREDRAW, 0, 0);
      try
        if Value = '' then I := -1 else I := Items.IndexOf(Value);
        ItemIndex := I;
      finally
        if Redraw then
        begin
          SendMessage(Handle, WM_SETREDRAW, 1, 0);
          Invalidate;
        end;
      end;
      if I >= 0 then Exit;
    end;
    if Style in [csDropDown, csSimple] then
    begin
      Text := Value;
      if Value = '' then ItemIndex := -1 else ItemIndex := Items.IndexOf(Value);
    end;
  end;
end;

It's apparently clear that last line of code cannot provide proper working in the case if given value is not found in the Items list. This code implementation causes erroneous behavior described above. However, related code for SetComboText in DBCtrls unit is the same in version XE, 10.2 and even in 10.3 - the difference is only that in XE the identical code worked okay but in 10.2 does not.

How about solution? Is quite simple, a minor change of the last part of the method will enough. Copy your Vcl.DBCtrls.pas and Vcl.DBGrids.pas from Source directory to Lib directory (keep on mind your platform, I'm talking about Lib\Win32 subdirectory, and make following changes:


procedure TDBComboBox.SetComboText(const Value: string);
var
  I: Integer;
  Redraw: Boolean;
begin
  if Value <> GetComboText then
  begin
    if Style <> csDropDown then
    begin
      Redraw := (Style <> csSimple) and HandleAllocated;
      if Redraw then SendMessage(Handle, WM_SETREDRAW, 0, 0);
      try
        if Value = '' then I := -1 else I := Items.IndexOf(Value);
        ItemIndex := I;
      finally
        if Redraw then
        begin
          SendMessage(Handle, WM_SETREDRAW, 1, 0);
          Invalidate;
        end;
      end;
      if I >= 0 then Exit;
    end;
    {if Style in [csDropDown, csSimple] then
    begin
      Text := Value;
      if Value = '' then ItemIndex := -1 else ItemIndex := Items.IndexOf(Value);
    end;}
    if Style in [csDropDown, csSimple] then
    begin
      Text := Value;
      if Value = '' then ItemIndex := -1 else
      begin
        I:=Items.IndexOf(Value);
        if I>=0 then
          ItemIndex := I;
      end;
    end;

  end;
end;

Save the changes and recompile your project. After that, you should see that appropriate values in DBComboBoxes are displayed correctly.

About the Author

Ing. Karel Janecek, MBA, MSc.
Torry.net

Unit changes:
Ing. Tomas Rosinsky
www.rosinsky.cz/delphi

More interesting links and pages



Visit GambleGenie.fi to get the best casino value in Finland


If you are going to play online casino in Canada you better visit the Genie first


KG To LBS


Casino Online Romania


Time Calculator


https://aspirecasinos.com


Wheel of Fortune Answers


Discover UK licensed casino sites at Casinopilot


Check out Valforex reviews


Efortuna Casino


Scrummaster and Agile trainings


Word Unscrambler


China Wholesale Suppliers Directory


Free Angram Solver


Syllable Word Counter


Printable Sudoku Puzzles


Download Instagram Stories


Word Search Puzzles


Try out new casino sites at SmartphoneCasinos.co.uk


https://www.applepaybingo.com


https://www.jumpmanslotsites.com


https://www.nektancasinosites.com


Percentage Calculator


Stopwatch


Indian casinos are here to stay and Royal Panda is your top choice


Best online roulette Nederland CasinoHEX


Play blackjack at the best live dealer casino online in the UK


Online Casino


Jackpot


Our favorite online real-money casinos in Austria on Casinohex.at is a great opportunity to enjoy all the benefits of playing for real money.