메뉴 및 공용대화상자
1. 메뉴만들기
1) 리소스 파일
[1] 리소스파일 생성
- [리소스파일(우클릭) - 추가 - 리소스] 를 클릭한다.
[2] 메뉴리소스 추가
- Menu 리소스를 클릭하고 새로만들기를 누른다.
[3] 현재 프로젝트의 리소스 뷰에 접근
- 리소스를 만들면 .rc확장자를 가지는 리소스 파일이 생성되고 헤더파일에 Resource.h 파일이 만들어진다.
- [프로젝트명.rc] 파일을 더블클릭하면 현재 프로젝트의 리소스 뷰에 접근하게 된다.
[4] 메뉴리소스 확인
- 여러가지 리소스중에 우리가 만든 메뉴리소스를 더블클릭한다.
[5] 메뉴에 원하는 문자를 넣어 메뉴를 구성할 수 있다.
- [여기에 입력] 부분을 클릭하여 작성 후 Enter키를 누르면 저장된다.
[6] Popup - True
- FILE이라고 적은 것의 속성을 확인한다.
- 속성의 모양에 Popup을 보면 True로 체크되어 있다.
- 이 말은 이 캡션은 기능을 수행하는 것이 아닌 다른 캡션을 띄우는 역활을 한다는 말이다..
[7] Popup - False
- EXIT라고 적은 것의 속성을 확인한다.
- 속성의 모양에 Popup을 보면 False로 체크되어 있다.
- 이 말은 이 캡션은 누르면 특정 기능을 수행하는 역활을 한다는 말이다.
[8] ID속성
- [7]번 그림에서 보면 [속성 - 기타 - ID] 에 보통 숫자가 적혀있다.
- 이 숫자(정수)가 어떤 메뉴항목이 선택되었는지를 구분지어주며 윈도우메세지처리함수로 전달된다.
- Popup이 True면 기능을 수행하는 것이 아니기 때문에 편집이 불가능하다.
※ [7]번 그림의 ID를 보면 ID_EXIT라고 적혀있다.
- .rc 파일을 닫고 [헤더파일 - Resourec.h]을 열어서 내용을 확인한다.
- 위 그림과 같이 Resource.h 파일에 ID에 적은 메세지가 정수로 들어가있다.
- 이렇게 하는 이유는 컴퓨터는 숫자를 보고 해당하는 처리를 하겠지만
사람은 숫자만 보고는 무슨동작을 하는지 가늠할 수 가 없다.
- 그래서 숫자에 해당하는 기능에 맞게 ID를 부여한 것이다.
[9] Prompt
- ID를 가진 메뉴의 도움말을 작성한다.
[10] Enable
- 프로그램 실행 시 이 메뉴를 사용할 수 있는지 True나 False로 나타낸다.
[11] Separator
- 메뉴구분선을 넣을지 True나 False로 나타낸다.
- 기능수행과 무관하다.
2) 소스파일
[1] resource.h 파일추가
- [프로젝트명.h] 파일에 resoure.h파일을 추가한다.
[2] 메뉴설정 필드에 메뉴리소스 추가
- lpszMenuName 필드에 [메뉴리소스이름]을 넣어준다.
- 메뉴리소스이름은 [1) - [4]]그림에서 확인할 수 있다.
[3] 메세지처리함수의 소스
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { OPENFILENAME OFN; //OPENFILENAME 구조체는 commdlg.h에 정의되어 있다. //파일을 여는 대화상자의 구조체 변수 OPN을 생성한다. TCHAR str[100] = _T(""); TCHAR lpstrFile[100] = _T(""); //파일을 열기위해 선택하면 메세지박스를 띄울 예정이고, //이 파일이 맞는지 확인하는 문자열을 저장하기위한 임시변수이다. TCHAR filter[] = _T("Every File \0 *.*\0Text File \0 *.txt; *.doc\0"); //OFN.lpstrFilter 필드에 열기대화상자에 나오는 필터를 지정한다, //모든파일은 *.* 형식 //텍스트파일은 *.txt와 *.doc 형식 //을 선택할 수 있다. //\0(NULL)을 넣어서 끊을 수 있고, ;(세미콜론)을 넣어서 추가할 수 있다. int wmId = LOWORD(wParam); //wParam의 하위 2바이트에는 발생된 이벤트의 메세지(ID)가 저장되어 있다. //LOWORD() 함수는 하위 2바이트를 추출하는 함수이다. //wmId는 윈도우메세지 ID값을 저장하는 변수이다. int answer; //메세지박스에서 누른 버튼의 ID값을 저장하는 정수변수이다. switch (message) { case WM_COMMAND: switch (wmId) { case ID_FILENEW: //NEW를 눌렀다면? MessageBox(hWnd, _T("새 파일을 여시겠습니까?"), _T("새 파일 선택"), MB_OKCANCEL); //OK와 CANCEL 만 선택이 가능한 메세지박스 호출 break; case ID_FILEOPEN: //OPEN을 눌렀다면? memset(&OFN, 0, sizeof(OPENFILENAME)); //memset함수를 이용하여 구조체의 모든 공간을 0으로 채운다. OFN.lStructSize = sizeof(OPENFILENAME); //lStructSize 필드는 구조체의 크기를 넣는다. OFN.hwndOwner = hWnd; //hwndOwner 필드는 윈도우의 핸들값을 넣는다. OFN.lpstrFilter = filter; //lpstrFilter 필드는 위에서 정의한 필터 변수의 주소를 넣는다. OFN.lpstrFile = lpstrFile; //lpstrFile 필드는 위에서 정의한 파일이름 변수의 주소를 넣는다. OFN.nMaxFile = 100; //nMaxFile 필드는 파일이름의 최대길이 100으로 지정한다. OFN.lpstrInitialDir = _T("."); //대화상자에 가장 먼저 보여줄 폴더는 현재디렉토리로 지정한다. if (GetOpenFileName(&OFN) != 0) { //GetOpenFileName함수는 OFN구조체의 주소를 파라미터로 넣어서 //정상적인 파일을 잘 선택했다면 1을 반환하여 아래 메세지를 출력한다. _stprintf_s(str, _T("%s 파일을 여시겠습니까?"), OFN.lpstrFile); MessageBox(hWnd, str, _T("열기 선택"), MB_OK); } break; case ID_EXIT: //EXIT를 눌렀다면? answer = MessageBox(hWnd, _T("파일을 저장하고 끝내겠습니까?"), _T("끝내기 선택"), MB_YESNOCANCEL); if (answer == IDYES || answer == IDNO) { //yes나 no가 눌렸다면 종료, cancle이 눌렸다면 아무 것도 안하기 PostQuitMessage(0); } break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다... EndPaint(hWnd, &ps); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
- 만약 OPENFILENAME 구조체에서 에러가 발생한다면 #include <commdlg.h>를 맨 위에 추가해주면 사용할 수 있다.
- 새로운 라인은 모두 주석처리해서 확인할 수 있다.
3) 시연
- NEW를 클릭한다.
- 메세지박스가 나오는 것을 확인할 수 있다.(새로 만들기의 메세지박스 내용이 이상하긴 하지만..)
- 아직은 파일 여는 동작에 대해 서술하지 않았기 때문에 파일이 열리지는 않는다.
- OPEN을 누르면 공용대화상자가 나오고 파일 형식은 지정한 파일 형식만 열 수 있다.
- 대화상자 오픈하는 것까지만 했고 파일입출력에 대해서는 추후에 서술할 예정이다.
- 예나 아니오를 누르면 종료되고 취소를 누르면 종료되지 않는다.
'Programming Language > Windows API' 카테고리의 다른 글
대화상자 생성 (0) | 2018.12.09 |
---|---|
리소스파일 (0) | 2018.12.09 |
지렁이게임 (0) | 2018.09.30 |
두더지잡기 게임 (0) | 2018.09.30 |
입력된 방향키 확인 (0) | 2018.09.30 |
댓글