Aplikacja konsolowa - jak pobrać hasło

piechnat

Czasami przy pisaniu aplikacji konsolowej zachodzi potrzeba pobrania od użytkownika hasła. Jak wiadomo procedura ReadLn pokazuje na ekranie wpisywane znaki więc nie nadaje się do tego celu. Poniższy kod pokazuje jak w prosty sposób wykonać to zadanie.

program PasswordTest;

{$APPTYPE CONSOLE}

uses Windows;

function ReadChar: Char;
var
  InptHnd: THandle;
  NumRead: Cardinal;
  InptRec: TInputRecord;
begin
  InptHnd := GetStdHandle(STD_INPUT_HANDLE);
  repeat
    ReadConsoleInput(InptHnd, InptRec, 1, NumRead);
    Result := InptRec.Event.KeyEvent.AsciiChar;
    if (InptRec.EventType and KEY_EVENT <> 0) and (Result <> #0)
      and InptRec.Event.KeyEvent.bKeyDown then Break;
  until False;
end;

procedure BackSpace;
var
  OtptHnd: THandle;
  Csbi: TConsoleScreenBufferInfo;
  Crd: TCoord;
  I: Integer;
  Noaw: Cardinal;
begin
  OtptHnd := GetStdHandle(STD_OUTPUT_HANDLE);
  GetConsoleScreenBufferInfo(OtptHnd, Csbi);
  Crd := Csbi.dwCursorPosition;
  I := Pred(Crd.X + (Csbi.dwMaximumWindowSize.X * Crd.Y));
  Crd.X := I mod Csbi.dwMaximumWindowSize.X;
  Crd.Y := I div Csbi.dwMaximumWindowSize.X;
  FillConsoleOutputCharacter(OtptHnd, #32, 1, Crd, Noaw);
  SetConsoleCursorPosition(OtptHnd, Crd);
end;

function ReadPasswd(PasswdChar: Char = '*'): string;
var
  Ch: Char;
  I: Integer;
begin
  Result := '';
  repeat
    Ch := ReadChar;
    case Ch of
      #08:
        begin
          I := Length(Result);
          if I > 0 then
          begin
            Delete(Result, I, 1);
            BackSpace;
          end;
        end;
      #13:
        Break;
    else
      Result := Result + Ch;
      Write(PasswdChar);
    end;
  until False;
  WriteLn;
end;

var
  Pass: string;
begin
  Write('Enter password: ');
  Pass := ReadPasswd;
  Write('Your password is "', Pass, '".');
  ReadLn;
end.

0 komentarzy