Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations MikeeOK on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

OnStartEdit OnStopEdit in StringGrids.

Status
Not open for further replies.

Nordlund

Programmer
Jul 17, 2001
458
SE
Hi there.
Has anyone implemented OnStartEdit or OnStopEdit in ordinary StringGrids.?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Norlund: These dont seem to be default methods for stringgrids.
e.g on OnSetEditText occurs when the user stops editing.



Steve: Delphi a feersum engin indeed.
 
Yep. I know, But I have done this once.
unfortunately, the code is vanished.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Onw way to solve the problem might be to override the InplaceEditor's WndProc, and find the inplace editors setfocus and killfocus....

...But the inplaceeditor isn't created until the first time the editor is shown.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Ok. I managed to do this... Look at the code example below.
This example may have a lot of bugs in it, use on you own risk :)

Code:
unit StringGridPlus;

interface

uses
  SysUtils, Classes, Grids, Messages, Windows;

type
  TOnCellEditEvent = procedure(Sender: TObject; ACol, ARow: Integer; var Value: String) of object;

  TStringGridPlus = class;
  TGridPlusInplaceEdit = class(TInplaceEdit)
  private
    FGrid: TStringGridPlus;
    InEditor: Boolean;
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    constructor Create(Owner: TComponent); override;
    property Grid: TStringGridPlus read FGrid;
  end;

  TStringGridPlus = class(TStringGrid)
  private
    FOnStartEdit: TOnCellEditEvent;
    FOnStopEdit: TOnCellEditEvent;
  protected
    function  CreateEditor: TInplaceEdit; override;
  public
    constructor Create(Owner: TComponent); override;
  published
    property OnStartEdit: TOnCellEditEvent read FOnStartEdit write FOnStartEdit;
    property OnStopEdit: TOnCellEditEvent read FOnStopEdit write FOnStopEdit;
  end;

procedure Register;

implementation

uses Mask;

procedure Register;
begin
  RegisterComponents('AaroLib', [TStringGridPlus]);
end;

{ TStringGridPlus }

constructor TStringGridPlus.Create(Owner: TComponent);
begin
  inherited;
  DefaultRowHeight := 17;
end;

function TStringGridPlus.CreateEditor: TInplaceEdit;
begin
  Result := TGridPlusInplaceEdit.Create(Self);
end;

{ TGridPlusInplaceEdit }

constructor TGridPlusInplaceEdit.Create(Owner: TComponent);
begin
  inherited;
  InEditor := false;
  FGrid := TStringGridPlus(Owner);
end;

procedure TGridPlusInplaceEdit.WndProc(var Message: TMessage);
var
  G: TStringGridPlus;
  tempStr: String;
begin
  if InEditor then
  begin
    Inherited;
    Exit;
  end;
  
  case Message.Msg of

    WM_SETFOCUS:
      begin
        InEditor := true;
        try
          tempStr := Text;
          if Assigned(FGrid.FOnStartEdit) then
            FGrid.FOnStartEdit(FGrid, G.Col, G.Row, tempStr);
        finally
          Text := tempStr;
          Grid.HideEditor;
          InEditor := false;
        end;
      end;

    WM_KILLFOCUS:
      begin
        tempStr := Text;
        if Assigned(FGrid.FOnStopEdit) then
        begin
          FGrid.FOnStopEdit(FGrid, G.Col, G.Row, tempStr);
          Text := tempStr;
        end;
      end;
  end;

  inherited;
end;

end.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Hi. Sending updated component.....
Some serious issues was found.
Code:
unit StringGridPlus;

interface

uses
  SysUtils, Classes, Grids, Messages, Windows;

type
  TOnCellStartEditEvent = procedure(Sender: TObject; ACol, ARow: Integer; var Value: String; var AutoClose: Boolean) of object;
  TOnCellStopEditEvent = procedure(Sender: TObject; ACol, ARow: Integer) of object;

  TStringGridPlus = class;
  TGridPlusInplaceEdit = class(TInplaceEdit)
  private
    FGrid: TStringGridPlus;
    InEditor: Boolean;
    UndoText: String;
  protected
    procedure WndProc(var Message: TMessage); override;
    procedure KeyPress(var Key: Char); override;
  public
    constructor Create(Owner: TComponent); override;
    property Grid: TStringGridPlus read FGrid;
  end;

  TStringGridPlus = class(TStringGrid)
  private
    FOnStartEdit: TOnCellStartEditEvent;
    FOnStopEdit: TOnCellStopEditEvent;
  protected
    function  CreateEditor: TInplaceEdit; override;
  public
    constructor Create(Owner: TComponent); override;
  published
    property OnStartEdit: TOnCellStartEditEvent read FOnStartEdit write FOnStartEdit;
    property OnStopEdit: TOnCellStopEditEvent read FOnStopEdit write FOnStopEdit;
  end;

