WinAPI

[WINAPI]컨트롤1(버튼, 체크박스)

FORHAPPy 2021. 12. 30. 15:47

컨트롤의 정의 : 사용자와의 인터페이스를 이루는 도구이다. 

즉, 사용자로부터 명령과 입력을 받아들이고 출력 결과를 보여준다는 뜻이다. 

 

컨트롤은 하나의 윈도우다. :  화면상의 일정한 영역을 차지하면 자신의 고유 메시지를 처리할 수 있는 능력을 가지고 있다. 그렇다고 해서 메모장이나 탐색기 같은 진짜 윈도우처럼 타이틀 바나 경계선을 가지고 독립적으로 사용되는 것은 아니며 보통 대화상자의 차일드 윈도우로 존재한다. (반드시 부모윈도우의 차일드 윈도우로 존재해야함)

 

보통 윈도우를 만들때는 WNDCLASS형 구조체를 정의 하고 RegisterClass 함수로 등록을 한 후 CreateWindow 함수를 호출한다.

 

그러나 컨트롤은 윈도우즈가 운영체제 차원에서 제공하기 떄문에 윈도우 클래스를 등록할 필요없이 미리 등록되어있는 윈도우 클래스를 사용하기만 하면 된다. 

미리정의된 윈도우 클래스에는 다음과 같은 종류가 있다.

 

윈도우 클래스 컨트롤
Button 버튼, 체크, 라디오
Static 텍스트
Scrollbar 스크롤바
edit 에디트
listbox 리스트박스
combobox 콤보박스

이 윈도우 클래스들은 시스템 부팅시에 운영체제에 의해 등록되므로 윈도우 클래스를 따로 등록할 필요없이 CreateWindow 함수의 첫번째 인수로 클래스 이름만 주면 해당 컨트롤을 만들 수 있다. 

 


<버튼 생성>

 

메인 윈도우 프로시져에서 윈도우 생성시 같이 생성 되도록 (WM_CREATE에서 해당함수 실행) 만들어 주었다. (보통이렇게 한다.)

