We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now

x

EditBox inside StringGrid

kacor
kacor asked
on
Medium Priority
4,639 Views
Last Modified: 2012-05-06
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

Comment
Watch Question

Commented:
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

Commented:
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

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
kacorretired

Author

Commented:
Thanks your highly appreciated help.
Janos
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.