2011년9월7일_winAPI_문자열테이블(String Table)



● 전체 소스코드

▷ main.cpp

   1: // 문자열 테이블 리소스 .
   2: // 2011년 9월 7일 작성 
   3: #include <windows.h>    // 모든 API함수들의 원형과 사용하는 상수들이 정의되어 있음.
   4: #include "MsgProc.h"    //add
   5: #include "resource.h"    //자동으로 만들어지는 헤더파일.
   6:  
   7: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);    //메시지처리함수
   8: HINSTANCE g_hlnst;    //핸들 인스턴스
   9: LPCTSTR lpszClass = TEXT("StrTable");        //윈도우 제목으로 사용되는 const char * (문자열)
  10:  
  11: //add
  12: typedef struct MESSAGEMAP {
  13:     UINT iMessage;
  14:     LRESULT (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
  15: } MESSAGEMAP;
  16:  
  17: //시작함수.
  18: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
  19: {
  20:     HWND hWnd;
  21:     MSG Message;
  22:     WNDCLASS WndClass;
  23:     g_hlnst = hInstance;
  24:  
  25:     WndClass.cbClsExtra = 0;
  26:     WndClass.cbWndExtra = 0;
  27:     //WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  28:     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  29:     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  30:     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  31:     WndClass.hInstance = hInstance;
  32:     WndClass.lpfnWndProc = WndProc;
  33:     WndClass.lpszClassName = lpszClass;
  34:     WndClass.lpszMenuName = NULL;
  35:     WndClass.style = CS_HREDRAW | CS_VREDRAW;
  36:     RegisterClass(&WndClass);
  37:  
  38:     
  39:     hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
  40:         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,        
  41:         NULL, (HMENU)NULL, hInstance, NULL);
  42:     
  43:     ShowWindow(hWnd, nCmdShow);
  44:  
  45:     while(GetMessage(&Message, NULL, 0, 0)) 
  46:     {
  47:         TranslateMessage(&Message);
  48:         DispatchMessage(&Message);
  49:     }
  50:  
  51:     return (int)Message.wParam;
  52: }
  53:  
  54: //운영체제가 호출하는 CALLBACK함수 (메시지 처리)
  55: LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
  56: {
  57:     //add
  58:     int i;
  59:  
  60:     static MESSAGEMAP MessageMaps[] = {
  61:         {WM_CREATE, OnCreate},
  62:         {WM_COMMAND, OnCommand},
  63:         {WM_LBUTTONDOWN, OnLButtonDown},
  64:         {WM_PAINT, OnPaint},
  65:         {WM_DESTROY, OnDestroy}
  66:     };
  67:  
  68:     for(i = 0 ; i < sizeof(MessageMaps) / sizeof(MessageMaps[0]) ; ++i)
  69:     {
  70:         if(MessageMaps[i].iMessage == iMessage)
  71:         {
  72:             return (*MessageMaps[i].lpfnMsgProc)(hWnd, wParam, lParam);
  73:         }
  74:     }
  75:     /////////////////////////////////
  76:  
  77:     return(DefWindowProc(hWnd, iMessage, wParam, lParam));
  78: }


▷ MsgProc.h

   1: //MsgProc.h
   2: #ifndef __MSGPROC_H_
   3: #define    __MSGPROC_H_
   4:  
   5: #include <windows.h>
   6:  
   7: LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
   8: LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
   9: LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
  10: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam);
  11: LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam);
  12:  
  13: extern HINSTANCE g_hlnst;
  14:  
  15: #endif


