fullerm
fullerm

Reputation: 468

Add DBLookupCombobox to Delphi DBGrid

I'd like to add DBLookupComboboxes to certain columns in a DBGrid. There is a nice article on About.com on how to do this here. The problem is that with a table having many columns, if you select from the DBLookupCombobox in one column and then try to scroll left, the combobox will move left too as shown in the included images. How can the About.com code can be changed to prevent this behavior? A web search showed two others complaining of the exact same problem with no solution. Note that I want to use a DBLookupCombobox to show a name but enter the id, so using a simple picklist will not do.

using combobox scroll left

procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
  if DBGrid1.SelectedField.FieldName = DBLookupComboBox1.DataField then
    DBLookupComboBox1.Visible := False
end;

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if (gdFocused in State) then
  begin
    if (Column.Field.FieldName = DBLookupComboBox1.DataField) then
    with DBLookupComboBox1 do
    begin
      Left := Rect.Left + DBGrid1.Left + 2;
      Top := Rect.Top + DBGrid1.Top + 2;
      Width := Rect.Right - Rect.Left;
      Width := Rect.Right - Rect.Left;
      Height := Rect.Bottom - Rect.Top;

      Visible := True;
    end;
  end
end;

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
  if (key = Chr(9)) then Exit;

  if (DBGrid1.SelectedField.FieldName = DBLookupComboBox1.DataField) then
  begin
    DBLookupComboBox1.SetFocus;
    SendMessage(DBLookupComboBox1.Handle, WM_Char, word(Key), 0);
  end
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 with DBLookupComboBox1 do
 begin
   DataSource := DataSource1; // -> AdoTable1 -> DBGrid1
   ListSource := DataSource2;
   DataField   := 'resource_id'; // from AdoTable1 - displayed in the DBGrid
   KeyField  := 'id';
   ListField := 'resource_name; id';

   Visible    := False;
 end;

 DataSource2.DataSet := AdoQuery1;

 AdoQuery1.Connection := AdoConnection1;
 AdoQuery1.SQL.Text := 'SELECT id,resource_name FROM resources';
 AdoQuery1.Open;
end;

Upvotes: 4

Views: 6842

Answers (1)

fullerm
fullerm

Reputation: 468

Here is one solution using a neat hack from François.

type
    // Hack to redeclare your TDBGrid here without the the form designer going mad
    TDBGrid = class(DBGrids.TDBGrid)
      procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
    end;

  TForm1 = class(TForm)
[...]
procedure TDBGrid.WMHScroll(var Msg: TWMHScroll);
begin
  if Form1.DBGrid1.SelectedField.FieldName = Form1.DBLookupComboBox1.DataField then begin
    case Msg.ScrollCode of
      SB_LEFT,SB_LINELEFT,SB_PAGELEFT: begin
        Form1.DBGrid1.SelectedIndex := Form1.DBGrid1.SelectedIndex-1;
        Form1.DBLookupComboBox1.Visible := False;
      end;
      SB_RIGHT,SB_LINERIGHT,SB_PAGERIGHT: begin
        Form1.DBGrid1.SelectedIndex := Form1.DBGrid1.SelectedIndex+1;
        Form1.DBLookupComboBox1.Visible := False;
      end;
    end;
  end;
  inherited; // to keep the expected behavior
end;

Upvotes: 1

Related Questions