StringGrid - clear range of cells based on a cell value lazarus / 31-LCL ---------------------------------------------------------------------- GregB · 2012-06-08 02:42 I have a stringgrid with a number of columns, one column has a pickbox that determines which columns in the row can be edited (this varies depending on the selection) , what i would like to do is if the user changes the pickbox selection i need to erase the data in the cells on that row. The problem i have is in detecting if the pick changes and where i need to put the code to clear the cells - clear columns 6 to 11 in the current row StringGrid1.clean(6, arow, 11, arow, [gznormal]); I am very new to Lazarus and Freepascal  but have done a fair bit with Turbo Pascal many many years ago, so am not even sure if a stringgrid is the right way to go about this. One other minor thing i can not seem to work out is if the user enters invalid data and the error message shows, the stringgrid does not show the current cell as being focused - does not have the red border thing. Thanks for any help. This is what i have so far ... most of it from googleing Code: [Select]unit Unit2; {$mode objfpc}{$H+} interface uses   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids,   StdCtrls; type   { TForm1 }   TForm1 = class(TForm)     Button1: TButton;     StringGrid1: TStringGrid;     procedure Button1Click(Sender: TObject);     procedure StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;       aRect: TRect; aState: TGridDrawState);     procedure StringGrid1SelectCell(Sender: TObject; aCol, aRow: Integer;       var CanSelect: Boolean);     procedure StringGrid1SelectEditor(Sender: TObject; aCol, aRow: Integer;       var Editor: TWinControl);     procedure StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;       const Value: string);   private     { private declarations }   public     { public declarations }   end; var   Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); begin   StringGrid1.col := 2;   StringGrid1.row := 4;   StringGrid1.SetFocus;    // this works !!!!!!!!!!!!!!   StringGrid1.Cells[1,1] := 'Hi World'; end; // grey out the cells that are not editable procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;   aRect: TRect; aState: TGridDrawState); begin   if ((StringGrid1.cells[5, aRow] = 'Straight')   and (aCol in [8,9,10,11])) or      ((StringGrid1.cells[5, aRow] = 'Transition') and (aCol in [6,7,11])) or      ((StringGrid1.cells[5, aRow] = 'Circ_Curve') and (aCol in [6,7,8,9,10]))   then   begin      StringGrid1.Canvas.Brush.Color := clBtnFace;      // colour Button Face      StringGrid1.Canvas.FillRect(aRect);   //end   //else   //begin   //  StringGrid1.Canvas.Brush.Color := clWindow;      // window colour   //  StringGrid1.Canvas.FillRect(aRect);   end; end; // set which cells can be edited based on the alignment option chosen procedure TForm1.StringGrid1SelectCell(Sender: TObject; aCol, aRow: Integer;   var CanSelect: Boolean); begin   if ((StringGrid1.cells[5, aRow] = 'Straight')   and (aCol in [8,9,10,11])) or      ((StringGrid1.cells[5, aRow] = 'Transition') and (aCol in [6,7,11]))   or      ((StringGrid1.cells[5, aRow] = 'Circ_Curve') and (aCol in [6,7,8,9,10]))   then      StringGrid1.options := StringGrid1.options - [goEditing]   else      StringGrid1.options := StringGrid1.options + [goEditing]; //  if StringGrid1.cells[aRow, 0] = 'PT' and aCol in [5, 8,9,10,11] then StringGrid1.options := StringGrid1.options - [goEditing]; //  if StringGrid1.cells[aRow, 0] = 'PT' and aCol in [5, 8,9,10,11] then StringGrid1.options := StringGrid1.options - [goEditing]; end; // set the pickbox editor for the alignment column procedure TForm1.StringGrid1SelectEditor(Sender: TObject; aCol, aRow: Integer;   var Editor: TWinControl); var   old_alignment : string; begin   if aCol = 5 then   begin      old_alignment := StringGrid1.cells[acol, arow]; // save the current value      Editor := StringGrid1.EditorByStyle(cbsPickList);      TCustomComboBox(Editor).Items.CommaText := 'Straight,Transition,Circ_Curve';      // if the user changes the alignment then we need to clear the data that was there      if StringGrid1.cells[acol, arow] <> old_alignment then      begin       StringGrid1.Clean(6, arow, 11, arow, [gznormal]);         old_alignment := '';      end;   end; end; Procedure ValidateReal(rstr : string; var valid : boolean); var   A : double; begin   // check for conversion errors   valid := True;   if (rstr <> '') then   try     A := StrToFloat(rstr);   except     valid := False;   end; end; procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;   const Value: string); Var   valid : boolean;   orig_col, orig_row : integer; begin   orig_col := aCol;   orig_row := aRow;   valid := True;      Case aCol of       0  : { point number - no validation required };           1  : { point code - no validation required };           2  : { kilometrage - real } ValidateReal(Value, valid); 3 : { east };           4 : { north };           5 : { alignment parameter};           6 : { bearing } ;           7 : { distance } ;           8 : { Xc }  ;           9  : { Yc }  ;           10 : { H }    ;           11 : { Radius } ;      end;      If not(valid) then      begin         ShowMessage('Invalid data entered ... ' + Value);         StringGrid1.Cells[orig_col, orig_row] := '';         StringGrid1.Col := orig_col;         StringGrid1.Row := orig_row;         StringGrid1.SetFocus;      end;      StringGrid1.Invalidate;  // this repaints the cells when the pickbox is used have no idea why end; end. This is the form Code: [Select]object Form1: TForm1   Left = 1087   Height = 502   Top = 48   Width = 939   Caption = 'Form1'   ClientHeight = 502   ClientWidth = 939   LCLVersion = '0.9.30.4'   object StringGrid1: TStringGrid     Left = 72     Height = 200     Top = 56     Width = 800     ColCount = 12     Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goEditing, goSmoothScroll]     RowCount = 6     TabOrder = 0     OnDrawCell = StringGrid1DrawCell     OnSelectCell = StringGrid1SelectCell     OnValidateEntry = StringGrid1ValidateEntry     ColWidths = (       64       80       73       64       64       64       64       64       64       64       64       64     )     Cells = (       21       0       0       'Code'       0       1       'PT'       0       2       'TP'       0       3       'TRS'       0       4       'TRS'       0       5       'TP'       1       0       'Point Number'       2       0       'Kilometrage'       3       0       'East'       4       0       'North'       5       1       'Straight'       5       2       'Transition'       5       3       'Circ Curve'       5       4       'Transition'       5       5       'Straight'       6       0       'Bearing'       7       0       'Distance'       8       0       'Xc'       9       0       'Yc'       10       0       'H'       11       0       'Radius'     )   end   object Button1: TButton     Left = 416     Height = 25     Top = 0     Width = 75     Caption = 'Button1'     OnClick = Button1Click     TabOrder = 1   end end ---------------------------------------------------------------------- howardpc · 2012-06-08 18:58 QuoteThe problem i have is in detecting if the pick changes and where i need to put the code to clear the cells - clear columns 6 to 11 in the current row StringGrid1.clean(6, arow, 11, arow, [gznormal]); One problem is not where to put the clearing code, but the fact that your OnDrawCell routine overwrites the clearing. Quotethe stringgrid does not show the current cell as being focused - does not have the red border thing. For this you need both stringGrid1.FocusRectVisible = True, and DrawFocusSelected present in the grid's Options. ---------------------------------------------------------------------- GregB · 2012-06-20 07:59 Thanks I got it to work by creating a global variable to hold the value and saved it when GetEditText was called and compared that to the value when SetEditText finished