1. 컨트롤
  가. 컨트롤(control)이란 사용자와의 인터페이스를 이루는 도구 (사용자로부터 명령과 입력을 받아들이고
    출력 결과를 보여준다, 즉 입출력 도구)
  나. 프로그램은 실행중에 끊임없이 사용자와 통신을 하는데 컨트롤을 통해 명령과 정보를 받아들이고
    또한 컨트롤을 통해 실행 결과를 사용자에게 보고한다.
  다. 컨트롤도 하나의 윈도우이다. 화면상의 일정한 영역을 차지하며 자신의 고유 메시지를 처리할 수
    있는 능력을 가지고 있으며 차일드 윈도우로 존재한다. 윈도우를 만들 때는 WNDCLASS형의 구조체를
    정의하고 RegisterClass함수로 등록한 후 CreateWindow 함수를 호출한다. 그러나 컨트롤은 윈도우즈가
    운영체제 차원에서 제공하기 때문에 윈도우 클래스를 등록할 필요없이 미리 등록되어 있는 윈도우 클래스를
    사용하기만 하면 된다. 미리 정의된 윈도우 클래스에는 다음과 같은 종류가 있다
  라. 윈도우 클래스의 종류
    윈도우 클래스         |           컨트롤
    ----------------------------------
    button                   |    버튼, 체크, 라디오
    static                   |    텍스트
    scrollbar               |    스크롤바
    edit                      |    에디트
    listbox                   |    리스트 박스
    combobox             |    콤보 박스
  마. 윈도우 클래스들은 시스템 부팅시에 운영체제에 의해 등록되므로 윈도우 클래스를 따로 등록할 필요없이
    CreateWindow함수의 첫 번째 인수로 클래스 이름만 주면 해당 컨트롤을 만들수 있다.

2. button
  가. CreateWindow(TEXT("button"), TEXT("Click Me"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
    20, 20, 100, 25, hWnd, (HMENU)0, g_hInst, NULL);
  == CreateWindow(만들고자 하는 윈도우의 클래스, 캡션, 스타일,
    위치, x위치, y위치, 폭, 높이, 부모 윈도우, 핸들, 부모윈도우 인스턴스 핸들, 사용자정의데이터);
  나. 스타일
    스타일                                           설명
    ------------------------------------------------------------------------------
    BS_PUSHBUTTON                           푸시 버튼
    BS_DEFPUSHBUTTON                     디폴트 푸시 버튼
    BS_CHECKBOX                               체크 박스
    BS_3STATE                                   3가지 상태를 가지는 체크 박스
    BS_AUTOCHECKBOX                       자동 체크 박스
    BS_AUTO3STATE                           3가지 상태를 가지는 자동 체크 박스
    BS_RADIOBUTTON                           라디오 버튼
    BS_AUTORADIOBUTTON                   자동 라디오 버튼
    BS_GROUPBOX                             그룹 박스
  다. 부모와의 통신
    1) 버튼을 클릭할 경우 WM_COMMAND 메시지를 부모 윈도우에게 보내며 이때 전달되는 정보는
      인수                 설명
      --------------------------
      HIWORD(wParam)        통지코드(왜 메시지를 보냈는가를 나타내는 값)
      LOWORD(wParam)       컨트롤의 ID (아홉번째 인수)
      lParam                        메시지를 보낸 차일드 윈도우의 윈도우 핸들
    2) 부모 윈도우는 WM_COMMAND에서 LOWORD(wParam)값을 조사하여 어떤 컨트롤이 눌러졌는지에
      따라 적절한 처리를 한다. WM_COMMAND 메시지는 컨트롤의 통지 메시지뿐만 아니라 메뉴항목,
      엑셀러레이터 등의 명령을 처리하는 중요한 일을 한다. 이름 그대로 버튼을 누르거나, 메뉴를 선택하거나
      엑셀러레이터를 누르는 등 사용자로부터의 명령이 될 만한 것들을 모두 처리한다. 이때 컨트롤의 ID, 메뉴 ID
      엑셀러레이터 ID등은 모두 LOWORD(WPARAM)으로 전달되므로 이 세가지 명령들끼리는 0~65535까지의
      범위에서 상호 중복되지 않는 ID를 가져야한다.
      가) 일반적인 메세지 처리 루틴
        case WM_COMMAND:
          switch( LOWORD(wParam) )     // ID에 따른 분기
             case 메뉴 1: 처리 1; break;
             case 메뉴 2: 처리 2; break;
             case 엑셀러레이터 1: 처리 3; break;
             case 컨트롤 1:
               switch( HIWORD(wParam) )       // 통지 코드에 따른 분기
                 case 통지코드 1: 처리 1; break;
                 case 통지코드 2: 처리 2; break;

