Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 팁&트릭
Delphi Programming Tip&Tricks
[313] Undocumented: InputBox 함수에서 Password 입력 받기
박지훈.임프 [cbuilder] 34566 읽음    2013-09-26 01:32
간단하지만 경우에 따라 꽤 유용하게 쓸 수 있는 팁입니다.
(아쉽게도, Delphi/C++Builder의 XE2  버전 이상에서만 가능한 기능입니다 -.-;;)

VCL에 InputQuery와 InputBox라는 함수가 있습니다. 아주 초보적인 함수인데, 아주 자주 쓰는 개발자도 있고 전혀 존재조차 모르는 분들도 꽤 많이 있습니다. 이 두 함수는 본질적으로 거의  같은 함수인데, 조그만 다이얼로그가 떠서 문자열을 입력받아 전달해주는 함수입니다. 가령 다음과 같이 한줄을 코딩하면,
Label1.Caption := InputBox('아이디 입력', '아이디: ', 'imp');

이 코드가 실행될 때 다음과 같은 다이얼로그가 나타납니다.



파라미터를 자세히 설명할 것도 없이 위 코드와 그림을 비교해보시면, 첫번째 인자는 다이얼로그의 타이틀에, 두번째 인자는 입력할 에디트의 바로 위에, 세번째 인자는 에디트의 기본값으로 나타난다는 것을 아실 수 있겠지요? 그리고 짐작하시겠지만 여기에 입력한 내용은 Label1에 나타나게 됩니다. 즉 에디트에 입력한 내용이 InputBox()의 리턴값입니다.

InputQuery()는 기본적으로 같은 함수인데 약간 다릅니다. 리턴값이 boolean 타입이라, 사용자가 OK 혹은 Cancel을 누른 결과가 리턴됩니다. 즉 InputBox()에서는 사용자가 Cancel을 클릭하더라도 에디트를 비운 상태에서 OK를 클릭한 것과 구분이 되지 않습니다만, InputQuery()에서는 구분이 됩니다. 대신 입력한 리턴값은 마지막 인자로 돌아옵니다. 즉 InputQuery()에서는 마지막 인자를 var 타입 변수로 넘겨줘야 합니다.

(InputBox()는 내부적으로 InputQuery()를 호출합니다)

그런데, 패스워드를 입력받으려면 어떻게 해야 할까요? 패스워드를 입력받으려면 에디트에서 입력되는 글자들이 보이지 않아야 하는데요. 이게 그냥 TEdit를 액세스할 수 있다면 TEdit의 PasswordChar 속성을 '*'로 설정해버리면 간단히 되는데, 다이얼로그에 나타나는 에디트의 PasswordChar 속성을 직접 액세스하기 어렵지요. XE까지의 버전에서는 방법이 없었습니다.  InputBox()나 InputQuery()에서 패스워드 기능을 너무나 원했던 외국의 개발자들은, 다이얼로그 안의 TEdit의 핸들을 찾아 윈도우 메시지로 PasswordChar를 설정해주는 방법을 쓰기도 했습니다.

물론 직접 폼을 만들어서 이런 다이얼로그를 만드는 일은 간단합니다. 그런데 아주 간단히만 쓰려고 하는데 폼을 하나 더 추가하기가 더 번거로울 때도 있습니다.

이게, XE2 버전부터는 간단히 되게 되었습니다. 마침 InputBox() 함수를 쓸 일이 있어 VCL의 소스를 뒤졌는데, 그런 기능이 추가되었더군요. 그런데 좋은 기능을 추가해놓고도 헬프와 문서에는 없습니다. 델파이, C++빌더의 헬프를 아무리 봐도 패스워드 입력 기능에 대한 아무런 언급이 없네요. VCL 소스를 직접 뒤져봐야지만 그런 기능이 추가되었다는 사실을 알 수 있습니다.

어쨌든, InputBox()와 InputQuery()에서 패스워드 입력 기능을 쓰려면, 방법은 아주 간단합니다. 두번째 인자 앞에, 문자코드가 32보다 작은 문자를 하나 더 붙여주기만 하면 됩니다. 앞에 덧붙여진 32보다 작은 문자 값은 화면에 나타나지 않고 무시됩니다. (InputQuery()도 마찬가지입니다)