CreateWindow(TEXT("button"), TEXT("Click Me"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20, 20, 100, 25, hWnd, (HMENU)0, g_hInst, NULL);

 

  1. 첫번째 인자에다가 TEXT("button") 해당 이름(위의 컨트롤 클래스에 해당) 을 넣어주면 그에 맞는 컨트롤이 생성된다. (대소문자 구분안함)
  2. 두번째 인자는 캡션(보여질 텍스트를)을 나타낸다. TEXT("Click Me") 윈도우 타이틀바에 나타날 윈도우의 제목이되 버튼위에 캡션이 나타날 위치가 달라진다.  보통 윈도우 라면 타이틀바에 캡션이 나타나지만 버튼은 버튼위에 캡션이 나타난다. 캡션이 필요없는 경우에는 NULL을 지정해주면 된다. 여기서는 Click Me라는 캡션을 준것이다. 
  3. 세번째 인자는 스타일 (속성값) (여기서는 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON)이다.  컨트롤은 차일드 윈도우이므로 예외없이 무조건 WS_CHILD를 주어야 한다.  WS_VISIBLE 역시 예외없이 주어야 한다.(showWindow를 호출하지 않아도 컨트롤이 화면에 나타나야 하기 때문)  그 외에는 컨트롤에 따른 고유한 스타일을 추가로 지정한다. 버튼의 스타일 값은 BS_접두어로 시작된다. 
스타일 설명
BS_PUSHBUTTON 푸시버튼
BS_DEFPUSHBUTTON 디폴트 푸쉬버튼
BS_CHECKBOX 체크박스
BS_3STATE 3가지 상태를 가지는 체크박스
BS_AUTOCHECKBOX 자동체크박스
BS_AUTO3STATE 3가지 상태를 가지는 자동체크박스
BS_RADIOBUTTON 라디오버튼
BS_AUTORADIOBUTTON 자동라디오버튼
BS_GROUPBOX 그룹박스

4. left, top, 폭, 높이 이다. lft top은 부모윈도우 기준이다.

5. 8번째 인자는 부모 윈도우 이다. 컨트롤은 차일드이므로 무조건 부모윈도우가 있어야 한다. 예제에서는 메인 윈도우의 핸들인 hWnd를 적어줌으로써 부모윈도우를 지정했다. 메인윈도우를 생성할때는 부모윈도우를 NULL로 하는데 이는 데스크탑을 부모로 한다는 뜻이다. WM_Create에서 생성되는 컨트롤의 부모는 통상 이 메시지를 처리하고 있는 부모인 hWnd가 된다. 

6. ID이다. 윈도우에서 사용할 메뉴의 핸들이다. 

**차일드 컨트롤에서는 메뉴가 없으므로 컨트롤 ID지정 용도로 사용된다. 컨트롤이 많다면 DEFINE을 지정해서 사용한다. (인수가 메뉴를 지정하므로 (HMENU)로 캐스팅 해야한다.

 

-->이 함수에서는 반환값으로 컨트롤의 핸들을 반환하지만 필요할 경우에는 따로 보관하여 쓰거나 필요없으면 그냥 무시하면 된다. 

 


<버튼이 눌렀을시 처리하기>

 

컨트롤에서 어떤 이벤트가 발생 했을 경우 부모윈도우로 통지메시지를 보내 어떤 사건이 발생했는지를 알린다. 그리고 부모윈도우는 차일드컨트롤이 보낸 통지메시지를 적절히 처리한다. 

버튼을 클릭할 경우 WM_COMMAND 메시지를 부모윈도우에게 보낸다. 

 

전달되는 정보는 다음과 같다. 

인수 설명
HIWORD 통지코드
LOWORD 컨트롤의 ID
IParam 메시지를 보낸 차일드 윈도우의 핸들

 

통지코드의 경우 차일드 컨트롤이 왜 메시지를 보냈는 가를 나타내는 값이다. 버튼의 경우 사용자가 자신을 클릭했다는 의미의 BN_CLICKED이므로 이값은 특별히 검사할 필요가 없지만 통지코드가 여러개인 컨트롤은 이값을 검사해보아야한다.

 

부모윈도우는 WM_COMMAND에서 LOWORD(wParam)값을 조사하여 어떤 컨트롤이 눌려졌는지에 따라 적절한 처리를 한다. 이 예제의 경우 각각다른 메시지 박스만 출력하였다. 

 


WM_COMMAND메시지는 사용자로부터 명령이 될만한 것들을 모두 처리한다. 

일반적인 처리루틴은 이렇다.

 

case WM_COMMAND:
   switch(LOWORD(wParam)
   {
   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;
        
        break;

<체크박스>

 

푸쉬버튼은 사용자로부터 명령을 받아들이기 위함

체크박스는 참과 거짓의 진위적인 선택을 입력받을때 주로 사용

클래스 이름은 버튼이다.

 

자동체크박스 수동체크박스
대화상자가 닫힐때 적용
직접 토글 하지 않아서 편리하다.
체크박스의 상태가 변경될 때마다 어떤 처리를 해야하고 체크조건이 복잡한 경우 사용 직접 토글해야함
(음소거를 누르는 즉시 적용시켜야 할 경우 사용)

 

SendMessage함수는

Api에서 특정 윈도우의 핸들에 있는 메시지를 전달하는 데 사용된다. 함수 원형은

LRESULT SendMessage(HWND hwnd, UNIT Msg, WPARAM wParam, LPARAM lParam);

첫번 째 인수, 메시지를 전달 받을 윈도우 핸들

두번 째 인수, 전달할 메시지 내용을 

세번 째, 네번 째 인수, 메시지의 추가 정보(메시지에 따라 다르다.)

통지메시지 : 컨트롤은 자신에게 어떤 변화가 있을 때 마다 부모윈도우로 메시지를 보낸다.

체크박스의 경우 사용자가 마우스로 클릭할때마다 부모윈도우로 BN_CLICKED 메시지를 보낸다. 

 

반대로 부모윈도우가 체크박스의 현재 상태를 알기 위해 차일드 윈도우로 메시지를 보낸다.

 

차일드윈도우로 보내는 메시지 종류는 다음과 같다.

메시지 설명
BM_GETCHECKED 체크박스가 현재 체크되어있는지 상태를 조사
반환값으로 체크상태를 돌려준다.
BM_SETCHECK 체크박스의 체크상태를 변경하며 wParam에 변경할 체크상태를 지정한다.

 

 

체크박스 상태는 3가지가 있다. 

상수 의미
BST_UNCHECKED 0 현재 체크되어있지 않다.
BST_CHECKED 1 현재 체크되어있다.
BST_INDETERMINATE 2 체크도 아니고 안체크로 아닌 상태

정리

 

일반버튼 - 체크상태를 조사할 필요가 없어서 lParam으로 들어오는 컨트롤 ID만 알면 된다.

체크박스 - BN_CLICKED (button notify)  메시지가 들어 왔을 경우 체크상태인지 아닌지를 조사해야 하기 떄문에 wParam으로 BST_GETCHECKED를 사용하여 조사해야함 (이건 자동 체크박스가 아닌 수동체크박스를 말한다.)