3. 체크 박스
  가. 푸시 버튼은 사용자로부터 명령을 받아들이기 위해 사용하는데 비해 체크 박스는 참, 거짓의 진위적인
    선택을 입력받을 때 주로 사용된다. 체크 박스도 푸시버튼과 마찬가지로 차일드 윈도우이며 스타일에
    따라 4가지 종류의 체크박스가 있다.  우선 선택 가능한 옵션의 개수에 따라 두가지 상태를 가지는
    체크박스와 세가지상태를 가지는 체크 박스로 구분된다. 또한 동작 방법에 따라 자동 체크 박스와
    수동 체크 박스로 나누어지는데 수동 체크 박스는 선택/비선택 상태를 부모 윈도우가 직접 바꾸어야
    하며 자동 체크 박스는 스스로 체크 상태를 바꾼다.자동 체크 박스는 별도의 코드를 작성하지 않아도
    체크 상태를 자동으로 토글할 수 있는 장점이 있기는 하지만 체크 상태를 결정하기 위해 좀 더 복잡한
    조건을 점검하기에는 어울리지 않는다.
  나. 컨트롤의 메시지
    1) 체크 박스는 사용자가 마우스로 클릭할 때마다 부모 윈도우로 BN_CLICKED 메시지를 보낸다. 컨트롤이
      부모 윈도우로 보내는 통지 메시지와는 달리 부모 윈도우가 체크 박스의 상태를 알아보거나 상태를
      바꾸고자 할 때도 차일드 윈도우로 메시지를 보낸다. 통지 메시지는 차일드가 부모로 보내는 보고 메시지이고
      그냥 메시지는 부모가 차일드에게 어떤 지시를 내리기 위해 보내는 명령이다. 메시지의 종류는 컨트롤마다
      다르다.
      메시지              설명
      -----------------------------------
      BM_GETCHECK   체크 박스가 현재 체크되어 있는 상태를 조사하며 wParam, lParam은 사용하지 않는다.
                               체크 상태는 리턴값으로 돌려진다.
      BM_SETCHECK  체크 박스의 체크 상태를 변경하며 wParam에 변경할 체크 상태를 지정한다.

      BM_GETCHECK에 의해 리턴되는 값, BM_SETCHECK에 의해 설정되는 체크박스의 상태
      상수                             값          의미
      BM_UNCHECKED           0           현재 체크되어 있지 않다.
      BM_CHECKED               0           현재 체크되어 않다.
      BM_INDETERMINATE      0          체크도 아니고 안 체크도 아닌 상태
                            <------ BN_CLICKED : 클릭되었음 -------------
      부모 윈도우       ------ BM_GETCHECK : 체크 상태 질문 ------->     체크 박스
                             ------ BM_SETCHECK : 체크 상태 변경 ------->

4. 라디오 버튼
  가. BS_RADIOBUTTON, BS_AUTORADIOBUTTON 둘 중 하나의 스타일을 지정하면 라디오 버튼이 되며
    체크 박스와 마찬가지로 수동, 자동의 두가지 종류가 있으며 라디오 버튼이 체크 상태를 스스로 변경
    하는 그렇지 않은가의 차이가 있다. 수동 라디오 버튼이 필요한 상황은 사실상 거의 없으며 대개의
    경우는 자동 라디오 버튼으로 충분하다. 하나의 선택 사항에 대해 여러 개의 라디오 버튼들이
    그룹을 이루어 사용된다는 특징이 있다. 같은 그룹에 속한 라디오 버튼은 오직 하나만 선택 가능
  나. 라디오 버튼의 그룹을 구성하는 방법은 간단하다. 그룹을 이루는 첫 번째 라디오 버튼에만 WS_GROUP
    스타일을 주고 나머지 라디오 버튼은 WS_GROUP 스타일을 주지 않으면 된다. 최초로 WS_GROUP을 가지는
    라디오 버튼부터 다음 WS_GROUP 스타일을 가지는 라디오 버튼 직전까지가 한 그룹이 된다.

5. 에디트
  가. EDIT 윈도우 클래스로부터 생성하며 CREATEWINDOW 함수로 스타일 인수로 지정하면 된다.
    부모 윈도우는 이 메시지를 받았을 때 적절한 처리를 하면 된다.EN_CHANGE 문자열이 변경되었다.
     EN_KILLFOCUS, EN_SETFOCUS 포커스를 잃고 얻었을 때의 메시지가 있다.
  나. 컨트롤도 윈도우와 동격이다. 일단 화면상의 사각영역을 차지한다는 점에 있어서 윈도우와 같은데
    메인 윈도우의 차일드로 존재하며 타이틀 바가 없기 때문에 사용자가 직접 이동시킬 수 없을 뿐이다.
    또한 윈도우처럼 스타일을 가지며 만들 때 지정한 스타일에 따라 모양이나 기능이 달라진다.
    컨트롤이 윈도우라느 결정적인 증거는 스스로 메시지를 처리할 수 있는 능력을 가진다는 점이다.
    버틍을 마우스로 누르면 쑥 들어가는 모양으로 바뀌고 에디트는 키보드 입력을 받으면 문자열을 조립하여
    보여준다. eH한 WM_PAINT 메시지를 처리하기 때문에 스스로 자신을 복구(REPAIR)할 수 있고 부모윈도우가
    메시지를 보내면 그 메시지를 처리한다. 체크 박스는 BM_SETCHECK 메시지를 받으면 WPARAM값에 따라
    자신의 체크 상태를 스스로 변경한다.