procedure Register;

implementation

uses Mask;

procedure Register;
begin
  RegisterComponents('Nordlund', [TStringGridPlus]);
end;

{ TStringGridPlus }

constructor TStringGridPlus.Create(Owner: TComponent);
begin
  inherited;
  DefaultRowHeight := 17;
end;

function TStringGridPlus.CreateEditor: TInplaceEdit;
begin
  Result := TGridPlusInplaceEdit.Create(Self);
end;

{ TGridPlusInplaceEdit }

constructor TGridPlusInplaceEdit.Create(Owner: TComponent);
begin
  inherited;
  InEditor := false;
  FGrid := TStringGridPlus(Owner);
end;

procedure TGridPlusInplaceEdit.KeyPress(var Key: Char);
begin
  try
    if Key = #27 then
    begin
      FGrid.HideEditor;
      FGrid.Cells[FGrid.Col, FGrid.Row] := UndoText;
      Text := UndoText;
      Key := #0;
    end;

  finally
    inherited KeyPress(Key);
  end;
end;

procedure TGridPlusInplaceEdit.WndProc(var Message: TMessage);
var
  G: TStringGridPlus;
  tempStr: String;
  AutoClose: Boolean;
begin
  if InEditor then
  begin
    Inherited;
    Exit;
  end;

  case Message.Msg of

    WM_SETFOCUS:
      begin
        InEditor := true;
        try
          UndoText := FGrid.Cells[FGrid.Col, FGrid.Row];

          tempStr := Text;
          if Assigned(FGrid.FOnStartEdit) then
          begin
            FGrid.FOnStartEdit(FGrid, FGrid.Col, FGrid.Row, tempStr, AutoClose);
            Text := tempStr;
            InEditor := false;
            if AutoClose then
              Grid.HideEditor;
          end;
        finally
          InEditor := false;
        end;
      end;

    WM_KILLFOCUS:
      begin
        if Assigned(FGrid.FOnStopEdit) then
        begin
          FGrid.FOnStopEdit(FGrid, FGrid.Col, FGrid.Row);
        end;
      end;
  end;

  inherited;
end;

end.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Norlund.
I know that the default behaviour of the Stringgrid Inplace editor makes it a pain to use.
Think I see whats happening here, I assume your code is an attempt to make the editor more manageable by controlling the focus, can you explain the usage?



Steve: Delphi a feersum engin indeed.
 
What I wanted to accomplish was a way to prevent the internal editor to pop up, (The masked edit).
Instead, the OnStartEdit event occur.

I'm using this to let the grid pop up a Window instead of editing the cell directly.



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
An example:

I have a grid with 3 columns (Name, Age, Shoesize and Descriptive text).

When I click on the Name column, I edit the text as regular StringGrid would let me to.

When I click on the Shoesize column, A window pop up and let me choose between a bunch of preselected values.

When I clik on the Age column, a popupwindow with a UpDOwn spinbutton and a Descriptive text popup.
When I click OK in this window, the Descritive column is filled in as well as the Age column.


The progblem with the GetEditText, is that this event is fired a little bit randomly... :)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"There is always another way to solve it, but I prefer my way.
 
Norland
Excellent I happen to be working on an application that can use your component (The user can enter and edit alternatives to words in different languages)
Don't know if I have fould a problem
heres how I have implememted popping up an input box.
This seemed to be working fine, but there are a couple of problems (one major)

1. If you double click on a cell the input box opens and you can see and edit the text if required. But on quiting the box the text in the grid remains highlighted but NOT selected, you must switch focus to another cell then back to be able to edit the same cell again.

2. I havent tried this outside the IDE yet.
If I open the inputbox as before then switch focus to the IDE then back to the application ad try to close the input box if repeatebly re-opens and become impossible to close, I have to reset the application from the IDE.
This isnt entirly repeatable.
Code:
procedure TMainForm.menulistStartEdit(Sender: TObject; ACol,
  ARow: Integer; var Value: String; var AutoClose: Boolean);
begin
   if acol = 2 then
      Value := Inputbox('Edit entry',  MenuList.Cells[1,0]+ ':  '+ MenuList.Cells[1,arow] ,Value);
end;

Steve: Delphi a feersum engin indeed.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top