Как изменить значение ячейки в TDBGrid в Delphi

Я должен отобразить некоторое измененное значение "masked" в VCL TDBGrid (Delphi XE2), т. е. изменить "пароль" на "xxxxxxxx" или верхний регистр "pass" на "PASS" или другие. Поскольку мои поля динамически создаются (но имя закодировано, поэтому я знаю, как и когда маскировать их ie : xxxx_PASSW для полей паролей), я не могу использовать (Я думаю) ongettext событие.

Итак, каков наиболее эффективный способ сделать это (поскольку я еще использую OnDrawColumnCell для некоторой модификации презентации, я бы предпочел использовать его) ?

4 ответов


есть по крайней мере 3 способа сделать это, я проиллюстрирую, маскируя поле пароля из базы данных. Я использую sql server для диалекта sql.

1. Определите вычисляемое поле в строке sql.

select field1, field2, '********' as maskedPwd from table1;

затем щелкните правой кнопкой мыши на dbgrid, выберите редактор столбцов. В Редакторе столбцов dbgrid просто выберите столбец maskedPwd вместо реального столбца пароля. Теперь dbgrid будет отображать маскированное значение вместо пароль:.

или

2. Определите вычисляемое поле в наборе данных, используемом dbgrid.

просто щелкните правой кнопкой мыши на наборе данных и используйте редактор полей для создания нового вычисляемого поля (например, maskedPwd2). Затем onCalcField событие набора данных, напишите код, чтобы установить значение maskedPwd2, т. е.

procedure TForm1.ADOQuery1CalcFields(DataSet: TDataSet);
begin
  DataSet.FieldByName('maskedPwd2').AsString := '********';
end;

обязательно включите maskedPwd2 в Редактор столбцов элемент управления dbgrid.

или

3. Напишите пользовательский текст в событии onDrawColumnCell dbgrid.

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  grid : TDBGrid;
  maskValue : String;
  aRect : TRect;
begin
  maskValue := '********';
  aRect := Rect;
  grid := sender as TDBGrid;

  if column.FieldName = 'password' then
  begin
    grid.Canvas.FillRect(Rect);
    DrawText(grid.Canvas.Handle, PChar(maskValue), Length(maskValue), aRect,
      DT_SINGLELINE or DT_LEFT or DT_VCENTER);
  end;
end;

обратите внимание, что код выше отображает только маскированное значение, но если сетка редактируема, реальное значение пароля будет видно при фокусировке/редактировании ячейки.

чтобы справиться с этим, удалите TEdit в форме, очистите свойство text, установите свойство PpasswordChar В ' * ' и visible в false. Теперь все готово. используется в качестве замены встроенного редактора ячейки. Теперь нам нужна логика склеивания, т. е.

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  grid : TDBGrid;
  maskValue : String;
  aRect : TRect;
begin
  maskValue := '********';
  aRect := Rect;
  grid := sender as TDBGrid;

  if column.FieldName = 'password' then
    if gdfocused in State then
      begin
        Edit1.Left := Rect.Left + grid.Left + 1;
        Edit1.Top  := rect.Top + grid.Top + 1;
        Edit1.Width := Rect.Right - Rect.Left + 2;
        Edit1.Height := Rect.Bottom - Rect.Top + 2;
        Edit1.Clear;
        Edit1.Visible := True;
      end
    else
      begin
        grid.Canvas.FillRect(Rect);
        DrawText(grid.Canvas.Handle, PChar(maskValue), Length(maskValue), aRect,
          DT_SINGLELINE or DT_LEFT or DT_VCENTER);
      end
  else
    grid.DefaultDrawColumnCell(Rect, DataCol, Column, state);
end;

procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
  Edit1.Visible := False;
end;

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key = Chr(9) then Exit;

  if (Sender as TDBGrid).SelectedField.FieldName = 'password' then
  begin
    Edit1.SetFocus;
    SendMessage(Edit1.Handle, WM_CHAR, word(Key), 0);
  end;
end;

procedure TForm1.Edit1Change(Sender: TObject);
begin
  if DBGrid1.DataSource.State in [dsEdit, dsInsert] then
    DBGrid1.DataSource.DataSet.FieldByName('password').AsString := Edit1.Text;
end;

procedure TForm1.Edit1Enter(Sender: TObject);
begin
  DBGrid1.DataSource.Edit;
end;

обратите внимание, что приведенный выше код еще не совершенен, но суть есть. Я оставлю это тебе для упражнений.


Я бы написал OnGetText для поля пароля в моем наборе данных, так как значение поля не должно отображаться ни в одном элементе управления вообще


вам нужно замаскировать все значения во всем столбце? В этом случае, если вы знаете, для чего TField (или fieldname) это сделать: попробуйте динамически создать вычисляемое поле с измененными значениями и отобразить его в столбце.


Я изменить приведенный выше код, чтобы показать и скрыть пароль. Если пользователь нажимает на ячейку пароля, он покажет ее, когда они нажимают на ячейку, она снова скроет ее.

// Add a cell click event from the TDBGrid
procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
if DBGrid1.SelectedField.FieldName = 'password' then
Edit1.Text := Your_Table_Name.FieldByName('password').AsString;
Edit1.PasswordChar:=#0;
end;

// Change the edit1change event to this
procedure TForm1.Edit1Change(Sender: TObject);
begin
if DBGrid1.DataSource.State in [dsEdit, dsInsert] then
Your_Table_Name.FieldByName('password').AsString := Edit1.Text;
Edit1.PasswordChar:=#0;
end;

// You should change colexit event to read like this
procedure TForm1.DBGrid1ColExit(Sender: TObject);
begin
if DBGrid1.SelectedField.FieldName = 'password' then
Edit1.Visible := False;
end; 

не потребовалось много работы, чтобы сделать его в прохладное поле пароля.

забыл одну вещь в событии ячейки столбца рисования DBGrid, вы должны изменить Edit1.Ясно; в Edit1.Текст := Your_Table_Name.FieldByName('Пароль').AsString;