6. 리스트 박스
  가. 리스트 박스는 선택 가능한 여러 개의 항목들을 나열해 놓고 그 중 하나(또는 여러개)를 선택하는 컨트롤
    이며 여기서 항목이란 주로 문자열이다. 리스트 박스도 일종의 윈도우이며 "listbox"라는 윈도우 클래스로
    생성한다. 차일드 컨트롤로 생성하는 것이 보통이므로 WS_CHILD|WS_VISIBLE 스타일은 기본적으로 지정
    해야 하며 이 외에 다음과 같은 여러 가지 고유의 스타일을 지정할 수 있다. 어떤 스타일을 지정하는가에
    따라 리스트박스와 모양과 동작이 달라진다.
    스타일                      설명
    LBS_MULIPLESEL    여러개의 항목을 선택 가능, 적용하지 않으면 디폴트로 하나의 선택만 가능
    LBS_NOTIFY             사용자가 목록중 하나를 선택했을 때 부모 윈도우로 통지 메시지를 보낸다.
    LBS_SORT                추가된 항목들을 자동 정렬한다.
    LBS_OWNERDRAW     문자열이 아닌 비트맵이나 그림을 넣을 수 있다..
    LBS_STANDARD        LBS_NOTIFY|LBS_SORT|WS_BORDER
  나. 부모 윈도우로 통지 메시지를 보내는 것이 일반적이르모 LBS_NOTIFY 스타일은 거의 필수적으로 선택
    하는 것이 좋으며 그 외는 필요할 때 선택하면 된다. 부모 윈도우가 리스트 박스를 조작하고자 할때는
    리스트 박스 메시지를 사용한다.
    메시지                      설명
    LB_ADDSTRING         리스트 박스에 항목을 추가 LPARAM으로 추가하고자 하는 문자열의 번지를 넘겨줌
    LB_DELETESTRING    항목을 삭제, WPARAM으로 항목의 번호를 넘겨주면 남은 항목수를 리턴
    LB_GETCURSEL        현재 선택된 항목의 번호를 조사
    LB_GETTEXT            지정한 항목의 문자열을 읽는다. WPARAM에 항목번호, LPARAM에 문자열
    LB_GETCOUNT         항목의 개수를 조사한다.
    LB_SETCURSEL        WPARAM이 지정한 항목을 선택한다
   다. 리스트 박스에서 어떤 사건이 발생했을 때 부모 윈도우로 다음과 같은 통지 메시지를 보낸다.
    메시지                      설명
    LBN_DBLCLK            리스트 박스를 더블 클릭하였다.
    LBN_ERRSPACE       메모리가 부족하다
    LBN_KILLFOCUS       키보드 포커스를 잃었다.
    LBN_SELCANCEL     사용자가 선택을 취소하였다
    LBN_SELCHANGE     사용자에 의해 선택이 변경되었다.
    LBN_SETFOCUS        키보드 포커스를 얻었다.
    자주 사용되는 통지 메시지는 선택이 변경될 때 보내지는 LBN_SELCHANGE이다

7. 콤보 박스
  가. 에디트컨트롤과 리스트 박스를 결합이다. 그래서 목록에 있는 항목중의 하나를 선택할 수도 있고 원하는
    항목이 없을 경우 에디트에 직접 입력해 넣을 수도 있다. combobox 윈도우 클래스를 사용하며 세 가지
    종류가 있는데 스타일로 원하는 종류를 선택
    스타일                        설명
    CBS_SIMPLE              에디트와 리스트 박스를 가지되 리스트 박스가 항상 펼쳐져 있다.
    CBS_DROPDOWN         에디트와 리스트 박스를 가진다.
    CBS_DROPDOWNLIST    리스트 박스만 가지며 에디트에 항목을 입력할 수는 없다.

