블로그 이미지
하루, 글. 그림. 영상매체. 표현을 도와주는 기기들. 도전 중. 동화다아아
    동화다아아

    카테고리

    분류 전체보기 (176)
    잡담 (1)
    IT 기기-리뷰&뉴스 (7)
    리뷰 - 도서 (1)
    리뷰 - 영상 (0)
    리뷰 - 그림/음악 (1)
    내장형 하드웨어 (163)
    Total
    Today
    Yesterday

    - 에디트
     → 에디트는 문자열을 직접 입력받을 때 사용하는데 버튼과 마찬가지로 윈도우즈에서 가장 흔하게 볼 수 있는 컨트롤이다.
     → 키보드로 입력을 받는 가장 기본적인 입력도구이며 콘솔 환경의 gets, scanf 등의 함수를 대체한다.

     → "edit" 윈도우 클래스로부터 생성하며 다음과 같은 스타일을 사용할 수 있다. 이 스타일들은 Create 함수의 세번째 인수로 지정한다.

     스타일 설명 
     ES_AUTOSCROLL  수평 스크롤을 지원한다. 
     ES_AUTOVSCROLL  여러 줄 편집시 수직 스크롤을 지원한다.
     ES_LEFT  왼쪽 정렬한다.
     ES_CENTER  중앙 정렬한다.
     ES_RIGHT  오른쪽 정렬한다. 
     ES_LOWERCASE  소문자로 변환하여 표시한다.
     ES_UPPERCASE  대문자로 변환하여 표시한다. 
     ES_MULTILINE  여러 줄을 편집할 수 있도록 한다.
     ES_NOHIDESEL  포커스를 잃더라도 선택된 영역을 표시한다.
     ES_READONLY  읽기전용으로 만들어 편집을 금한다.

     → 배치하고 데이트에 입력된 문자열을 부모 윈도우의 타이틀 바에 출력하는 예제

    #include "MsgProc.h"
    #define ID_EDIT 100
    HWND hEdit;

    LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      hEdit = CreateWindow(TEXT("edit"), NULL, WS_CHILD|WS_VISIBLE|WS_BORDER|
        ES_AUTOHSCROLL, 101020025, hWnd, (HMENU)ID_EDIT, g_hInst, NULL);
      return 0;
    }
    LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      TCHAR str[128];
      switch(LOWORD(wParam))
      {
      case ID_EDIT:
        switch(HIWORD(wParam))
        {
        case EN_CHANGE:
          GetWindowText(hEdit, str, 128);
          SetWindowText(hWnd, str);
        }
      }
      return 0;
    }
    LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      return 0;
    }
    LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      HDC hdc;
      PAINTSTRUCT ps;

      hdc = BeginPaint(hWnd, &ps);
      EndPaint(hWnd, &ps);
      return 0;
    }
    LRESULT OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
    {
      PostQuitMessage(0);
      return 0;
    }

     → WM_CREATE에서 에디트를 생성하였으며 ES_AUTOHSCROLL 스타일을 주어 수평 스크롤이 가능하도록 하였다. 이 스타일을 주지 않으면 에디트의 오른쪽 끝까지만 문자열을 입력할 수도 있으나 이 스타일을 주면 에디트 끝부분에 닿았을 때 자동으로 수평 스크롤되어 자신의 폭보다도 긴 문자열도 입력할 수 있다.
     → 생성된 에디트 컨트롤의 윈도우 핸들값을 hEdit에 저장해 두었는데 이 핸들은 이후 에디트 컨트롤과 통신할 때 사용된다. WM_COMMAND에서 EN_CHANGE 통지 메시지가 전달될 때 에디트의 텍스트를 읽어 부모 윈도우의 타이틀 바로 출력하였다.

     → 에디트는 사용자가 자신을 편집할 때마다 부모 윈도우로 EN_CHANGE 메시지를 보내며 메인 윈도우는 이 메시지를 받을 때마다 에디트의 텍스트를 읽어 자신의 타이틀 바를 갱신한다. EN_CHANGE 통지 메시지 처리 코드에서 에디트에 입력된 텍스트를 읽을 때 GetWindowText 함수를 사용하였는데 보다시피 컨트롤도 윈도우의 일종이기 때문에 윈도우 관리 함수를 모두 사용할 수 있다.



    - 컨트롤도 윈도우다.
     → 컨트롤이 윈도우와 동격이라는 말은 초보자가 선뜻 이해하기 힘들지만 부명히 윈도우의 일종이 틀림없다.
     → 일단 화면상의 사각영역을 차지한다는 점에 있어서 윈도우와 같은데 메인 윈도우의 차일드로 존재하며 타이틀 바가 없기 때문에 사용자가 직접 이동시킬 수 없을 뿐이다. 또한 윈도우처럼 스타일을 가지며 만들 때 지정한 스타일에 따라 모양이나 기능이 달라진다.
     → 컨트롤이 윈도우라는 결정적인 증거는 스스로 메시지를 처리할 수 있는 능력을 가진다는 점이다.
     → 버튼은 마우스로 누르면 쑥 들어가는 모양으로 바뀌고 에디트는 키보드 입력을 받으면 문자열을 조립하여 보여준다.
     → 또한 WM_PAINT 메시지를 처리하기 때문에 스스로 자신을 복구(Repaint)할 수 있고 부모 윈도우가 메시지를 보내면 그 메시지를 처리한다.
     → 체크 박스는 BM_SETCHECK 메시지를 받으면 wParam 값에 따라 자신의 체크 상태를 스스로 변경한다.
     → 버튼이나 에디트를 만들 때 사용한 함수가 CreateWindow라는 점만 봐도 역시 컨트롤은 윈도우이다. CreateWindow 외에 윈도우에 적용할 수 있는 함수는 대부분 컨트롤에도 적용할 수 있다.

     →  예제

    #include "MsgProc.h"
    #define ID_EDIT 100
    HWND hEdit;
    int nTop = 10;
    BOOL bShow = TRUE;

    TCHAR *Mes = TEXT("왼쪽 클릭 : 에디트 이동, 오른쪽 클릭 : 보임/숨김");

    LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      hEdit = CreateWindow(TEXT("edit"), NULL, WS_CHILD|WS_VISIBLE|WS_BORDER|
        ES_AUTOHSCROLL, 10, nTop, 20025, hWnd, (HMENU)ID_EDIT, g_hInst, NULL);
      SetWindowText(hEdit, TEXT("에디트도 윈도우다"));
      return 0;
    }
    LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {

      return 0;
    }
    LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      HDC hdc;
      PAINTSTRUCT ps;

      nTop += 10;
      MoveWindow(hEdit, 10, nTop, 20025, TRUE);
      return 0;
    }
    LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      if(bShow)
      {
        bShow = FALSE;
        ShowWindow(hEdit, SW_HIDE);
      }
      else
      {
        bShow = TRUE;
        ShowWindow(hEdit, SW_SHOW);
      }
      return 0;
    }
    LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      HDC hdc;
      PAINTSTRUCT ps;

      hdc = BeginPaint(hWnd, &ps);
      TextOut(hdc, 200100, Mes, lstrlen(Mes));
      EndPaint(hWnd, &ps);
      return 0;
    }
    LRESULT OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
    {
      PostQuitMessage(0);
      return 0;
    }

     →  WM_CREATE 메시지에서 에디트를 하나 생성했는데 이때 사용한 함수는 CreateWindow이며 이 함수는 에디트 윈도우를 만든 후 윈도우 핸들을 리턴한다. 
     →  에디트를 만들자마자 SetWindowText 함수로 캡션을 변경하여 에디트에 문자열을 대입했다.
     →  마우르 왼쪽 버튼을 누르면 MoveWindow 함수로 에디트를 조금 아래로 이동시키며 오른쪽 버튼을 누르면 에디트를 숨기거나 보이게 한다.
     →  실행 결과


    - 리스트 박스
     →  선택가능한 여러 개의 항목들을 나열해 놓고 그 중 하나(또는 여러 개)를 선택하는 컨트롤이며 여기서 항목이란 주로 문자열
     →  에디트로 입력받으면 문자열 형태로 직접 타이프해야 하므로 번거롭고 오타를 입력할 가능성도 많은데 비해 문자열을 리스트 박스에 넣어두고 사용자가 선택하도록 하는 것은 훨씬 더 쉽고 정확하다.

     → 리스트 박스도 물론 일종의 윈도우이며 "listbox"ㄹ는 윈도우 클래스로 생성한다.
     →  차일드 컨트롤로 생성하는 것이 보통이므로 WS_CHILD와 WS_VISIBLE스타일은 기본적으로 지정해야 하며 이 외에는 여러가지 고유 스타일 중에서 지정할 수 있다.
     →  부모 윈도우로 통지 메시지를 보내는 것이 일반적이므로 LBS_NOTIFY 스타일은 거의 필수적으로 선택하는 것이 좋으며 그외 LBS_SORT나 LBS_MULTIPLESEL 스타일은 필요할 떄 선택한다.

     →  부모 윈도우가 리스트를 조작하고자 할 때는 리스트 박스 메시지를 사용한다.
     →  리스트 박스에 선택한 항목을 채울 때는 LB_ADDSTRING을 사용하며 현재 선택된 항목의 인덱스는 LB_GETCURSEL로 구하고 특정 인덱스의 문자열을 읽을 때는 LB_GETTEXT 메시지를 사용한다.
     →  이 메시지들은 부모 윈도우가 리스트 박스에게 명령을 내리기 위해 사용

     →  반대로 리스트 박스에서 어떤 사건이 발생하였을 때 부모 윈도우로 통지 메시지를 보낸다.
     →  가장 자주 사용되는 통지메시지는 메시지 선택이 변경될 때 모내지는 LBN_SELCHANGE이다. 
     →  부모 윈도우는 WM_COMMAND의 HIWORD(wParam)으로 전달된 통지 코드를 보고 리스트 박스에 무슨 사건이 발생했는지를 알게된다.

     →  예제
     →  리스트 박스에 문자열을 나열해 두고 선택시 이 항목을 읽어와 메인 윈도우의 타이틀 캡션을 변경하는 예제

    #include "MsgProc.h"

    #define ID_LISTBOX 100
    TCHAR *Items[] = {TEXT("Apple"), TEXT("Orange"), TEXT("Melon"), TEXT("Grape"), TEXT("Strawgberry")};
    HWND hList;
      int i;
    LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      hList = CreateWindow(TEXT("listbox"), NULL, WS_CHILD|WS_VISIBLE|WS_BORDER|
        LBS_NOTIFY, 1010100200, hWnd, (HMENU)ID_LISTBOX, g_hInst, NULL);
      for(i=0;5>i;++i)
      {
        SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)Items[i]);
      }
      return 0;
    }
    LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      TCHAR str[128];
      switch(LOWORD(wParam))
      {
      case ID_LISTBOX:
        i=SendMessage(hList, LB_GETCURSEL, 00);
        SendMessage(hList, LB_GETTEXT, i, (LPARAM)str);
        SetWindowText(hWnd, str);
        break;
      }
      return 0;
    }
    LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {

      return 0;
    }
    LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      return 0;
    }
    LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      HDC hdc;
      PAINTSTRUCT ps;
      hdc = BeginPaint(hWnd, &ps);
      
      EndPaint(hWnd, &ps);
      return 0;
    }
    LRESULT OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
    {
      PostQuitMessage(0);
      return 0;
    }

     → 전역변수로 Items 문자열 배열이 정의되어 있다.
     → WM_CREATE에서 리스트 박스를 생성하고 LB_ADDSTRING 메시지를 보내 항목 다섯 개를 추가하였다.

     → 위 상태에서 사용자가 리스트 박스의 항목을 선택하면 LBN_SELCHANGE 통지 메시지가 전달된다.
     → 이 때 LB_GETCURSEL 메시지로 현재 선택된 항목의 번호를 구한 후 LB_GETTEXT 메시지로 항목의 문자열을 str 버퍼에 읽는다.
     → SetWindowText 함수로 메인 윈도우의 타이틀 바에 출력을 확인한다.


    - 콤보 박스
     → 에디트 컨트롤과 리스트 박스를 결합해 놓은 컨트롤
     → 따라서 목록에 있는 항목중의 하나를 선택할 수도 있고 원하는 항목이 없을 경우 에디트에 직접 입력해 넣을 수도 있다.
     → 또한 리스트 박스는 항상 열려 있는데 비해 콤보 박스는 필요한 경우만 목록을 열어 선택하므로 화면 공간을 적게 차지한다는 장점도 있다.
     → 반면 항목을 선택하려면 일단 목록을 아래로 펼쳐야 하므로 리스트 박스보다 선택에 시간이 걸리며 (Two Touch) 선택 가능한 항목에 어떤 것들이 있는지 바로 확인할 수 없어 쓰기에는 조금 번거롭다는 단점도 있다.
     → "combobox" 윈도우 클래스를 사용한다.

    #include "MsgProc.h"

    #define ID_COMBOBOX 100
    TCHAR *Items[] = {TEXT("Apple"), TEXT("Orange"), TEXT("Melon"), TEXT("Grape"), TEXT("Strawgberry")};
    HWND hCombo;
    int i;
    LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      hCombo = CreateWindow(TEXT("combobox"), NULL, WS_CHILD|WS_VISIBLE|
        CBS_DROPDOWN, 1010100200, hWnd, (HMENU)ID_COMBOBOX, g_hInst, NULL);
      for(i=0;5>i;++i)
      {
        SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)Items[i]);
      }
      return 0;
    }
    LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      TCHAR str[128];
      switch(LOWORD(wParam))
      {
      case ID_COMBOBOX:
        i=SendMessage(hCombo, CB_GETCURSEL, 00);
        SendMessage(hCombo, CB_GETLBTEXT, i, (LPARAM)str);
        SetWindowText(hWnd, str);
        break;
      }
      return 0;
    }
    LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {

      return 0;
    }
    LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      return 0;
    }
    LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
    {
      HDC hdc;
      PAINTSTRUCT ps;
      hdc = BeginPaint(hWnd, &ps);
      
      EndPaint(hWnd, &ps);
      return 0;
    }
    LRESULT OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
    {
      PostQuitMessage(0);
      return 0;
    }

     →  WM_CREATE에서 드롭다운 스타일의 콤보 박스 하나를 생성하고 CB_ADDSTRING 메시지를 보내 다섯 개를 추가하였다.
     →  WM_COMMAND 가 처리하는 통지 메시지를 보면 LBN_SELCHANGE에 대응하는 CBN_SECHANGE와 EN_CHANGE에 대응하는 CBN_EDITCHANGe 메시지 뿐이다.
     →  두 메시지는 리스트 박스, 에디트의 메시지와 동일한 의미를 가지며 이 예제에서 처리하는 방식도 동일하다.

     →  목록에 있는 항목 중 하나를 선택할 수도 있고 목록에 없는 것도 위쪽의 에디트에 직접 입력해 넣을 수 있다.
     →  제시된 목록 중 하나를 반드시 선택해야 한다면 리스트 박스가 적합하며 자주 선택하는 몇 가지 항목을 제시하고 더 원하는 것은 직접 입력할 수 있도록 학 때는 콤보 박스가 어울린다.
     


     

    '내장형 하드웨어 > WINAPI' 카테고리의 다른 글

    WINAPI - 대화상자  (0) 2011.09.27
    WINAPI - 스크롤 바  (0) 2011.09.26
    WINAPI - Static  (1) 2011.09.22
    WINAPI - 라디오 버튼  (0) 2011.09.21
    WINAPI - 체크 박스  (0) 2011.09.20
    Posted by 동화다아아
    , |

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함