Label1.Caption := InputBox('아이디 입력', #31 + '아이디: ', 'imp');



여기서, VCL의 개발자가 32보다 작은 값으로 정했던 이유는 간단합니다. 문자코드 32는 스페이스이고, 이 스페이스부터 화면에 보이는 영숫자 등의 문자들입니다. 31이나 그보다 작은 값들은 제어코드로서 화면에 나타나지 않는 문자들이기 때문에, 개발자가 화면에 표시할 문자열에 31이나 그보다 작은 문자를 포함시킬 리가 없으니까요.

아주 중요한 기능은 아니고 편의 기능에 불과하긴 하지만, 적지 않은 개발자들이 오랫동안 바랬던 기능인데, 드디어 추가하고도 문서에 추가하지 않은 것은 좀 어이가 없습니다.

쓴 김에 마저 언급하자면, XE2 이후의 InputQuery()에는 여러 값을 입력받을 수 있는 기능도 추가되었습니다. InputQuery() 함수 자체가 여러 버전으로 오버로드되어, 여러 값들을 전달하고 받을 수 있게 되었습니다. (InputBox()는 입력된 값을 단 하나의 결과값만 리턴받기 때문에 불가능합니다)

긴 설명보다는 간단한 예제 코드가 더 이해하기 쉽겠죠? 아래는 델파이 코드입니다.
procedure TForm1.Button1Click(Sender: TObject);
var
  sValues: array[0..1] of string;
  sUserID, sPassword: string;
begin
  if InputQuery('로그인', ['아이디: ', #31+'패스워드: '], sValues) then
  begin
    sUserID := sValues[0];
    sPassword := sValues[1];
  end
  else
    ShowMessage('로그인 취소하셨네용?');
end;


C++빌더라면 다음과 같이 됩니다.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	String sUserID, sPassword;
	String sPrompts[2], sValues[2];
	sPrompts[0] = "아이디: ";
	sPrompts[1] = String(Char(31))+"패스워드: ";
	if(InputQuery("로그인", sPrompts, 1, sValues, 1))
	{
		sUserID = sValues[0];
		sPassword = sValues[1];
	}
	else
		ShowMessage("로그인 취소하셨네용?");
}

위 코드의 결과는 다음과 같습니다.



즉, 두번째, 세번째 인자에 각각 두 개의 값을 전달하게 되는데요. 둘 다 array of string 입니다만 세번째 인자는 var로 받아야 하기 때문에 array of string 변수로 선언해놓고 넘겨줘야 합니다. 그리고 앞에서 설명했듯이, 두번째 입력 에디트는 패스워드를 입력받아야 하므로 두번째 인자 배열의 두번째 '패스워드:' 문자열 앞에 #31을 붙여줬습니다. (물론 단지 두개만이 아니라 10개, 20개 이상도 가능합니다)

이렇게 여러 값을 입력받을 수 있다는 사실도, 문서에는 역시 안나와있습니다. 단지 오버로드된 함수들의 프로토타입들만 보여줄 뿐, 설명에는 하나의 입력만 가능했던 이전 버전들의 설명 텍스트가 그대로입니다. 그래서 오버로드된 선언을 유심히 보지 않으면 그런 기능이 있는줄 알 수조차 없습니다. 코드 샘플 페이지에도 이전의 단순한 예제만 그대로 있고요. 그래서, 지금도 구글링을 해보면, 델파이 최근 버전들에서 여러 값을 입력받기 위해 직접 구현해서 소스를 공개한 개발자들까지 있습니다. (대체 엠바카데로는 일을 어떻게 하는 거야? -.-;;)

뭐, 세심한 디자인이 필요한 프로젝트라면 당연히 이런 다이얼로그도 직접 디자인해서 폼으로 추가하는 게 맞겠지만, 간단한 프로젝트, 예를 들어 파일럿 프로그램 같은 것을 만드는 데에 일일이 입력용 다이얼로그를 다 디자인해서 폼으로 추가하기는 번거롭겠지요. 그럴 때 아주 유용하게 쓸 수 있겠습니다.
memi [j00nh0]   2013-09-27 17:26 X
간단한 테스트 프로그램 자주 만드는데 아주 유용하게 잘 쓰고 있습니다~
감사합니다.

+ -

관련 글 리스트
313 Undocumented: InputBox 함수에서 Password 입력 받기 박지훈.임프 34566 2013/09/26
(링크)     C++Builder Tip'N Tricks > Undocumented: InputBox 함수에서 Password 입력 받기
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.