8. 스크롤 바
  가. 비교적 복잡한 컨트롤로 윈도우의 스크롤 상태를 고나리하기 위해 사용하기도 하며 일정 범위에 있는 값을
    대충 선택할 때도 사용한다. scrollbar 위노우 클래스로 생성하며 수평 스크롤 바일경우 SBS_HORZ 스타일을
    수직 스크롤 일때는 SBS_VERT 스타일을 지정한다.
    BOOL SetScrollRange(HWND hWnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw);
    (스크롤 바 윈도우 핸들, 표준 또는 별도 스크롤바를 지정하는 값, 최대값, 최소값, ?)
    int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw);
    (?, ?, 현재 위치, ?);
  나. 다른 컨트롤은 WM_COMMAND로 통지메시지를 보내는데 스크롤 바는 WM_HSCROLL, WM_VSCROLL
    이라는 별도의 메시지를 부모 윈도우로 보낸다.
    인수                              설명
    LOWORD(WPARAM)        스크롤 바 내의 어디를 눌렀는가?
    HIWORD(WPARAM)          현재 위치
    LPARAM                          스크롤 바의 윈도우 핸들
  다. LOWORD(WPARAM)으로 전달되는 값은 사용자의 스크로로 요구사항을 나타냄
    값                                                 설명
    SB_LINELEFT, SB_LINEUP               사용자가 왼쪽 화살표를 눌렀음
    SB_LINERIGHT, SB_LINEDOWN         사용자가 오른쪽 화살표를 눌렀음
    SB_PAGELEFT, SB_PAGEUP            사용자가 왼쪽 몸통을 눌렀음
    SB_PAGERIGHT, SB_PAGEDOWN      사용자가 오른쪽 몸통을 눌렀음
    SB_THUMBPOSITION                       스크롤 박스를 드래그한 후 마우스 버튼을 놓았다.
    SB_THUMBTRACK                           스크롤 박스를 드래그하고 있는 중 마우스버튼 놓을때까지 계속 전달

9. 스태틱
  가. 입력은 없고 오로지 문자열만 보여줌 WM_CREATE에서 스태틱 컨트롤을 만들기만 할 뿐 그외의 코드는
    작성할 필요가 없다. 스태틱 컨트롤은 실행중에 부모 윈도우로 통지 메시지를 보낼 필요가 없기 때문에 ID를
    -1로 지정하며 여러개의 스태틱 컨트롤이 있을 모든 경우도 -1의 같은 ID를 사용해도 된다. -1은 ID를 주지
    않는다는 뜻이며 더 이상 컨트롤을 프로그래밍할 필요가 없을 때 사용된다. 물론 필요하면 줄수도 있다.
  나. TextOut으로 출력한 문자열과는 달리 스태틱 컨트롤은 스스로 메시지를 처리할 수 있는 윈도우이기 때문에
    배치해 놓기만 하면 WM_PAINT와 같은 통지 메시지로 복구할 필요가 없다. 또한 색상, 글꼴 크기 등
    운영체제의 세팅이 바뀔 경우 이런 변화에 대해서도 스스로 대처한다는 장점이 있다.
1. GDI Object
  GDI 오브젝트는 GDI가 그래픽 출력을 위해 사용하는 도구임과 동시에 사용자가 GDI의 출력을 조장할 수
  이쓴 도구이기도 하다. 원하는 색상과 모양의 모브젝트를 만들고 DC에 선택해 놓으면 이후부터 선택된
  오브젝트의 속성대로 출력

2. GDI 오브젝트를 만들 때 핸들을 발급받으며 선택하거나 삭제할 때는 이 핸들만 가지고 GDI 오브젝트를
  사용 DC가 BeginPaint나 GetDC 함수에 의해 처음 만들어 졌을 때 디폴트로 선택된 GDI 오브젝트는
  아래와 같음
GDI 오브젝트     핸들타입     설명                                디폴트
펜                    HPEN         선을 그을 때 사용              검정색의 가는 실선
브러시              HBRUSH     면을 채울때 사용               흰색
폰트                 HFONT       문자 출력에 사용되는 글꼴   시스템 글꼴
비트맵              HBITMAP    비트맵 이미지                   선택되지 않음
팔레트              HPALLETTE팔레트                              선택되지 않음
리전                 HRGN          화면상의 영역                  선택되지 않음

3. Stock Object
  가. 윈도우가 기본적으로 제공하는 GDI 오브젝트
  나. 운영체제가 부팅할 때부터 미리 만들어 놓아 일부러 만들지 않아도 언제든지 사용가능 하며
    사용한 후 파괴할 필요도 없음
    1) HGDIOBJ GetStockObject(int fnObject);  주로 브러시와 펜이 스톡 오브젝트로 제공됨
      함수는 여러 종류의 스톡 오브젝트를 리턴하므로 대입하기 전에 원하는 타입으로 캐스팅
    2) HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj); 이전에 쓰던 오브젝트를 리턴

4. 색상
  RGB 매크로 함수를 사용하여 색상값을 만듬
  typedef DWORD COLORREF;
  #define RGB(r, g, b)
                    ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b)<<16)))

