Home » Tipps & Tricks » Komponenten » TStringGrid » Combobox in ein StringGrid einbauen

Combobox in ein StringGrid einbauen

Will man in einer Zelle eines Stringgrids nur bestimmte Werte zulassen, die aus einer Combobox ausgewählt werden sollen, ist etwas Arbeit notwendig. Auf Form1 wird ein normales StringGrid gesetzt. Auf dieses StringGrid kommt eine normale ComboBox, die die zulässigen Werte enthält. Die Combobox wird bei Programmstart unsichtbar gemacht. Erst, wenn der Anwender in die betroffene Spalte des StringGrids kommt, wird sie sichtbar und über der aktiven Zelle eingeblendet. Bei Verlassen der Zelle, wird sie wieder unsichtbar gemacht. Im Beispiel werden alle Zellen der dritten Spalte mit einer Combobox versehen (Methode StringGrid1SelectCell: if (ACol=2)…).

unit Unit1;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    ComboBox1: TComboBox;
    procedure ComboBox1Exit(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    private
      procedure CMDialogKey(var msg: TCMDialogKey); message CM_DIALOGKEY;
    public
  end;

var Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.CMDialogKey(var msg: TCMDialogKey);
begin
  if ActiveControl = ComboBox1 then begin
    if msg.CharCode = VK_TAB then begin
      // setzt den Fokus zurück auf das StringGrid
      StringGrid1.SetFocus;
      StringGrid1.Perform(WM_KEYDOWN, msg.CharCode, msg.KeyData);
      msg.Result := 1;
      exit;
    end;
  end;
  inherited;
end;

procedure TForm1.ComboBox1Exit(Sender: TObject);
begin
  with sender as TComboBox do begin
    hide;
    if ItemIndex >= 0 then
      with StringGrid1 do
        Cells[col, row] := Items[ItemIndex];
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Combobox1.Parent := Stringgrid1;
  ComboBox1.Visible := False;
end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
var
  R: TRect;
  org: TPoint;
begin
  if (ACol = 2) and (ARow >= StringGrid1.FixedRows) then begin
    StringGrid1.Perform(WM_CANCELMODE, 0, 0);
    R := StringGrid1.CellRect(ACol, ARow);
    org := self.ScreenToClient(self.ClientToScreen(R.TopLeft));
    with ComboBox1 do begin
      SetBounds(org.X, org.Y, R.Right-R.Left, Stringgrid1.Height);
      ItemIndex := Items.IndexOf(StringGrid1.Cells[ACol, ARow]);
      Show;
      BringToFront;
      SetFocus;
      DroppedDown := true;
    end;
  end;
end;

end.