2012-09-19 27 views
5

Tôi phải hiển thị một số giá trị 'được che giấu' đã sửa đổi trong VCL TDBGrid (Delphi XE2), tức là: thay đổi 'mật khẩu' thành 'xxxxxxxx' hoặc chữ hoa 'chuyển' thành 'PASS' hoặc những người khác. Khi các trường của tôi được tạo động (nhưng tên được mã hóa để tôi biết cách thức và khi mặt nạ chúng tức là: xxxx_PASSW cho các trường mật khẩu) Tôi không thể sử dụng (Tôi nghĩ) sự kiện OnGetText.Cách sửa đổi giá trị ô trong Delphi TDBGrid

Vì vậy, cách hiệu quả nhất để làm điều này (như tôi chưa sử dụng OnDrawColumnCell cho một số sửa đổi bản trình bày tôi sẽ prefere để sử dụng nó) là gì?

+0

Có 3 cách để thực hiện việc này. 1. Tạo trường được tính toán cho mật khẩu trên tập dữ liệu được dbgrid sử dụng. 2. Tạo một trường được tính toán cho mật khẩu trên câu lệnh chọn sql. hoặc 3. sử dụng onDrawColumCell/Dữ liệu sự kiện của dbgrid, như bạn đã nói ở trên. Nhưng cá nhân tôi KHÔNG muốn lưu trữ mật khẩu trong cơ sở dữ liệu, nhưng phiên bản mã hóa băm của mật khẩu. Bởi vì mã băm là một hàm một chiều (tức là không thể lấy mật khẩu ban đầu từ mã băm), và chỉ mật khẩu chính xác mới có thể tạo ra cùng mã băm, nó an toàn hơn để sử dụng.] – Hendra

+0

@Hendra Chắc chắn, Mật khẩu là một ví dụ, nhu cầu của tôi quá phức tạp để giải thích rõ ràng. Nhưng tôi biết làm thế nào để thay đổi trình bày của một tế bào, với onDrawColumCell, nhưng không phải là nội dung văn bản, bất kỳ ví dụ hoặc tuto? – philnext

Trả lời

10

Có ít nhất 3 cách để thực hiện việc này, tôi sẽ minh họa bằng cách che dấu trường mật khẩu từ cơ sở dữ liệu. Tôi đang sử dụng máy chủ sql cho phương ngữ sql.

1. Xác định trường được tính toán trên chuỗi sql.

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

Sau đó, nhấp chuột phải vào dbgrid, chọn trình chỉnh sửa cột. Bên trong trình soạn thảo cột của dbgrid, chỉ cần chọn cột maskedPwd thay vì cột mật khẩu thực. Bây giờ dbgrid sẽ hiển thị giá trị mặt nạ thay vì mật khẩu.

hay

2. Xác định một lĩnh vực tính toán trên các số liệu được sử dụng bởi DBGrid.

Chỉ cần nhấp chuột phải vào tập dữ liệu và sử dụng trình chỉnh sửa trường để tạo trường được tính toán mới (ví dụ: maskedPwd2). Sau đó onCalcField trường hợp số liệu, viết code để thiết lập giá trị của maskedPwd2, ví dụ:

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

Hãy chắc chắn bao gồm maskedPwd2 trong trình soạn thảo cột của DBGrid.

hay

3. Viết tùy chỉnh văn bản trên các sự kiện onDrawColumnCell của 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; 

Lưu ý rằng đoạn mã trên chỉ hiển thị giá trị đeo mặt nạ, nhưng nếu lưới điện có thể chỉnh sửa, giá trị mật khẩu thực sẽ được hiển thị khi các tế bào tập trung/chỉnh sửa.

Để giải quyết vấn đề này, hãy thả TEdit trên biểu mẫu, xóa thuộc tính văn bản, đặt thuộc tính PpasswordChar thành '*' và hiển thị thành sai. Bây giờ nó đã sẵn sàng để được sử dụng như một sự thay thế cho trình soạn thảo sẵn có cho ô. Bây giờ, chúng ta cần một số logic keo, tức là

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; 

Lưu ý rằng mã trên không hoàn hảo, nhưng bản chất là ở đó. Tôi sẽ để nó cho bạn để tập thể dục.

+0

Câu trả lời rõ ràng và đầy đủ. – philnext

6

tôi sẽ viết một OnGetText cho trường mật khẩu trong tập dữ liệu của tôi, như giá trị của lĩnh vực không được hiển thị trong bất kỳ kiểm soát ở tất cả

+0

Chắc chắn nhưng câu hỏi của tôi không hoàn thành (xin lỗi), DBGrids của tôi được tạo động và tôi có thể có các TField khác nhau để tôi không thể gán OnGetText. Tôi xem OnDrawColumnCell thay thế. – philnext

+0

Tôi chưa bao giờ thử điều đó. Tôi đoán bạn có thể sử dụng này: 'với (Tên người gửi là TDBGrid) .Canvas bắt đầu Font.Color: = clWhite; Brush.Color: = clWhite; Brush.Style: = bsSolid; kết thúc; 'để ẩn giá trị bạn muốn, nhưng tôi không chắc chắn cách thay đổi văn bản thực tế của trường tại đó. Sẽ không dễ dàng hơn khi chỉ định một 'OnGetText' cho một vài' TField's? –

+0

Bây giờ tôi thấy tại sao bạn không thể sử dụng 'OnGetText', nhưng bạn có thể dễ dàng gán cùng một màu cho' font' và 'brush' trong' OnDrawColumnCell' cho cột _password_ của bạn. –

2

Bạn phải che giấu tất cả các giá trị trong toàn bộ một cột? Trong trường hợp đó, nếu bạn biết TField (hoặc tên trường) nào để làm điều này cho: hãy thử tự động tạo trường được tính toán với các giá trị đã sửa đổi và hiển thị trong cột.

+0

Bạn có thể chính xác hơn không? – philnext

+0

Tôi không có thời gian để làm ví dụ. Tại thời điểm bạn tạo ra các TFields cần masking, cũng làm TFields.Add để thêm một trường được tính toán. Đi qua TDBGrid.Columns, thay thế trường được sử dụng bởi cột đó. Bạn cũng phải móc một trình xử lý sự kiện OnCalcFields vào tập dữ liệu của bạn tất nhiên (có thể bạn đã có). Hy vọng việc này có thể thúc đẩy bạn. –

+0

Thx rõ ràng hơn. – philnext

1

Tôi sửa đổi mã ở trên để hiển thị và ẩn mật khẩu. Nếu người dùng nhấp vào ô Mật khẩu, nó sẽ hiển thị nó, khi họ nhấp vào ô, nó sẽ ẩn nó một lần nữa.

// 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; 

Không mất nhiều công việc để làm cho nó vào một lĩnh vực mật khẩu mát mẻ.

Quên một điều về sự kiện DBGrid Draw Column Cell, bạn nên thay đổi Edit1.Clear; để Edit1.Text: = Your_Table_Name.FieldByName ('Mật khẩu'). AsString;

Các vấn đề liên quan