5. PEN
  가. 기본 스톡 펜은 흰색, 검정색, 투명색 세 가지 뿐이며 원색 펜은 직접 만들어서 사용
    HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor);
    (선의 모양, 선의 폭, 선의 색상) 펜의 핸들을 리턴 리턴후에는 반드시 파괴
    BOOL DeleteObject(HGDIOBJ hObject);   GDI 오브젝트를 삭제할 때 사용

6. BRUSH
  가. 기본 스톡 브러시는 단색 브러시가 있음, 만드는 건 PEN과 동일
    HBRUSH CreateSolidBrush(COLORREF crColor);  단색의 브러시 제작
    HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref); 무늬와 색상을 지정할수 있음

7. Old의 의미
  가. GDI 오브젝트를 생성하고 파괴하지 않으면 안됨
  나. GDI 오브젝트를 저장하는 리소스 영역은 메인 메모리와는 다른 특수한 영역으로 이 영역의 크기가
    그리 크지 못해 오브젝트를 많이 만들면 금방 가득차 버림
  다. DC에 선택되어 있는 오브젝트는 삭제할 수 없기 때문에 Old라는 GDI 오브젝트를 사용하여
    사용중인 오브젝트를 Old라는 오브젝트로 교체후 삭제함
  라. 코드의 범용성을 위해서는 항상 Old 오브젝트를 사용하여 DC를 원래대로 돌려놓는 습관을
    가지는 것이 좋음

8. 투명 오브젝트
 스톡 오브젝트에는 투명색의 오브젝트가 존재함

9. 그리기 모드
  가. 윈도우즈에서 사용하는 디폴트 그리기 모드는 R2_COPYPEN 모드라서 그려지는 그림이
    기존 그림을 덮어버림
    1) int SetROP2(HDC hdc, int fnDrawMode);
        int GetROP2(HDC hdc);
  나. 마우스를 따라 선을 이동시킬 때 이미 그려진 그림을 보존해야 하므로 그리는 중의 선을 반점 모드로
    그려 이 선이 지워질 때 원래대로 복구해 놓고 가야하는 것이다. 그러기 위해서느 절대 색상으로 삭제,
    그리기 해서는 안되면 이미 그려진 그림과 논리 연산을 취하는 다른 방법을 사용해야 한다. R2_NOT는
    이런 작업이 가능한 그리기 모드의 한 예인데 흑백 환경에서는 이 모드가 가장 편리하며 컬러 환경에는
    R2_NOTXORPEN이 가장 완벽함

10. BITMAP
    비트맵은 대용량이라 직접 출력하는 함수는 제공하지 않으며 약간의 준비를 거친 후 출력해야 한다.
    이렇게 준비 동작을 취한 후 출력하면 여러번 출력할 때 이미 준비된 데이터를 전송하기만 하면
    출력 속도도 빠르고 예비동작을 미리 취해 놓을 수 있다는 점에서도 유리하다. 비트맵은 화면으로
    직접 출력할 수 없으며 반드시 메모리 DC에 미리 준비해 놓고 사용해야 한다
  가. 메모리 DC란 화면 DC와 동일한 특성을 가지며 그 내부에 출력 표면을 가진 메모리 영역이다.
    메모리에 있기는 하지만 화면 DC에서 사용할 수 있는 모든 출력을 메모리 DC 에서도 할 수 있다.
  나. HDC CreateCompatibleDC(HDC hdc);
    화면 DC의 핸들을 주면 화면 DC와 동일한 특성을 가지는 DC를 메모리에 만들어 핸들을 리턴
  다. HBITMAP LoadBitmap(HINSTANCE hInstance, LPCTSTR lpBitmapName);
    (비트맵 리소스를 가진 인스턴스의 핸들, 비트맵 리소스의 이름)
  라. BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc,
    int nXSrc, int nYSrc, DWORD dwRop);
    (복사 대상 DC, X좌표, Y좌표, 폭, 높이, 복사원 DC, 복사원X좌표, 복사원 Y좌표, 래스터 연산방법)
  마. BOOL StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
    HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, DWORD dwRop);
    확대, 축소가 가능
 
