Tutorial 11: More about Dialog Box
그럼 다이얼로그 박스에 대해서 더 자세한 부분을 설명한다. 특히, 유저와 정보교환의 목적으로 다이얼로그 박스를 어떻게 사용하는지를 주의 깊게 보기바란다. 이전장의 설명을 읽었다면, 이 번장은 간단하다고 느낄 것일 것이다. 왜냐하면, 메인 윈도우의 보조수단으로 사용하기 위한 변경만 존재하기 때문이다. 이번장에서는 common dialog 박스에 대해서도 설명한다.
소스 1 | 리소스 스크립트 1 | 실행 결과 1 |
소스 2 | 리소스 스크립트 2 | 실행 결과 2 |
소스 3 | 리소스 스크립트 3 | 실행 결과 3 |
|
프로그램의 정보 입출력용으로서 다이얼로그 박스를 사용하는 것에 대하여, 이번장에서 다시 설명하는 부분은 매우 적다. 늘 하던대로 메인 윈도우를 생성하고, 다이얼로그 박스를 표시하고 싶을 때, CreateDialogParam 함수(모달리스)나 DialogBoxParam 함수(모달)를 호출 하면 된다. DialogBoxParam 함수를 호출 했을 경우, 아무런 일도 하지 않고, 메세지 처리는 다이얼로그 박스 프로시저가 하게 된다. CreateDialogParam 함수로 생성했을 경우는, 메시지 루프에서 IsDialogMessage 함수를 호출해야만 하고, 다이얼로그 박스 매니저가 키보드 처리를 대신 해 주게 된다. 두가지 모두 특별한 일은 없기 때문에, 여기에서는 코드를 사용하지 않는다.
그럼 이제는, common dialog 박스의 설명을 하겠다. Windows는 기본적인 다이얼로그 박스를 몇가지 제공해 주고 있다. 이런 표준 다이얼로그 박스는 유저 인터페이스의 표준화를 실현해 준다. 파일, 인쇄, 색, 폰트, 검색 등에 사용하는 다이얼로그 박스가 있다. 가능한 한 이런 공용 다이얼로그 박스를 사용하길 바란다.공용 다이얼로그 박스는 comdlg32.dll 에 포함되어있다. 이들을 사용하기 위해서, comdlg32.lib 를 링크해주어야 한다.
사용하고자 하는 다이얼로그 박스에 상응한 공용 다이얼로그박스 프로그램의 라이브러리 함수를 호출 해서 사용한다. 파일을 오픈하는 다이얼로그 박스를 생성할 때는 GetOpenFileName 함수, 파일을 저장할 때는 GetSaveFileName 함수, 인쇄는 PrintDlg 함수등이 그것이다. 이런 함수는 각각,대응되는 구조체의 포인터를 인수로 취하고 있고, 자세한 것은 Win32API 레퍼런스를 참조하기 바란다. 이 번장에서는, 파일을 오픈하는 다이얼로그 박스의 생성 방법 및 사용 방법을 설명한다. 다른것도 이와 유사하므로 이것만 익혀도 사용법을 알 수 있게 된다.
다음은, GetOpenFileName 함수의 프로토타입이다.
GetOpenFileName proto lpofn:DWORD보는 대로, 인수는 OPENFILENAME 구조체의 포인터 뿐이다. 반환값은 TRUE일경우 유저가 파일을 선택한 것을 의미하고, FALSE라면 아무것도 선택하지 않았다고 가정 하는 것이다. 다음으로 OPENFILENAME 구조체에 대해서 알아 보자.
OPENFILENAME STRUCT lStructSize DWORD ? hwndOwner HWND ? hInstance HINSTANCE ? lpstrFilter LPCSTR ? lpstrCustomFilter LPSTR ? nMaxCustFilter DWORD ? nFilterIndex DWORD ? lpstrFile LPSTR ? nMaxFile DWORD ? lpstrFileTitle LPSTR ? nMaxFileTitle DWORD ? lpstrInitialDir LPCSTR ? lpstrTitle LPCSTR ? Flags DWORD ? nFileOffset WORD ? nFileExtension WORD ? lpstrDefExt LPCSTR ? lCustData LPARAM ? lpfnHook DWORD ? lpTemplateName LPCSTR ? OPENFILENAME ENDS인수가 많으므로, 자주 사용되는 인수에 대해서 알아 보자.
- lStructSize
OPENFILENAME 구조체의 크기(바이트)- hwndOwner
현재 다이얼로그 박스의 윈도우 핸들- hInstance
다이얼로그 박스를 생성한 어플리케이션의 인스턴스 핸들- lpstrFilter
파일 형식을 지정하는데 사용하는 문자열의 쌍. 첫번째의 문자열은 설명이고, 두번째는 파일형식을 지정한다.
예) FilterString db "All Files (*. *)", 0, "*. *", 0
db "Text Files (*. txt)", 0,"*. txt", 0,0
두번째의 문자열에 해당하는 파일명만 Windows가 필터링 한다. 그리고,필터 문자열의 마지막에는 끝을 의미하는「0」을 추가하는것을 잊지말자.- nFilterIndex
다이얼로그 박스가 생성되었을 때, 어떤 필터문자열을 표시하는지를 지정한다. 1부터 시작되는 숫자로서 , 1번째 필터를 가장 먼저 표시하고 싶다면 1을 지정하고, 2번필터를 가장 먼저 표시하고 싶다면 2를 지정하면 된다. 위의 예에서는, 2 를 설정했고,"*. txt" 가 표시되게 된다.- lpstrFile
유저가 선택한 파일명이 풀 패스형태로 문자열 버퍼에 저장되며, 이공간은 최소한 260바이트의 영역이 필요하다. 또한, 다이얼로그 박스를 생성하기 전에 이 포인터에 문자열이 이미 설정되어 있으면, 그 문자열이 다이얼로그 박스가 표시될때 에디트 컨트롤에 미리 입력되게 된다.- nMaxFile
lpstrFile가 가리키는 문자열버퍼의 크기- lpstrTitle
다이얼로그 박스의 타이틀 문자열의 포인터- Flags
다이얼로그 박스의 스타일을 선택하는 플래그- nFileOffset
유저가 파일을 선택한 후, 풀 패스형태로 파일명이 lpstrFile에 설정 되지만, 그 문자열의 몇번째부터 파일명이 시작되는지를 나타낸다.
예) "c:\windows\system\lz32.dll" : nFileOffset = 18- nFileExtension
유저가 파일을 선택한 후, 풀 패스 형태로 확장자(extension)가 몇번째로부터 시작되는지를 나타낸다
|
다음의 예제에서는 메뉴에서 「File」→「Open」을 선택했을 때 파일을 오픈하는 다이얼로그 박스가 표시된다. 다이얼로그 박스로부터 유저가 파일을 선택하면, 선택된 파일명과, 확장자(extension), 풀 패스명을 메시지 박스로 출력한다.
|
|
mov ofn.lStructSize, SIZEOF ofn push hWnd pop ofn.hwndOwner push hInstance pop ofn.hInstance전형적인 ofn 구조체를 설정하는 코드이다.
mov ofn.lpstrFilter, OFFSET FilterString파일명 필터의 문자열을 설정한다.
FilterString db "All Files", 0,"*. *", 0 db "Text Files", 0,"*. txt", 0,0이것은 필터 문자열을 선언하는 부분으로, 4개의 문자열은 모두 「0」으로 끝나야 한다. 이들은 쌍으로 사용되기 때문에 첫번째의 문자열이 설명부분이며,두번째 문자열이 필터문자열이다. 이 예제에서는 필터문자열은 "*. *"과 "*. txt" 이다. 어떤 필터문자열이라도 가능하다. 그리고, 절대로 잊어서는 안되는 것은, 제일 마지막의 「0」이다. 이것은 필터문자열의 종료를 의미하기 때문이다.
mov ofn.lpstrFile, OFFSET buffer mov ofn.nMaxFile, MAXSIZE유저가 선택한 파일명을 저장하는 버퍼를 설정한다. 그리고, nMaxFile 멤버로 그 버퍼의 크기를 설정한다. 이후에, 버퍼로부터 파일명을 추출하게 된다.
mov ofn.Flags, OFN_FILEMUSTEXIST or \ OFN_PATHMUSTEXIST or OFN_LONGNAMES or\ OFN_EXPLORER or OFN_HIDEREADONLY다이얼로그 박스의 스타일을 선택하는 플래그다.
OFN_FILEMUSTEXIST 와 OFN_PATHMUSTEXIST 는 파일명을 입력하는 에디트 컨트롤에 파일명이 반드시 존재 해야함을 요구한다.
OFN_LONGNAMES 는 다이얼로그 박스에 표시되는 파일명이긴 파일명으로 표시가능 하다는 의미한다(긴 파일명이 아닌 경우에는 8.3 형식의 파일명으로 표시된다)
OFN_EXPLORER 는 다이얼로그 박스가 탐색기형태로 표시된다.
OFN_HIDEREADONLY 는 다이얼로그 박스의 읽기전용 체크 박스를 숨긴다.실제론 더 많은 플래그가 존재하지만, 여기에서는 간단히 설명했다. 자세한것은 Win32API 레퍼런스를 참고하기 바란다.
mov ofn.lpstrTitle, OFFSET OurTitle다이얼로그 박스의 타이틀을 설정한다.
invoke GetOpenFileName, ADDR ofn인수로 ofn 구조체를 설정하고, GetOpenFileName 함수를 호출 한다.
이 때, 파일 오픈 다이얼로그 박스는 화면에 표시되고, 유저가 파일을 선택하든가(eax == TRUE), 취소 버튼을 누르는 등, 다이얼로그 박스를 닫을 때까지 제어를 반환하지 않는다.(모달)유저가 어떠한 파일을 선택해서 함수로부터 제어가 돌아 왔을 때에, eax 레지스터에는 TRUE가 설정되어 유저가 파일을 선택했다는 것을 알 수있다.FALSE라면 어떤 파일도 선택하지 않았다는 의미이다.
.if eax==TRUE invoke lstrcat, offset OutputString, OFFSET FullPathName invoke lstrcat, offset OutputString, ofn.lpstrFile invoke lstrcat, offset OutputString, offset CrLf invoke lstrcat, offset OutputString, offset FullName유저가 파일을 선택했을 경우, 메시지 박스에 출력할 문자열을 준비한다. OutputString 변수를 메모리에 설정하고, 문자열을 연결하기 위해서 API 함수 lstrcat 를 호출 한다.여러줄의 문자열을 구별하기 위해서 개행문자로 문자열을 종료해준다. (CrLf)
mov eax, ofn.lpstrFile push ebx xor ebx, ebx mov bx, ofn.nFileOffset add eax, ebx pop ebx invoke lstrcat, offset OutputString, eax위의 몇 줄은 설명이 필요 할 것이다. nFileOffset 는 lpstrFile 에 설정되어있는 풀 패스형태의 문자열중 파일명이 몇번째부터 시작되는지를 나타낸다. 그러나, lpstrFile 는 DWORD 크기로, nFileOffset는 WORD 크기이므로 직접 2개의 변수를 직접 계산할 수 없기때문에, nFileOffset 를 일단 ebx의 하위워드에 저장하고, 그값으로 lpstrFile를 더해서 처리해야만 한다.(형식 일치)
invoke MessageBox, hWnd, OFFSET OutputString, ADDR AppName, MB_OK메시지 박스에 문자열을 출력한다.
invoke RtlZerolMemory, offset OutputString, OUTPUTSIZEOutputString은 사용후에는 반드시, 클리어 해 두어야한다. 그래서, RtlzeroMemory 함수를 호출해서, 클리어처리를 해준다.