2007. július 27., péntek

Attach a TComboBox to the column of a TStringGrid


Problem/Question/Abstract:

How to attach a TComboBox to the column of a TStringGrid

Answer:

Solve 1:

Here is one way to do it, using a single combobox that moves from cell to cell as required.

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
    { Private declarations }
    procedure CMDialogKey(var msg: TCMDialogKey); message CM_DIALOGKEY;
  public
    { Public declarations }
  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
      {set focus back to the grid and pass the tab key to it}
      stringgrid1.setfocus;
      stringgrid1.perform(WM_KEYDOWN, msg.charcode, msg.keydata);
      {swallow this message}
      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.visible := false;
end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
var
  R: TRect;
  org: TPoint;
begin
  with Sender as TStringGrid do
    if (ACol = 2) and (ARow >= FixedRows) then
    begin
      {entered the column associated to the combobox}
      {get grid out of selection mode}
      perform(WM_CANCELMODE, 0, 0);
      {position the control on top of the cell}
      R := CellRect(Acol, Arow);
      org := Self.ScreenToClient(ClientToScreen(R.topleft));
      with ComboBox1 do
      begin
        setbounds(org.X, org.Y, r.right - r.left, height);
        itemindex := Items.IndexOf(Cells[acol, arow]);
        Show;
        BringTofront;
        {focus the combobox and drop down the list}
        SetFocus;
        DroppedDown := true;
      end;
    end;
end;

end.


Solve 2:

unit GridCombo;

interface

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

type
  TFrmGridCombo = class(TForm)
    StringGrid1: TStringGrid;
    BtnSave: TButton;
    StringGrid2: TStringGrid;
    BtnLoad: TButton;
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var
      CanSelect: Boolean);
  private
    FCBox: TComboBox;
    procedure ComboClick(Sender: TObject);
  public
    { Public declarations }
  end;

var
  FrmGridCombo: TFrmGridCombo;

implementation

{$R *.DFM}

procedure TFrmGridCombo.StringGrid1SelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
var
  thisRect: TRect; {Notational clarity.}
begin
  if (ARow = 1) and (ACol <> 0) then
  begin
    if Assigned(FCBox) then
      FCBox.Free;
    FCBox := TComboBox.Create(self);
    FCBox.Parent := self;
    thisRect := StringGrid1.CellRect(ACol, ARow);
    FCBox.Left := thisRect.Left + StringGrid1.Left + 2;
    FCBox.Top := thisRect.Top + StringGrid1.Top + 2;
    FCBox.Width := (thisRect.Right - thisRect.Left);
    FCBox.Height := (thisRect.Bottom - thisRect.Top);
    FCBox.Items.LoadFromFile('File2.Txt');
    FCBox.SetFocus;
    FCBox.OnClick := ComboClick;
  end
  else if Assigned(FCBox) then
  begin
    FCBox.Free;
    FCBox := nil;
  end;
end;

procedure TFrmGridCombo.ComboClick(Sender: TObject);
begin
  if Sender is TComboBox then
    StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := TComboBox(Sender).Text;
end;

end.

Nincsenek megjegyzések:

Megjegyzés küldése