11. FONT
  HFONT CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight,
    DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet,
    DWORD FdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality,
    DWORD fdwPitchAndFamily, LPCTSTR lpszFace);
  (폰트의 높이, 폰트의 폭, 폰트의 각도, 개별문자 기울기, 폰트의 두께, 폰트 속성, 문자셋,
  출력 정확도, 클리핑 정확도, 논리적 폰트를 물리적 폰트와 얼마나 근접시킬 것인가 지정,
  폰트의 피치와 그룹을 설정, 글꼴의 이름)
  가. LOGFONT 구조체를 사용하여 폰트를 정의하고 CreateFontIndirect 함수로 폰트를 만드는 방법
    LOGFONT 구조체는 CreateFont 함수의 인수 전체를 멤버로 가지는 구조체로 LOGFONT에
    원하는 값을 먼저 대입한 후 CreateFontIndirect 함수로 이 구조체의 번지를 넘기면 됨
    HFONT CreateFontIndirect(CONST LOGFONT * lplf);
  나. 텍스트의 색상
    COLORREF SetTextColor(HDC hdc, COLORREF crColor); 글자 색상
    COLORREF SetBkColor(HDC hdc, COLORREF crColor); 글자 배경색상
    int SetBkMode(HDC hdc, int iBkMode); 글자배경색상 모드(투명, 불투명) 기본은 불투명
1. 윈도우즈 환경에서 리소스를 만드는 과정과 코딩과정이 분리되면 얻는 장점
  가. 분담 작업으로 전문성을 높임, 개발과 디자인을 동시에 수행함으로써 전체적인 개발 기간 단축효과
  나. 재사용에 유리
  다. 모듈 분할 컴파일 방식의 장점과 같이 매번 컴파일할 필요가 없음
  라. 실행중에 교체가 가능한 모듈임

2. 리소스 편집기들은 리소스 ID에 겹따옴표없이 IDR_MENU1 식으로 이름을 지정하면 이 이름을
  resource.h에 정수형의 매크로로 정의하고 사용되지 않은 정수를 배정한다. 정수 타입의 리소스 ID를
  문자열 포인터에 대입할 수 없으므로 적당히 캐스팅해야 하는데 이 캐스팅을 대신하는  매크로가
  MAKEINTRESOURCE 이다
  ( #define MAKEINTRESOURCE(i)    (LPSTR)((DWORD)((WORD)(i))) )

3. WM_COMMAND
  가. 메뉴 항목을 선택하면 WM_COMMAND 메시지가 발생
  나. 어떤 메뉴 항목이 선택되었는가는 WPARAM의 하위 워드로 전달되므로 LOWORD(WPARAM)을 읽어
    판단
  다. WndProc에서는 WM_COMMAND 메시지를 받을 경우 switch 문으로 다시 LOWORD(WPARAM)의
    값에 따라 분기를 하여 각 메뉴 항목에 따른 처리를 수행

4. Accelerator
  가. 설정 기능을 곧바로 실행하는 키보드 조합키
  나. HACCEL LoadAccelerators(HINSTANCE hInstance, LPCTSTR lpTableName);
    리소스로부터 엑셀러레이터 테이블을 읽어들이며 그 핸들을 리턴
  다. int TranslateAccelerator(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg);
    키보드 메시지를 WM_COMMAND 메시지로 변경하여 액셀러레이터가 동작할 수 있도록 함

5. 문자열 테이블
  가. 대량의 문자열을 사용하는 프로그램은 리소스에 문자열을 정의해 놓고 필요할 때마다
    리소스의 문자열을 읽어와 사용(최대 4K까지의 길이를 가질 수 있음)
  나. int LoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax);
    hInstance가 정의하고 있는 uID 문자열을 길이 nBuffexMax의 lpBuffer 문자 배열로 읽어오라는 뜻)
  다. 장점
    1) 문자열 자체가 코드와 분리됨으로써 문자열만 따로 관리할 수 있으며 프로젝ㅌ를 유지하는데 도움
    2) 많은 문자열을 다루는 대형 프로젝트에는 메시지만을 전문적으로 관리하는 사람이 따로 있어
      문체의 일관성 확보와 메시지의 내용을 정확하게 할 수 있으며 수정하기도 편리
    3) 다국어 버전을 쉽게 만들 수 있으며 문자열을 고쳐도 소스를 다시 컴파일 할 필요가 없어
      개발 속도가 빨라진다.
1. 키보드로 입력이 발생되면 윈도우는 WM_CHAR, WM_KEYDOWN 메시지 발생
  입력된 문자의 코드는 WPARAM으로 전달되며 LPARAM에는 비트별로 복잡한 정보가 전달
  필요한 정보가 있으면 LPARAM을 참조하고 필요없으면 WPARAM만 사용하면 된다

2. 무효영역
  InvalidateRect 함수를 호출하여 강제로 WM_PAINT 메시지를 발생할 수 있다.
  BOOL InvalidateRect(HWND hWnd, CONST RECT * lpRect, BOOL bErase);

3. 문자를 입력하고자 할 경우는 WM_CHAR 메시지를 사용하고
  문자 이외의 키는 입력 받을 수 없다. 이럴때는 WM_KEYDOWN 메시지를 사용 한다.

