[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4211
  • Last Modified:

EditBox inside StringGrid

Hi Experts,
based on http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_20369496.html I tried to replace the combobox with editbox (TEdit). On the form is a stringgrid and an editbox. The control positioned well in the stringgrid. But I can write into this editbox only one character and the editbox disappears and it's content won't be transferred into the stringgrid cell. I added the InputEnd variable to signalize the end of input but this didn't helped.
One more question: I don't understand the role of the CMDialogKey procedure.
thanks
Janos
unit Main;
 
interface
 
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids;
 
type
  TfrmMain = class(TForm)
    StringGrid1: TStringGrid;
    edbInplaceEditbox: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure StringGrid1SelectCell(Sender: TObject; ACol,
      ARow: Integer; var CanSelect: Boolean);
    procedure StringGrid1DrawCell(Sender: TObject; Col, Row: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure edbInplaceEditboxChange(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
 
  private
    { Private declarations }
    procedure CMDialogKey(var msg: TCMDialogKey); message CM_DIALOGKEY;
  public
    { Public declarations }
  end;
 
var
  frmMain: TfrmMain;
  InputEnd: Boolean;
 
implementation
 
{$R *.DFM}
 
procedure TfrmMain.FormCreate(Sender: TObject);
var i: Integer;
begin
  StringGrid1.DefaultRowHeight := edbInplaceEditbox.Height;
  edbInplaceEditbox.Visible := False;
  StringGrid1.Cells[0, 0] := 'Column1';
  for i := 1 to StringGrid1.RowCount-1 do
    StringGrid1.Cells[0, i] := IntToStr(i);
end;
 
procedure TfrmMain.CMDialogKey(var msg: TCMDialogKey);
begin
  if (ActiveControl = edbInplaceEditbox) then
  begin
    if (msg.CharCode = VK_TAB) then
    begin
      //set focus back to the grid and pass the tab key to it
      edbInplaceEditbox.SetFocus;
      edbInplaceEditbox.Perform(WM_KEYDOWN, msg.CharCode, msg.KeyData);
      // swallow this message
      msg.result := 1;
      Exit;
    end;
  end;
  inherited;
end;
 
procedure TfrmMain.edbInplaceEditboxChange(Sender: TObject);
var
  intRow: Integer;
begin
  inherited;
  {get the selection of the EditBox and place onto grid}
  with edbInplaceEditbox do
  begin
    intRow := StringGrid1.Row;
    if ((StringGrid1.Col = 0) and (InputEnd = true)) then
    begin
      StringGrid1.Cells[0, intRow] := edbInplaceEditbox.Text;
    end;
    Visible := False;
  end;
  StringGrid1.SetFocus;
end;
 
procedure TfrmMain.StringGrid1SelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
var R: TRect;
begin
  {Position of the control to place onto grid}
  R := StringGrid1.CellRect(ACol, ARow);
  R.Left := R.Left + StringGrid1.Left;
  R.Right := R.Right + StringGrid1.Left;
  R.Top := R.Top + StringGrid1.Top;
  R.Bottom := R.Bottom + StringGrid1.Top;
  if ((ARow <> 0) and (ACol = 0)) then
  begin
    {Show the Editbox}
    with edbInplaceEditbox do
    begin
      Left := R.Left + 1;
      Top := R.Top + 1;
      Width := (R.Right + 1) - R.Left;
      Height := (R.Bottom + 1) - R.Top;
      Visible := True;
      SetFocus;
    end;
  end
  else edbInplaceEditbox.Visible := False;
  CanSelect := True;
end;
 
 
procedure TfrmMain.StringGrid1DrawCell(Sender: TObject; Col, Row: Integer;
  Rect: TRect; State: TGridDrawState);
const
  AlignFlags: array [TAlignment] of Integer =
     (DT_LEFT or DT_VCENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
      DT_RIGHT or DT_VCENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX,
      DT_CENTER or DT_VCENTER or DT_WORDBREAK or DT_EXPANDTABS or DT_NOPREFIX);
var s: string;
begin
  inherited;
  with Rect do
  begin
    Left := Left + 2;
    Top := Top + 2;
    Right := Right - 5
  end;
  s := StringGrid1.Cells[Col, Row];
  if (Row = 0) and (Col < StringGrid1.ColCount) then
  begin
    StringGrid1.Canvas.Font.Style := StringGrid1.Canvas.Font.Style + [fsBold];
    StringGrid1.Canvas.Brush.Color := StringGrid1.FixedColor;
    StringGrid1.Canvas.FillRect(Rect);
 
    DrawText(StringGrid1.Canvas.Handle,
             PChar(s), Length(s),
             Rect, AlignFlags[taCenter]);
  end
  else
    if (Col = 0) and (Row > 0) and (Row < StringGrid1.RowCount) then
    begin
      StringGrid1.Canvas.FillRect(Rect);
      DrawText(StringGrid1.Canvas.Handle,
               PChar(s), Length(s),
               Rect, AlignFlags[taRightJustify]);
    end;
end;
 
 
procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  InputEnd:=False;
  if Key = VK_RETURN  then
    InputEnd := True;
end;
 
end.

Open in new window

0
kacor
Asked:
kacor
  • 2
1 Solution
 
ahalyaCommented:
I notice two issues in your code.

The call to StringGrid1.SetFocus in the OnChange event handler for the TEdit. [procedure TForm3.edbInplaceEditboxChange(Sender: TObject); is the reason for you not being able to type more than one character.    I'd suggest changing procedure TForm3.edbInplaceEditboxChange(Sender: TObject);  into an OnExit event handler, instead of an onchange handler.

Also, you should change the reference to Edit to StringGrid in the CMDialogKey procedure.  It simply enables the tab key to work correctly in the stringgrid.

procedure TForm3.CMDialogKey(var msg: TCMDialogKey);
begin
  if (ActiveControl = edbInplaceEditbox) 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;

Open in new window

0
 
ahalyaCommented:
Three of your procedures with minor changes are posted below.  They make it work.
procedure TForm3.CMDialogKey(var msg: TCMDialogKey);
begin
  if (ActiveControl = edbInplaceEditbox) 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 TForm3.edbInplaceEditboxExit(Sender: TObject);
 
begin
  inherited;
    {get the selection of the EditBox and place onto grid}
    StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row] := edbInplaceEditbox.Text;
    edbInplaceEditbox.Visible := False;
    StringGrid1.SetFocus;
end;
 
procedure TForm3.StringGrid1SelectCell(Sender: TObject; ACol,  ARow: Integer; var CanSelect: Boolean);
var R: TRect;
begin
  {Position of the control to place onto grid}
  R := StringGrid1.CellRect(ACol, ARow);
  R.Left := R.Left + StringGrid1.Left;
  R.Right := R.Right + StringGrid1.Left;
  R.Top := R.Top + StringGrid1.Top;
  R.Bottom := R.Bottom + StringGrid1.Top;
   {Show the Editbox}
    with edbInplaceEditbox do
    begin
      Left := R.Left + 1;
      Top := R.Top + 1;
      Width := (R.Right + 1) - R.Left;
      Height := (R.Bottom + 1) - R.Top;
      Visible := True;
      Text := StringGrid1.Cells[ACol, ARow];
      SetFocus;
    end;
 
  CanSelect := True;
end;
 

Open in new window

0
 
kacorretiredAuthor Commented:
Thanks your highly appreciated help.
Janos
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now