[Solved] Focus cells in reverse order for any utility don’t support RTL [closed]


The following code, without an OnKeyUp handler, does what you seem to want

    type
      TMyDBGrid = class(TDBGrid);

    procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word; Shift:
        TShiftState);
    begin
      if Key = VK_Tab then begin
        Key := 0;
        if ssShift in Shift then
          DBGrid1.SelectedIndex := DBGrid1.SelectedIndex + 1
        else begin
          if TMyDBGrid(DBGrid1).Col = 1 then begin
            //  The following goes to the rightmost cell in the next row 
            //  if the focus is already on the leftmost column, as specified
            //  in the original version of the q
            DBGrid1.DataSource.DataSet.Next;
            TMyDbGrid(DBGrid1).Col := DBGrid1.Columns.Count;
          end
          else
            DBGrid1.SelectedIndex := DBGrid1.SelectedIndex - 1;
        end;
      end;
    end;

Update In a comment to this, you asked for a fuller implementation. Here it is:

procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word; Shift:
    TShiftState);

  procedure TabForwards;
  begin
    if TMyDBGrid(DBGrid1).Col = DBGrid1.Columns.Count then begin
      DBGrid1.DataSource.DataSet.Next;
      if DBGrid1.DataSource.DataSet.Eof then
        DBGrid1.DataSource.DataSet.Append;
      TMyDbGrid(DBGrid1).Col := 1;
    end
    else
      DBGrid1.SelectedIndex := DBGrid1.SelectedIndex + 1;
  end;

  procedure TabBackwards;
  begin
    if DBGrid1.DataSource.DataSet.State = dsInsert then begin
       DBGrid1.DataSource.DataSet.Cancel;
       Exit;
    end;

    if TMyDBGrid(DBGrid1).Row = 1 then begin
      if TMyDBGrid(DBGrid1).Col = 1 then
        TMyDBGrid(DBGrid1).Col := DBGrid1.Columns.Count
      else
        DBGrid1.SelectedIndex := DBGrid1.SelectedIndex - 1;
    end
    else begin
      if TMyDBGrid(DBGrid1).Col = 1 then begin
        DBGrid1.DataSource.DataSet.Prior;
        TMyDbGrid(DBGrid1).Col := DBGrid1.Columns.Count;
      end
      else
        DBGrid1.SelectedIndex := DBGrid1.SelectedIndex - 1;
    end;
  end;

begin
  Caption := IntToStr(TMyDbGrid(DBGrid1).RowCount);
  if cbNormal.Checked then
    Exit;
  if Key = VK_Tab then begin
    Key := 0;
    if ssShift in Shift then
      TabForwards
    else
      TabBackwards;
  end;
end;

Notice that this uses TabForwards and TabBackwards sub-procedures and effectively reverses the roles of Tab and Shift Tab. The reason for this is because it separates thinking, and talking, about the movement behaviour from the key combination which produces it, which I found easier easier to code and to describe what the movement behaviour actually is.

With Tab and Shift Tab behaving as standard, this is how the DBGrid behaves:

  1. Tabbing forwards

If the cursor is in the New Record row, focus move to the next cell in the row until it reaches the RH column, then it wraps to the first column.

Otherwise, focus moves to the next cell in the current row until it reaches the RH column, then it wraps to the first column of the next row, if there is one, otherwise it calls Append on the grid’s Dataset, and moves to the first column of the New Record row.

In the New Record row, pressing the Tab Backwards key abandons the new record.

  1. Tabbing backwards

If the cursor is in the New Record row, the new record is abandoned. Otherwise, focus moves to the prior cell in the current row until it reaches the LH column, then it wraps to the RH column of the prior row. Once it reaches the LH column of the first row, it wraps to the RH column in that row.

That is what the second example does.

This does not, however, do what you said in your comment

when I reach last cell in DBgrid, the tab key (not shift-Tab) need to open new record.

and this is why:

Your way, the behaviour of the grid in response to the Tab key is different in the last cell compared with every other one. In the other cells, Tab will move left and wrap upwards to the prior row, whereas in the last cell it will move downwards. That would puzzle me as a user. Anyway, if that’s really what you want, you can rearrange the second example to behave that way.

When you use Tab and Shift Tab in the normal way, the behaviour is as follows:

8

solved Focus cells in reverse order for any utility don’t support RTL [closed]