4. 키보드를 입력하게 되면 Getmessage는 메시지 큐에서 메시지를 꺼낸 후 메시지를 TranslateMessage
  함수로 넘긴다. TranslateMessage 함수는 전달된 메시지가 WM_KEYDOWN 인지와 눌러진 키가
  문자키인지 검사해 보고 조건이 맞을 경우 WM_CHAR 메시지를 추가로 발생시킨다.

5. 마우스 입력
  가. 마우스 메시지는 LPARAM의 상위 워드에 마우스 버튼이 눌러진 Y좌표, 하위 워드에 X좌표를 가지며
    좌표값을 검출해 내기 위해 HIWORD, LOWORD 등의 매크로 함수를 사용한다. 즉 마우스 메시지가
    발생한 위치의 좌표는 (LOWORD(LPARAM), HIWORD(LPARAM))이 된다.
    좌표값을 음수가 발생할 수도 있다. 모니터가 2개이상일 시
  나. WPARAM에는 마우스 버튼의 상태와 키보드 조합 키(SHIFT, CTRL)의 상태가 전달된다.
  * 상, 하위 워드 추출, WORD로 부터 상, 하위 바이트 추출, 조립 매크로 들이 존재한다.
    (LOWORD, HIWORD, LOBYTE, HIBYTE <- 추출, MAKEWORD(A,B), MAKELONG(A,B) <- 조립)
  다. 더블클릭
    1) 더블클릭을 사용할시는 더블클릭 메시지를 받고자하면 윈도우 클래스의 스타일에 원한다는
      의사표시를 해야한다.
        WndClass.style = CS_HREDRAW|CS_VREDRAW|CS_DBLCKS;
    2) 디폴트로 지원하지 않고 플래그를 지정하도록 되어 있는 이유는 더블클릭을 검출하는데는
      그만큼 실행시간의 감소가 요구되며 어떤 프로그램은 더블클릭보다 WM_LBUTTONDOWN을 두 번
      받기를 원할 수도 있기 때문이다. 가령 트리플 클릭을 검출하고 싶은데 더블클릭이 디폴토로 지원
      하게 되면 트리플 클릭이전에 운영체제에 의해 더블클릭이 처리되어 버리기 때문이다.

6. 타이머
  가. 한 번 지정해 놓기만 하면 일정한 시간 간격을 두고 연속적으로 계속 발생한다.
    Uint SetTimer(HWND hWnd, UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
    BOOL KillTimer(HWND hWnd, UINT uIDEvent);
  나. LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    강제로 메시지가 발생한 것처럼 만들어야 할 때 사용
  다. WndProc에서 첫 번째로 처리하는 메시지는 WM_CREATE 메시지이다.
  라. 두 개의 타이머
    SetTimer 함수의 두번째 인수로 지정한 값(타이머 ID)를 다르게 줌으로 가능하며
    (타이머 ID가 다른 2개의 타이머 함수 호출) 어떤 타이머로 부터 메시지가 발생하면
    WPARAM으로 타이머 ID가 전달된다.
  마. 콜백함수
    1) SetTimer의 네 번째 인수는 타이머 프로시저 함수의 포인터를 가리킨다. NULL일시는 첫 번째 인수로
      지정된 hWnd로 WM_TIMER 메시지가 전달되지만 이 인수에 타이머 함수가 지정되었을 경우는
      매 시간마다 이 함수가 대신 호출된다.
      VOID CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
    2) 콜백함수를 사용하는 것과 WM_TIMER 메시지를 받는 것은 사실상 거의 동일한 기법이라고
      할 수 있으며 상황에 따라 편리한 방법을 사용하면 된다. 차이점이라면 WM_TIMER 메시지는 다른
      메시지가 있을 경우 실행 순서에 밀려 늦게 호출되는 경우가 있지만 콜백함수를 사용하면
      정확한 시간에 호출된다는 점이다.; 그래서 정확도를 요하는 작업은 타이머 메시지보다는 콜백함수를
      사용하는 것이 더 좋다고 되어 있다.
  바. 일회용 타이머
    타이머를 원하는 곳에 SetTimer함수를 사용한뒤 WM_TIMER 부분에 KillTimer을 호출하면 됨

7. 윈도우 관리 메시지
  가. 작업영역의 좌표를 조사 BOOL GetClientRect(HWND hWnd, LPRECT lpRect);
  나. 윈도우의 크기가 변경될 때마다 윈도우로 부터 WM_SIZE 메시지가 전달됨
    LPARAM의 하위워드는 변경된 후의 윈도우 폭이 상위 워드에는 높이가 전달되며
    WPARAM에는 이 메시지가 발생한 이유를 나타내는 플래그가 전달됨
  다. 윈도우의 위치가 변경될 때마다 WM_MOVE 메시지가 발생됨
    LPARAM의 하위워드는 새로운 X좌표, 상위워드는 새로운 Y좌표

