我必须在 VCL TDBGrid(Delphi XE2)中显示一些修改后的“屏蔽”值,即:将“密码”更改为“xxxxxxxx”或将大写“通过”更改为“通过”或其他。由于我的字段是动态创建的(但名称是编码的,所以我知道如何以及何时屏蔽它们,即:xxxx_PASSW 用于密码字段)我不能使用(我认为)OnGetText 事件。
那么最有效的方法是什么(因为我还使用 OnDrawColumnCell 进行一些我希望使用它的演示修改)?
我必须在 VCL TDBGrid(Delphi XE2)中显示一些修改后的“屏蔽”值,即:将“密码”更改为“xxxxxxxx”或将大写“通过”更改为“通过”或其他。由于我的字段是动态创建的(但名称是编码的,所以我知道如何以及何时屏蔽它们,即:xxxx_PASSW 用于密码字段)我不能使用(我认为)OnGetText 事件。
那么最有效的方法是什么(因为我还使用 OnDrawColumnCell 进行一些我希望使用它的演示修改)?
至少有 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;
确保在 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;
请注意,上面的代码仅显示掩码值,但如果网格是可编辑的,则当单元格被聚焦/编辑时,真正的密码值将可见。
为了解决这个问题,在表单上放置一个 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(或字段名)执行此操作:尝试使用修改后的值动态创建计算字段并将其显示在列中。
我修改了上面的代码来显示和隐藏密码。如果用户单击“密码”单元格,它将显示它,当他们单击该单元格时,它将再次隐藏它。
// 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 Draw Column Cell 事件的一件事,你应该改变 Edit1.Clear; 到 Edit1.Text := Your_Table_Name.FieldByName('Password').AsString;