▷ MsgProc.cpp

   1: //MsgProc.cpp
   2:  
   3: #include "MsgProc.h"
   4: #include "resource.h"
   5:  
   6:  
   7: LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
   8: {
   9:     return 0;
  10: }
  11:  
  12: LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
  13: {
  14:  
  15:     return 0;
  16: }
  17:  
  18: LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
  19: {
  20:  
  21:     return 0;
  22: }
  23:  
  24: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
  25: {
  26:     HDC hdc;
  27:     PAINTSTRUCT ps;
  28:     TCHAR str[256];
  29:  
  30:     hdc = BeginPaint(hWnd, &ps);
  31:  
  32:     LoadString(g_hlnst, IDS_STRING1, str, sizeof(str));
  33:     LoadString(GetModuleHandle(NULL), IDS_STRING1, str, sizeof(str));    //인스턴스를 얻는 함수사용.
  34:     TextOut(hdc, 10, 10, str, lstrlen(str));
  35:  
  36:     EndPaint(hWnd, &ps);
  37:  
  38:     return 0;
  39: }
  40:  
  41: LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
  42: {
  43:     PostQuitMessage(0);
  44:     return 0;
  45: }
  46:  




● 문자열 테이블 리소스 생성과 링크




imageimage

메뉴 – Insert - Resource를 선택하여 리소스를 추가하자.
abc모양 아이콘의 String Table을 선택하고 New버튼을 클릭하여 새로운 문자열 테이블을 만든다.


image

파란 막대로 칠해진 빈 칸을 더블클릭하여 속성창을 열고,
ID는 디폴트로 정해진 그대로 두고 Caption에 아무 문자열을 입력하고 닫자.

실행파일과 링크를 위해..

  32:     LoadString(g_hlnst, IDS_STRING1, str, sizeof(str));

LoadString(g_hlnst, IDS_STRING1, str, sizeof(str));

LoadString()를 사용해 문자열테이블에서 문자열을 불러 온다.
이 함수의 원형은 다음과 같다.

int LoadString(HINSTANCE hInstance,        // 프로그램의 인스턴스(객체) 핸들
                                 UINT uID,       // 문자열 테이블 ID
                         LPTSTR lpBuffer,       // 문자열을 읽을 버퍼
                           int nBufferMax);       // 버퍼의 길이 (Byte단위)

프로그램의 인스턴스 핸들은 WinMain() 시작시 첫 번째 인자로, WinMain() 내부에서만 사용할 수 있으므로..
다른 함수나 다른 소스파일에서도 사용할 수 있도록 해야한다.

main.cpp

   8: HINSTANCE g_hlnst;    //핸들 인스턴스
  23:     g_hlnst = hInstance;

HINSTANCE type으로 WinMain()위에 핸들을 선언하고, WinMain() 안에서 그 핸들에 인스턴스값을 대입한다.


MsgProc.h

  13: extern HINSTANCE g_hlnst;

MsgProc.cpp는 메시지맵에 등록된 함수들이 있는 곳으로 실제 메시지 발생시 하는 일이 있으므로,
여기에서 프로그램 인스턴스 핸들을 사용해야 한다.
main.cpp에 선언된 변수를 사용하기 위해 extern지시어를 사용해 외부변수라는 것을 지정하여,
링크시에 서로 참조할 수 있도록 한다.

다른 방법으로…

  33:     LoadString(GetModuleHandle(NULL), IDS_STRING1, str, sizeof(str));    //인스턴스를 얻는 함수사용.

GetModuleHandle()을 사용하여 현재 실행 중인 프로그램의 인스턴스를 리턴받아 넣는 방법도 있다.
이렇게 문자열 테이블을 사용하면 다음과 같은 장점이 있다.



● 문자열테이블 사용시 장점

문자열 자체가 코드와 분리됨으로써 문자열만 따로 관리할 수 있으며 프로젝트를 유지하는데 큰 도움을 준다.
    매크로의 장점과 유사하다.
    프로그래머와 메시지 문자열을 관리하는 사람이 따로 있어,
    프로그래머는 코드에만 집중하고,
    메시지 문자열은 문장가에게 맡기면 문체의 일관성과 내용이 충실해진다.

다국어 버전을 쉽게 만들 수 있다.
    소스코드와 리소스가 분리되어 있으므로 언어를 바꿀 때 리소스만 바꾸면 된다.

개발속도 + 메모리의 효율적인 사용
    (②과 같은 이유)