#include <Windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass = TEXT("Class");

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdparam, int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst = hInstance;
 
 WndClass.cbClsExtra = 0;
 WndClass.cbWndExtra = 0;
 WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 WndClass.hInstance = hInstance;
 WndClass.lpfnWndProc = WndProc;
 WndClass.lpszClassName = lpszClass;
 WndClass.lpszMenuName = NULL;
 WndClass.style = CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);
 
 hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  NULL, (HMENU)NULL, hInstance, NULL);
 ShowWindow(hWnd, nCmdShow);
 
 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)
{
 HDC hdc;
 PAINTSTRUCT ps;

 switch( iMessage )
 {
 case WM_CREATE:
  {
   hWndMain = hWnd;

   return 0;
  }
 case WM_PAINT:
  {
   hdc = BeginPaint(hWnd, &ps);
   EndPaint(hWnd, &ps);

   return 0;
  }
 case WM_DESTROY:
  {
   PostQuitMessage(0);
   
   return 0;
  }
 }
 
 return (DefWindowProc(hWnd, iMessage, wParam, lParam));
}

유니코드는 16비트의 단일한 값으로 지구상의 모든 문자를 표현할 수 있는 문자 코드 체계

C 타입           |        유니코드 타입
---------------------------------
char              |        TCHAR
char *            |        LPSTR
const char *   |        LPCTSRT

TCHAR는 C의 기본 타입 중 하나인 char과 일단 같지만 유니코드로 컴파일할 때는 wchar_t타입이 됨
wchar_t는 실제로 unsigned short로 정의되어 있으며 부호없는 16비트 정수형

TCHAR 타입의 실제 정의문은 다음과 같이 조건부 컴파일문으로 작성되어 있다.
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif

문자가 필요할시는 TCHAR로 문자열이 필요할 때는 LPSTR 또는 TCHAR *를 쓰는 것이 현명함

문자열처리 함수들도 C의 표준 함수를 쓰지 말고 가급적 유니코드를 인식하는 함수를 사용할 것

C 표준함수          |            유니코드 지원 함수
------------------------------------------
strlen                  |            lstrlen
strcpy                 |            lstrcpy
strcat                  |            lstrcat
strcmp                 |           lstrcmp
sprintf                  |           wsprintf

문자열 상수도 타입이 있으므로 겹 따옴표안에 바로 문자열 상수를 쓰지 말고
TEXT 매크로로 둘러싸는 것이 좋다.
TEXT 매크로는 유니코드 설정에 따라 문자열 상수의 타입을 변경한다.

cb           Count of Bytes          바이트 수
dw          double word             부호없는 long형 정수
h             handle                     윈도우, 비트맵, 파일 등의 핸들
sz           NullTerminated          Null 종료 문자열
ch          Characte                  문자형
a            Array                       배열
w           Word                        부호없는 정수형
i             integer                     정수형
p, lp       long pointer               포인터형
b            Boole                      논리형



BYTE             unsigned char
CHAR            char
WORD            unsigned short
DWORD          unsigned long
LONG            long
BOOL            int

1. DC란 출력에 필요한 모든 정보를 가지는 데이터 구조체이며 GDI 모듈에 의해 관리된다.
  문자열을 지정하는 폰트, 선의 색상과 굵기, 채움 무늬와 색상, 그리기 모드 등등이
  모두 출력에 필요한 정보들이다.

2. Uncover시 OS는 프로그램에게 WM_PAINT 메시지를 전송하므로
  모든 그래픽 출력은 WM_PAINT 메시지에서 처리해야만 한다

3. DC를 얻는 방법
  가. 일반적으로 DC를 얻는 방법
    HDC GetDC(HWND hWnd);
    int ReleaseDC(HWND hWnd, HDC hdc);
  나. WM_PAINT 메시지 처리루틴에서 사용할 수 있는 방법
    PAINTSTRUCT ps;
    HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint);
    BOOL EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint);
    PAINTSTRUCT 구조체에는 그리기 속도를 비약적으로 향상시킬 수 있는 정보들이 들어 있다

4. 문자열의 출력
  가. BOOL TextOut(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString);
  나. UINT SetTextAlign(HDC hdc, UINT fMode);
  다. int DrawText(HDC hdc, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat);

5. 여러 가지 출력
  가. COLORREF SetPixel(hdc, nXPos, nYpos, clrref);
  나. DWORD MoveToEx(hdc, x, y, lpPoint);
  다. BOOL LineTo(hdc, xEnd, yEnd);
  라. BOOL Rectangle(hdc, nLeftRect, nTopRectm nRightRect, nBottomRect);
  마. BOOL Ellipse(hdc, nLeftRect, nTopRect, nRightRect, nBootmRect);

6. 메시지 박스
  가. int MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCation, UINT uType);

7. 메시지 비프
  가. BOOL MessageBeep(UINT uType);

+ Recent posts