Click to select row using TStringGrid? lazarus / 31-LCL ---------------------------------------------------------------------- tearsfornations · 2023-06-11 04:14 I have a TStringGrid with 2 columns Game Info and Moves When I double click on a row (or cell in row), I want to highlight that whole row and then load the game. I tried gridPGNDatabaseSelectCell and gridPGNDatabaseSelection with no luck. I'm sorry I am a newbie. Thanks, ---------------------------------------------------------------------- cdbc · 2023-06-11 05:43 Hi 1) To be able to select an entire row in the grid, you have to first, enable    "RowSelect" in "gridPGNDatabase", in OI. 2) Then in "gridPGNDatabaseDbClick", "gridPGNDatabaseSelectCell" or    "gridPGNDatabaseSelection" event-handlers, you read the "Row" and "Col"    properties and then load the corresponding game... It goes something like this excerpt from an app of mine:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfraBook.grdMainDblClick(Sender: TObject);begin  case grdMain.Row of  2: fBook.ArchiveDir:= InputBox('Input property','Enter Directory name:','NO path!');    3: if dlgDir.Execute then fBook.BackupDir:= dlgDir.FileName+bcPathDelimiter;    7: fBook.Name:= InputBox('Input property','Enter Name:','NO \ / . , or *');    9: fBook.SalesTax:= StrToBool(InputBox('Input property','Enter False/0 or True/1:','False'));    10: if dlgDir.Execute then fBook.WorkingDir:= dlgDir.FileName+bcPathDelimiter;  end;end; procedure TfraBook.grdMainKeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);begin  case Key of    $0D: grdMainDblClick(Sender);  end;end;  HTH Regards Benny ---------------------------------------------------------------------- tearsfornations · 2023-06-11 12:45 I appreciate your reply, but I cannot get it to work. When I double click the row, it keeps saying the row is 41 when I do a ShowMessage()  (which is the last row), see the screenshot. My code is here as well: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit unitFrmPgnDatabase; {$mode ObjFPC}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,  ExtCtrls, Grids, Menus, Types; type   { TfrmPGNDatabase }   TfrmPGNDatabase = class(TForm)    mniLoadGame: TMenuItem;    pnlDatabase: TPanel;    gridPGNDatabase: TStringGrid;    pmnPGNDatabase: TPopupMenu;    procedure gridPGNDatabaseClick(Sender: TObject);    procedure gridPGNDatabaseDblClick(Sender: TObject);    procedure gridPGNDatabaseDrawCell(Sender: TObject; aCol, aRow: Integer;      aRect: TRect; aState: TGridDrawState);    procedure gridPGNDatabaseMouseMove(Sender: TObject; Shift: TShiftState; X,      Y: Integer);    procedure gridPGNDatabasePrepareCanvas(Sender: TObject; aCol,      aRow: Integer; aState: TGridDrawState);    procedure gridPGNDatabaseSelectCell(Sender: TObject; aCol, aRow: Integer;      var CanSelect: Boolean);    procedure gridPGNDatabaseSelection(Sender: TObject; aCol, aRow: Integer);    procedure mniLoadGameClick(Sender: TObject);  private   public   end; var  frmPGNDatabase: TfrmPGNDatabase;  My_Grid_Highlight_BackGround_Color:Tcolor=ClGreen;  My_Grid_Highlight_Font_Color:Tcolor=clYellow;  My_Grid_Highlight_Font_Multiplier:Real=1.5;  // FOnt Multiplier for selected row  LastRow : Integer;implementation uses  MainUnit, GraphUtil, LCLIntf;{$R *.lfm} { TfrmPGNDatabase } procedure TfrmPGNDatabase.gridPGNDatabaseDblClick(Sender: TObject);begin  ShowMessage(IntToStr(gridPGNDatabase.Row));  if LastRow <> -1 then  begin    gridPGNDatabase.Row := LastRow;    MainForm.FGame.ChessNotation.PGNString := gridPGNDatabase.Rows[gridPGNDatabase.Row].Strings[1] + ' ' + gridPGNDatabase.Rows[gridPGNDatabase.Row].Strings[2];  end;end; procedure TfrmPGNDatabase.gridPGNDatabaseClick(Sender: TObject);begin  if LastRow <> -1 then  begin    gridPGNDatabase.Row := LastRow;  end;end; procedure TfrmPGNDatabase.gridPGNDatabaseDrawCell(Sender: TObject; aCol,  aRow: Integer; aRect: TRect; aState: TGridDrawState);begin  If Sender is TStringGrid then  begin    With (sender as TStringGrid) Do    Begin    Canvas.Brush.Style := bsSolid;      canvas.Font.Color:=clWhite;    if arow=row then       // Selected Row      begin        FocusColor:=My_Grid_Highlight_BackGround_Color;        Canvas.Brush.Color:=My_Grid_Highlight_BackGround_Color;        canvas.Font.Color:=My_Grid_Highlight_Font_Color;        canvas.Font.Size:=round(font.Size*My_Grid_Highlight_Font_Multiplier);      end      else      begin        canvas.Font.Color:=font.Color;      Canvas.Brush.Color:=color;        canvas.Font.Size:=font.Size;    end;      defaultdrawcell(Acol, Arow, arect, astate);    end;  end;end; procedure TfrmPGNDatabase.gridPGNDatabaseMouseMove(Sender: TObject;  Shift: TShiftState; X, Y: Integer);var  R, C:        Integer;  Start, Size: Integer;  i:           Integer;begin  // Row  R     := -1;  Start := 0;  for i := 0 to gridPGNDatabase.RowCount-1 do  begin    Size := gridPGNDatabase.RowHeights[i];    if (Y > Start) and (Y < Start + Size) then    begin      R := i;      Break;    end;    Inc(Start, Size);  end;  // Column  C     := -1;  Start := 0;  for i := 0 to gridPGNDatabase.ColCount-1 do  begin    Size := gridPGNDatabase.ColWidths[i];    if (X > Start) and (X < Start + Size) then    begin      C := i;      Break;    end;    Inc(Start, Size);  end;  // Show result  //Caption := 'Mouse X:Y = ' +  X.ToString + ':' + Y.ToString;  case (R < 0) or (C < 0) of    True:  LastRow := -1;    False: LastRow := R;  end;  gridPGNDatabase.Invalidate();end; procedure TfrmPGNDatabase.gridPGNDatabasePrepareCanvas(Sender: TObject; aCol,  aRow: Integer; aState: TGridDrawState);var  P: TPoint;  c, r: LongInt;  obe: Boolean;begin  P := gridPGNDatabase.ScreenToClient(Mouse.CursorPos);  if (aState = []) or (gdFixed in aState) then  begin    obe := gridPGNDatabase.AllowOutBoundEvents;    gridPGNDatabase.AllowOutBoundEvents := false;    gridPGNDatabase.MouseToCell(P.X, P.Y, c, r);    gridPGNDatabase.AllowOutBoundEvents := obe;    if (aRow = r) and (aRow >= gridPGNDatabase.FixedRows) then    begin      if aState = [] then      gridPGNDatabase.Canvas.Brush.Color := rgb(232, 232, 232)      else        gridPGNDatabase.Canvas.Brush.Color := GetShadowColor(ColorToRGB(gridPGNDatabase.FixedColor), -20);    end;  end;end; procedure TfrmPGNDatabase.gridPGNDatabaseSelectCell(Sender: TObject; aCol,  aRow: Integer; var CanSelect: Boolean);begin end; procedure TfrmPGNDatabase.gridPGNDatabaseSelection(Sender: TObject; aCol,  aRow: Integer);begin end; procedure TfrmPGNDatabase.mniLoadGameClick(Sender: TObject);begin   if LastRow <> -1 then   begin     gridPGNDatabase.Row := LastRow;     gridPGNDatabase.Invalidate();     MainForm.FGame.ChessNotation.PGNString := gridPGNDatabase.Rows[LastRow].Strings[1] + ' ' + gridPGNDatabase.Rows[LastRow].Strings[2];     while (not MainForm.FGame.ChessNotation.Iterator.IsFirst) do     begin        MainForm.FGame.ChessNotation.Iterator.PrevMove();     end;   end;end; { TfrmPGNDatabase }  end.   and here is how I load the pgns in there: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainForm.actLoadPGNFileExecute(Sender: TObject);var  SList : TStringList;  PGNList : array of AnsiString;  i, R : Integer;  s, s2, pgn : AnsiString;  RegexObj: TRegExpr;begin  //load pgn file  RegexObj := TRegExpr.Create();  RegexObj.Expression := '((((\[.*?\])\s*)+)(1\.[^[]+(0-1|1-0|1/2-1/2)))';  if dlgOpenPGN.Execute() then  begin    frmPGNDatabase.Show();    //frmPGNDatabase.listPGNs.Items.Clear();    frmPGNDatabase.gridPGNDatabase.Clear();    pgn := '';    s := '';    s2 := '';    R := 1;    SList := TStringList.Create();    SList.LoadFromFile(dlgOpenPGN.FileName);    for i := 0 to SList.Count-1 do    begin      s2 := SList[i];      s += s2 + #13#10;       if (s2.Contains(' 1-0') or s2.Contains(' 1/2-1/2') or s2.Contains(' 0-1')) and RegexObj.Exec(s) then       begin         pgn := RegexObj.Match[1];         //ShowMessage(pgn);         PGNList := [ RegexObj.Match[2], RegexObj.Match[5] ];          frmPGNDatabase.gridPGNDatabase.RowCount := frmPGNDatabase.gridPGNDatabase.FixedRows + 2;         frmPGNDatabase.gridPGNDatabase.FixedRows := frmPGNDatabase.gridPGNDatabase.FixedRows + 1;         frmPGNDatabase.gridPGNDatabase.InsertRowWithValues(R,PGNList);        pgn := StringReplace(pgn, #13#10, '', [rfReplaceAll]);         pgn := StringReplace(pgn, #13, '', [rfReplaceAll]);         pgn := StringReplace(pgn, #10, '', [rfReplaceAll]);          s := '';         R := R + 1;       end    end;    try       CreateNewGame();       FGame.ChessNotation.PGNString := s2;    except      on E: Exception do        MessageDlg(E.Message, mtError, [mbOK], 0);    end;    SList.Free();  end;  RegexObj.Free();end; ---------------------------------------------------------------------- cdbc · 2023-06-11 15:08 Hi What has this got to do in there?!?:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmPGNDatabase.gridPGNDatabaseClick(Sender: TObject);begin  if LastRow <> -1 then  begin    gridPGNDatabase.Row := LastRow;  end;end;//-------- try like this...procedure TfrmPGNDatabase.gridPGNDatabaseClick(Sender: TObject);begin(*  if LastRow <> -1 then  begin    gridPGNDatabase.Row := LastRow;  end; *)end; This get fired first in a dblclick(2 clicks... you know)  Comment all this and see what happens  edit: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmPGNDatabase.gridPGNDatabaseMouseMove(Sender: TObject;  Shift: TShiftState; X, Y: Integer);  I'm a bit puzzled of what you're trying to achieve, with that code? It could throw your "LastRow" off course... Regards Benny ---------------------------------------------------------------------- jamie · 2023-06-11 15:38 I see the code in the MouseMove is way over kill! Use the MouseToCell method to obtain your Column and row markers, the grid takes care of that for you. ---------------------------------------------------------------------- cdbc · 2023-06-11 15:50 Hi @jamie: +1, I was wondering the exact same thing  Regards Benny ---------------------------------------------------------------------- tearsfornations · 2023-06-11 19:41 I get that some of the code is not optimal, that is why I posted it, but it still doesn't answer my question, how do I make it so that on click or double click, I can highlight the row and use it to load in my chess game with MainForm.FGame.ChessNotation.PGNString := gridPGNDatabase.Rows[LastRow].Strings[1] + ' ' + gridPGNDatabase.Rows[LastRow].Strings[2]; ---------------------------------------------------------------------- cdbc · 2023-06-12 05:33 Hi Right, first off the bat e.g.: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfraBook.grdMainMouseMove(Sender: TObject; Shift: TShiftState; X,  Y: Integer);var  lcol,lrow: Longint;begin  { convert the mousecoordinates to column & row }  grdMain.MouseToCell(X,Y,lcol,lrow);  { show hints from array, corresponding to the items under the mouse }  pnlBottom.Caption:= 'Property: ' + fBra[lrow-1].brName + fBra[lrow-1].brHint;  { keep focus on grid, mainly for "KeyDown" events to work }  if grdMain.CanSetFocus then grdMain.SetFocus;end; In your case it will look like this:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmPGNDatabase.gridPGNDatabaseMouseMove(Sender: TObject;  Shift: TShiftState; X, Y: Integer);var  R, C:        Integer;begin  { convert the mousecoordinates to column & row }  gridPGNDatabase.MouseToCell(X,Y,C,R);  case (R < 0) or (C < 0) of    True:  LastRow := -1;    False: LastRow := R;  end; { IS all of this really necessarry??? See DblClick-handler }  gridPGNDatabase.Invalidate();end; But why would you want to do all that, when a dblclick, 1) selects a row with the first click and 2) keep you from opening a game, when you just wanted to focus... So: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TfrmPGNDatabase.gridPGNDatabaseDblClick(Sender: TObject);begin//  ShowMessage(IntToStr(gridPGNDatabase.Row));  LastRow := gridPGNDatabase.Row;  MainForm.FGame.ChessNotation.PGNString := gridPGNDatabase.Cells[1,LastRow] +' '+ gridPGNDatabase.Cells[2,LastRow];end; If you have enabled "goRowSelect" in gridPGNDatabase.Options, either via the object- inspector or with this call somewhere in your startup code:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Include(gridPGNDatabase.Options,goRowSelect)Then the dbl-click handler should be enough. Oh, and you've got some cleaning up to do... 1) single click events are mostly annoying, e.g.: you want to bring form to    front / focus, then it starts opening games... 2) selection events are mainly useful for keyboard actions... 3) selectcell could double for your dbl-click event, but again it's a "One Hit    Wonder" i.e.: acts on first click... 4) mouse-over events are great for hot-tracking, but if you go out of bounds,    you're left with the last first/last row or column... In your case the KISS principle is sound advice, the grid knows when and where you clicked and all your unused (by now, anyway) code that's laying around clutters it up, so it's hard to read. Ok, that was my "Nickles Worth"  Regards Benny ---------------------------------------------------------------------- tearsfornations · 2023-06-12 08:26 ok I seem to have achieved what I wanted, thank you very much for your replies!, but still I'm left with a lot of extra blank rows. See screenshot. Here is the code I am using to add the rows: What am I doing wrong? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainForm.actLoadPGNFileExecute(Sender: TObject);var  SList : TStringList;  PGNList : array of AnsiString;  i, R, j : Integer;  s, s2, pgn, pgntags, white, black : AnsiString;  RegexObj: TRegExpr;begin  //load pgn file  RegexObj := TRegExpr.Create();  RegexObj.Expression := '((((\[.*?\])\s*)+)(1\.[^[]+(0-1|1-0|1/2-1/2)))';  if dlgOpenPGN.Execute() then  begin    frmPGNDatabase.Show();    //frmPGNDatabase.listPGNs.Items.Clear();    frmPGNDatabase.gridPGNDatabase.RowCount := 1;    frmPGNDatabase.gridPGNDatabase.Clear();    pgn := '';    s := '';    s2 := '';    R := 1;    SList := TStringList.Create();    SList.LoadFromFile(dlgOpenPGN.FileName);    for i := 0 to SList.Count-1 do    begin      s2 := SList[i];      s += s2 + #13#10;       if (s2.Contains(' 1-0') or s2.Contains(' 1/2-1/2') or s2.Contains(' 0-1')) and RegexObj.Exec(s) then       begin         pgn := RegexObj.Match[1];         pgntags := RegexObj.Match[2];         j := pgntags.IndexOf('[White "');         white := '';         if (j > 0) then         begin           white := pgntags.Substring(j+8, pgntags.Substring(j+8).IndexOf('"]'));         end;         j := pgntags.IndexOf('[Black "');         black := '';         if (j > 0) then         begin           black := pgntags.Substring(j+8, pgntags.Substring(j+8).IndexOf('"]'));         end;          PGNList := [ RegexObj.Match[2], white, black, RegexObj.Match[5] ];         frmPGNDatabase.gridPGNDatabase.RowCount := frmPGNDatabase.gridPGNDatabase.RowCount + 1;         //frmPGNDatabase.gridPGNDatabase.RowCount := frmPGNDatabase.gridPGNDatabase.FixedRows + 1;         //frmPGNDatabase.gridPGNDatabase.FixedRows := frmPGNDatabase.gridPGNDatabase.FixedRows + 1;         frmPGNDatabase.gridPGNDatabase.InsertRowWithValues(R,PGNList);        pgn := StringReplace(pgn, #13#10, '', [rfReplaceAll]);         pgn := StringReplace(pgn, #13, '', [rfReplaceAll]);         pgn := StringReplace(pgn, #10, '', [rfReplaceAll]);          s := '';         R := R + 1;       end    end;    try       CreateNewGame();       FGame.ChessNotation.PGNString := s2;    except      on E: Exception do        MessageDlg(E.Message, mtError, [mbOK], 0);    end;    SList.Free();  end;  RegexObj.Free();end; ---------------------------------------------------------------------- cdbc · 2023-06-12 10:44 Hi Well, let's see what gives:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainForm.actLoadPGNFileExecute(Sender: TObject);var  SList : TStringList;  PGNList : array of AnsiString;  i, R, j : Integer;  s, s2, pgn, pgntags, white, black : AnsiString;  RegexObj: TRegExpr;begin  //load pgn file  RegexObj := TRegExpr.Create();  RegexObj.Expression := '((((\[.*?\])\s*)+)(1\.[^[]+(0-1|1-0|1/2-1/2)))';  if dlgOpenPGN.Execute() then  begin    frmPGNDatabase.Show();    { these 2 swapped places }    frmPGNDatabase.gridPGNDatabase.Clear();     frmPGNDatabase.gridPGNDatabase.RowCount := 1;        pgn := '';    s := '';    s2 := '';    R := 1;    SList := TStringList.Create();    SList.LoadFromFile(dlgOpenPGN.FileName);    for i := 0 to SList.Count-1 do    begin      s2 := SList[i];      s += s2 + #13#10;       if (s2.Contains(' 1-0') or s2.Contains(' 1/2-1/2') or s2.Contains(' 0-1'))        and RegexObj.Exec(s) then       begin       pgn := RegexObj.Match[1];         pgntags := RegexObj.Match[2];       j := pgntags.IndexOf('[White "');         white := '';         if (j > 0) then         begin           white := pgntags.Substring(j+8, pgntags.Substring(j+8).IndexOf('"]'));         end;         j := pgntags.IndexOf('[Black "');         black := '';         if (j > 0) then         begin           black := pgntags.Substring(j+8, pgntags.Substring(j+8).IndexOf('"]'));         end;         { are you sure that regex doesn't return empty lines in its resultset? }         PGNList := [ RegexObj.Match[2], white, black, RegexObj.Match[5] ];       { set R = rowcount before you increment it }         R:= frmPGNDatabase.gridPGNDatabase.RowCount;         frmPGNDatabase.gridPGNDatabase.RowCount:= R + 1;         { now R points to the second to last row }         frmPGNDatabase.gridPGNDatabase.InsertRowWithValues(R,PGNList);       { does "InsertRowWithValues" add a row on its own accord?!? }        pgn := StringReplace(pgn, #13#10, '', [rfReplaceAll]);         pgn := StringReplace(pgn, #13, '', [rfReplaceAll]);         pgn := StringReplace(pgn, #10, '', [rfReplaceAll]);          s := '';       end    end;    try       CreateNewGame();       FGame.ChessNotation.PGNString := s2;    except      on E: Exception do        MessageDlg(E.Message, mtError, [mbOK], 0);    end;    SList.Free();  end;  RegexObj.Free();end;                             Maybe you can try this out for size... Then we'll have a looksee if more has to be done. Regards Benny ---------------------------------------------------------------------- tearsfornations · 2023-06-12 13:35 I fixed it by not using InsertRowWithValues and just using Cells[] Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMainForm.actLoadPGNFileExecute(Sender: TObject);var  SList : TStringList;  i, R, j, row : Integer;  s, s2, pgntags, white, black : AnsiString;  RegexObj: TRegExpr;begin  //load pgn file  RegexObj := TRegExpr.Create();  RegexObj.Expression := '((((\[.*?\])\s*)+)(1\..+?(0-1|1-0|1/2-1/2)))';  if dlgOpenPGN.Execute() then  begin    frmPGNDatabase.Show();    frmPGNDatabase.gridPGNDatabase.Clear();    frmPGNDatabase.gridPGNDatabase.RowCount := 1 + frmPGNDatabase.gridPGNDatabase.FixedRows;    s := '';    s2 := '';    R := 1;    row := frmPGNDatabase.gridPGNDatabase.FixedRows;    SList := TStringList.Create();    SList.LoadFromFile(dlgOpenPGN.FileName);  for i := 0 to SList.Count-1 do    begin      s2 := SList[i];      s += s2 + #13#10;       if (s2.Contains(' 1-0') or s2.Contains(' 1/2-1/2') or s2.Contains(' 0-1')) and RegexObj.Exec(s) then       begin         pgntags := RegexObj.Match[2];         j := pgntags.IndexOf('[White "');         white := '';         if (j > 0) then         begin           white := pgntags.Substring(j+8, pgntags.Substring(j+8).IndexOf('"]'));         end;         j := pgntags.IndexOf('[Black "');         black := '';         if (j > 0) then         begin           black := pgntags.Substring(j+8, pgntags.Substring(j+8).IndexOf('"]'));         end;          frmPGNDatabase.gridPGNDatabase.RowCount := frmPGNDatabase.gridPGNDatabase.RowCount + 1;          frmPGNDatabase.gridPGNDatabase.Cells[0, row] := RegexObj.Match[2];       frmPGNDatabase.gridPGNDatabase.Cells[1, row] := white;         frmPGNDatabase.gridPGNDatabase.Cells[2, row] := black;         frmPGNDatabase.gridPGNDatabase.Cells[3, row] := RegexObj.Match[5];       Inc(row);         s := '';         R := R + 1;       end    end;    if (R-1 = 1) then    begin       frmPGNDatabase.Caption := FormatFloat('#,',R-1) + ' PGN Game';    end else    begin       frmPGNDatabase.Caption := FormatFloat('#,',R-1) + ' PGN Games';    end;     try       CreateNewGame();    except      on E: Exception do        MessageDlg(E.Message, mtError, [mbOK], 0);    end;    SList.Free();  end;  RegexObj.Free();end; ---------------------------------------------------------------------- tearsfornations · 2023-06-12 13:36 Thanks for all your help! ---------------------------------------------------------------------- cdbc · 2023-06-12 19:25 Hehehe... Tried your quiz... It's Cool  Regards Benny