2012-09-19 22 views
5

Muszę wyświetlić zmodyfikowaną "zamaskowaną" wartość w VCL TDBGrid (Delphi XE2), tj .: zmienić "hasło" na "xxxxxxxx" lub wielkie "przejść" na "PASS" lub inni. Ponieważ moje pola są tworzone dynamicznie (ale nazwa jest kodowana, więc wiem jak i kiedy zamaskować je, tj .: xxxx_PASSW dla pól hasła) Nie mogę użyć zdarzenia (myślę) OnGetText.Jak zmienić wartość komórki w Delphi TDBGrid

Jaki jest najskuteczniejszy sposób na zrobienie tego (jak już używam OnDrawColumnCell do jakiejś modyfikacji prezentacji, wolałbym go użyć)?

+0

Istnieją 3 sposoby, aby to zrobić. 1. Utwórz pole obliczeniowe dla hasła w zestawie danych używanym przez dbgrid. 2. Utwórz pole obliczeniowe dla hasła w instrukcji SQL select. lub 3. użyj zdarzenia onDrawColumCell/Data dla dbgrid, jak to podano powyżej. Ale ja osobiście nie lubię przechowywania hasła w bazie danych, ale hash-kodowanej wersji hasła. Ponieważ kod skrótu jest funkcją jednokierunkową (tzn. Nie może uzyskać oryginalnego hasła z kodu skrótu), a tylko poprawne hasło może wygenerować ten sam kod skrótu, jest bezpieczniejsze w użyciu.] – Hendra

+0

@Hendra Sure, hasło było przykład, moje potrzeby są zbyt skomplikowane, aby jednoznacznie wyjaśnić. Ale wiem, jak zmienić prezentację komórki za pomocą onDrawColumCell, ale nie treści tekstowej, żadnego przykładu czy tuto? – philnext

Odpowiedz

10

Są co najmniej 3 sposoby, aby to zrobić, zilustruję poprzez maskowanie pola hasła z bazy danych. Używam serwera sql dla sql dialekt.

1. Zdefiniuj obliczone pole w ciągu znaków sql.

Następnie kliknij prawym przyciskiem myszy na dbgrid, wybierz edytor kolumn. W edytorze kolumn dla dbgrid wystarczy wybrać kolumnę maskedPwd zamiast kolumny prawdziwego hasła. Teraz dbgrid wyświetli zamaskowaną wartość zamiast hasła.

lub

2. Zdefiniuj pole obliczona na zbiorze danych używanej przez DBGrid.

Po prostu kliknij prawym przyciskiem myszy na zestaw danych i użyj edytora pól, aby utworzyć nowe pole obliczeniowe (np. MaskedPwd2). Następnie onCalcField wydarzeniem zbioru danych, napisać kod, aby ustawić wartość maskedPwd2, tj

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

Upewnij się m.in. maskedPwd2 w edytorze kolumny w DBGrid.

lub

3. Zapis własny tekst na razie onDrawColumnCell w 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; 

Zauważ, że powyższy kod tylko wyświetlanie wartości zamaskowany, ale jeśli siatka jest edytowalny, rzeczywista wartość hasło będzie widoczne, gdy komórka skupia/edytowany.

Aby uporać się z tym, upuść TEdit na formularzu, wyczyść właściwość text, ustaw właściwość PpasswordChar na "*", a widoczną na false. Teraz jest gotowy do użycia jako zamiennik wbudowanego edytora dla komórki. Teraz musimy trochę logiki klejenie, tj

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; 

Zauważ, że powyższy kod nie jest doskonały, ale, ale istota istnieje. Zostawię to dla ciebie do ćwiczeń.

+0

Wyczyść i uzupełnij odpowiedź. – philnext

6

chciałbym napisać OnGetText na polu hasła w moim zbiorze, jak wartość pola nie powinny być wyświetlane w dowolnej kontroli na wszystkich

+0

Pewnie, ale moje pytanie nie było kompletne (przepraszam), moje DBGrids są dynamicznie tworzone i mogę mieć różne TFieldy, więc nie mogę przypisać OnGetText. Zamiast tego uważam OnDrawColumnCell. – philnext

+0

Nigdy tego nie próbowałem. Sądzę, że możesz użyć tego: 'with (Sender jako TDBGrid) .Canvas rozpoczyna Font.Color: = clWhite; Brush.Color: = clWhite; Brush.Style: = bsSolid; end; ', aby ukryć żądaną wartość, ale nie wiem, jak zmienić tam tekst rzeczywisty pola. Czy nie byłoby łatwiej przypisać jeden 'OnGetText' do kilku' TField'ów? –

+0

Teraz widzę, dlaczego nie można użyć 'OnGetText', ale można łatwo przypisać ten sam kolor do' font' i 'brush' w' OnDrawColumnCell' dla kolumny _password. –

2

Czy trzeba zamaskować wszystkie wartości w całej kolumnie? W takim przypadku, jeśli wiesz, co TField (lub nazwa pola) to zrobić: spróbuj dynamicznie tworzyć pole obliczeniowe ze zmodyfikowanymi wartościami i wyświetlać je w kolumnie.

+0

Czy możesz być bardziej precyzyjny? – philnext

+0

Nie mam czasu na wypracowanie przykładu. W momencie tworzenia TFieldów, które wymagają maskowania, należy również dodać TFFs.Add, aby dodać pole obliczeniowe. Przejdź przez TDBGrid.Columns, zastąp pole używane przez tę kolumnę. Musisz również przypiąć procedurę obsługi zdarzenia OnCalcFields do swojego zestawu danych (oczywiście, że już go masz). Mam nadzieję, że to się zaczyna. –

+0

Więcej jasne thx. – philnext

1

Modyfikuję powyższy kod, aby wyświetlić i ukryć hasło. Jeśli użytkownik kliknie komórkę Hasło, pokaże ją, gdy kliknie komórkę, ukryje ją ponownie.

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

Nie potrzeba wiele pracy, aby uczynić go chłodnym polu hasła.

Zapomniałem jednej rzeczy na temat zdarzenia DBGrid Draw Column Cell, powinieneś zmienić Edit1.Clear; do Edit1.Text: = Your_Table_Name.FieldByName ("Password"). AsString;

Powiązane problemy