posted by nsakura 2010. 7. 20. 22:02

프로그램은 코드와 데이터로 구성.

데이터는 프로그램의 처리 대상을 말하죠

코드는 데이터를 처리하기 위한 수단이 되는거죠.

도스에서는 이런 데이터를 만들고 관리하는 작업이 하나의 과정에 통합되어있었지만.

윈도우 에서는 분리되어있고

리소스라고 하면 메뉴,비트맵, 액셀러레이터, 문자열, 아이콘,커서 등이 여기에 속한다.

그렇다면.. 분리하면 뭐가 좋을까?

1. 디자이너와 프로그래머가 분담하여 작업이 편리하다.

2. 리소스를 수정하더라도 소스를 일일히 다시 컴파일 하지 않아도 리소스만 컴파일 하면 된다.

3. 재사용에 용이하다

4. 리소스는 실행중에 교체가 가능한 모듈이므로 상황에 따라 다른 형태의 리소스를 사용 할 수 있다.

리소스 작성

리소스는 RC파일로 작성하는데 이 파일은 메모장 등으로 편집이 가능하고 스크립트 레벨의 언어를 사용한다.

RC파일을 컴파일하면 이진파일이 만들어지고 (RES) 최종적으로 실행파일에 합쳐진다.

자 그럼 프로젝트를 하나 생성한다. 그리고 CPP파일을 하나 만드는데.

#include <windows.h>
#include "resource.h"

HINSTANCE g_Inst;
LPCTSTR wndName=TEXT("GFP MENU");

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_Inst=hInstance;

 WndClass.cbClsExtra=0;
 WndClass.cbWndExtra=0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
 WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance=hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=wndName;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(wndName,wndName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);

 ShowWindow(hWnd,nShowCmd);
 while(GetMessage(&Message,NULL,0,0)){
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }


 return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
  }
  return 0;
 }
 
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

이렇게 틀만 만들어 둔다.

이제 리소스를 만들어보자 파일을 생성할때 Resource Script

를 선택하고 확장명을 rc로 설정하고 ok를 누르면 된다.

그리고 워크 스테이션에 리소스뷰 탭에 가면 만든 rc파일이 보일것인데 아무것도 만들지 않았으므로 아무것도 빈 폴더로 표시 될것

이다.

말로 설명하니 힘드니 한장의 스크린샷을 첨부한다.


여기서 메뉴 rc를 선택하고. insert를 누르면


이렇게 뜰것이다 메뉴를 선택하고 뉴를 선택.


이렇게 메뉴를 만들어주자.

메뉴를 만들때.


ID부분은 메뉴의 특징을 나타낼수있게 만드는게 편할것이다.

WinMain에는

 WndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);

그리고 WndProc 함수에

 case WM_COMMAND:
  switch(LOWORD(wParam)){
  case ID_NSAKURA:
   MessageBox(hWnd,TEXT("Nsakura 입니다."),TEXT("NSAKURA"),MB_OK);
   break;
  case ID_EXIT:
   MessageBox(hWnd,TEXT("종료 합니다.."),TEXT("EXIT"),MB_OK);
   DestroyWindow(hWnd);


를 추가한다.


자 코드 설명 들어가자.

메뉴의 항목의 id는 정수의 값인데 이걸 일일히 외울수 없기 때문에 메크로로 정의가 되어있는데.

"resource.h" 를 열어보자.

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by menu.rc
//
#define IDR_MENU1                       101
#define ID_NSAKURA                      40001
#define ID_EXIT                         40002

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40003
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

이렇게 되어있다.

그러므로 리소스를 사용한다면. 당연히 따라오는 인클루드는 resource.h가 필요하게 된다.

WndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);

MAKEINTRESOURCE는 숫자로 정의된 메뉴 이름을 문자열 형태로 바꾸기 위해 사용한다.

위에 보면 #define IDR_MENU1                       101 만일 문자열이라면

이해가 안되는분을 위해 스샷을 준비!



이렇게 문자열로 바꾸면

WndClass.lpszMenuName=TEXT("menu");

이렇게 바꾸면 되겠다.

하지만 되도록이면 숫자로 사용하는게 좋다

이유는 간단. 문자는 인간과 친하지만.

기계는 숫자랑 친하기 때문이다.

문자열로 테스트 했다면 다시 원상 복구 하라.

참고로 한가지 더 방법이 있는데

 WndClass.lpszMenuName=(TCHAR*)IDR_MENU1; 이방법도 있는데 이유는.

MAKEINTRESOURCE 이녀석의 정의를 보면 된다.

#define MAKEINTRESOURCE(i) (LPSTR)((DWORD)((WORD)(I)))

이렇게 정의되어있기 때문이다.

결국

(TCHAR*)IDR_MENU1 =MAKEINTRESOURCE(IDR_MENU1);

이렇게 되는것이다.

WndProc의 새로운 메세지가 있다.

바로 WM_COMMAND 이다.

WM_COMMAND는  사용자가 메뉴 항목을 선택하면 WM_COMMAND 메세지가 발생된다.

사용자가 어떤 메뉴를 선택를 선택하였는가 판별은 wParam으로 할수 있다.

그렇기 때문에 LOWORD(wParam)으로 판별하면 되겠다.

WM_COMMAND는 메뉴선택뿐만 아니라.. 액셀러레이터[단축키]를 눌러도. 발생하며

자주 사용하게 된다.

 lParam  통지 메세지를 발생시킨 컨트롤의 윈도우 핸들
 LOWORD(wParam)  메뉴나 액셀러레이터 컨트롤의 ID
 HIWORD(wParam)  컨트롤이 보내는 통지 메시지 메뉴가 선택된 경우 0이 되며 액셀러레이터가 선택된 경우는 1

메뉴의 추가나 삭제는 직접 실습해보기 바란다.

삭제시 파업메뉴를 삭제한다면 하위의 메뉴까지 모두 날라가니 주의하자.




'Computer > Win API' 카테고리의 다른 글

WinApi 리소스 [액셀러레이터]  (0) 2010.07.20
WinApi 리소스 [아이콘][커서]  (2) 2010.07.20
WinApi WM_SIZE  (0) 2010.07.20
WinApi 생성과 종료, 작업영역  (0) 2010.07.19
WinApi 타이머 확장 2  (0) 2010.07.19