我需要在Delphi XE2的VCL TDBGrid中显示一些修改后的“掩码”值,即:将“password”更改为“xxxxxxxx”,或将大写字母“pass”更改为“PASS”或其他内容。由于我的字段是动态创建的(但名称是编码的,因此我知道何时以及如何将它们掩码,例如xxxx_PASSW用于密码字段),所以我不能使用OnGetText事件。那么最有效的方法是什么?(由于我已经在一些演示文稿修改中使用了OnDrawColumnCell,因此我更喜欢使用它)。
至少有三种方法可以做到这一点,我将通过屏蔽数据库中的密码字段来说明。我使用的是sql server作为sql方言。
1. 在sql字符串上定义一个计算字段。
select field1, field2, '********' as maskedPwd from table1;
接下来,右键单击dbgrid,选择列编辑器。在dbgrid的列编辑器中,仅选择掩码密码列而非真实密码列。现在,dbgrid将显示掩码值而不是密码。
或者
2. 在dbgrid使用的数据集上定义计算字段。
只需右键单击数据集,并使用字段编辑器创建一个新的计算字段(例如,maskedPwd2)。然后,在数据集的onCalcField事件中编写代码以设置maskedPwd2的值,即
procedure TForm1.ADOQuery1CalcFields(DataSet: TDataSet);
begin
DataSet.FieldByName('maskedPwd2').AsString := '********';
end;
请务必在dbgrid的列编辑器中包含maskedPwd2。
或者
3. 在dbgrid的onDrawColumnCell事件中编写自定义文本。
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;
请注意,上面的代码仅显示掩码值,但如果网格是可编辑的,则在单元格聚焦/编辑时实际密码值将可见。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
,因为该字段的值不应在任何控件中显示。
with (Sender as TDBGrid).Canvas do begin Font.Color := clWhite; Brush.Color := clWhite; Brush.Style := bsSolid; end;
来隐藏你想要的值,但我不确定如何在那里更改字段的实际文本。将一个 OnGetText
分配给多个 TField
是否更容易呢? - iMan BiglariOnGetText
,但是你可以在 OnDrawColumnCell
中轻松地将相同的颜色分配给 password 列的 font
和 brush
。 - iMan BiglariOnGetText
的方法。虽然我没有尝试过,但也许你可以在打开数据集后刷新 FieldsDef
,查找你的字段并在运行时分配 OnGetText
。 - iMan BiglariMyField.OnGetText:=PassFieldGetText
,其中PassFieldGetText是某个类的过程,其签名为(Sender: TField; var Text: string; DisplayText: Boolean);
。 - Sertac Akyuz您是否需要掩盖整个列中的所有值?如果是这样,如果您知道要对哪个TField(或字段名)执行此操作:请尝试动态创建一个带有修改后的值的计算字段,并在该列中显示。
// 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.Clear;更改为Edit1.Text:=Your_Table_Name.FieldByName('Password').AsString;