Win32_API - 체크버튼과 토글버튼 구현하기

컴퓨터/Win32-API

728x90
반응형

서론

이전에는 간단한 푸시버튼에 대해서만 다뤘습니다. 

하지만 체크 버튼과 토글 버튼 또한 사용빈도가 높고 다양한 형태의 프로그래밍을 할 때 필요한 요소입니다.

본문에서는 체크버튼과 토글 버튼을 직접 구현해 보도록 합시다.

 

 

체크 버튼과 토글 버튼

우선 체크 버튼과 토글 버튼이 무엇인지부터 알아보도록 합시다. 

사실 기능은 똑같은 녀석이라고 봐도 무방합니다. 버튼의 상태를 체크의 형태로 표시할 것이냐, 눌림의 상태로 표시할 것이냐입니다.

간단하게 예시를 들어 확인해 보도록 합시다.

체크버튼
토글 버튼

여기서 중요한 점은 두 버튼 모두 버튼이 2가지의 상태를 가지고 있다는 것입니다.

선택이 됐다 또는 선택이 되지 않았다.

이 부분에 유의해서 직접 구현해 보도록 합시다.

 

체크 버튼 구현하기 1 - BS_CHECKBOX 스타일

체크 버튼을 구현하기 위해서 버튼을 생성하는 과정에서 체크박스의 스타일을 정의해 주면 됩니다.

    case WM_CREATE:
    {
        //버튼 생성
        hButton = CreateWindowW(
            L"button",
            L"buttion1",
            WS_CHILD | WS_VISIBLE | BS_CHECKBOX , //체크 버튼 스타일로 설정!
            20, 20, 50, 50,
            hWnd,
            NULL,
            hInst,
            NULL);
    }

위와 같은 소스코드를 작성하고 빌드를 한다면 체크 버튼이 생성이 됩니다. 하지만 정상적으로 동작하지 않습니다.

해당 버튼을 클릭했을 때 체크상태를 확인하면서 상태를 계속 변경해 주어야 합니다.

 

이 버튼 컨트롤 또한 클릭을 하는 과정에서 WM_COMMAND를 발생하기 때문에 해당 영역에서 처리를 해주어야 합니다.

 

체크 버튼 구현하기 2 - 버튼 상태 변경하기

SendMessagw 함수를 이용해서 두 가지 메시지를 통해 버튼의 상태를 조절할 수 있습니다.

자세한 메세지 컨트롤 방법은 링크의 MSDN을 확인해 보도록 하세요

 

내용처럼 버튼에 메세지를 보내주면 다음과 같이 작성할 수 있습니다.

    case WM_COMMAND:
    {
        //만약 체크가 안되어있다면 체크활성화
        if (SendMessageW(hButton, BM_GETCHECK, 0, 0) == BST_UNCHECKED) {
            SendMessageW(hButton, BM_SETCHECK, BST_CHECKED, 0);
        }

        //체크되어있다면 체크 비활성화
        else {
            SendMessageW(hButton, BM_SETCHECK, BST_UNCHECKED, 0);
        }
        break;
    }

 

토클 버튼 구현하기 1 - 버튼 스타일 설정 (BS_PUSHLIKE | BS_ICON)

사실 체크 버튼과 토글 버튼은 똑같은 개념입니다. 다만, 체크 버튼에 이미지를 사용할 수 있도록 설정해 주면 됩니다.

따라서 2개의 스타일 BS_PUSHLIKE | BS_ICON이 추가됩니다.

    case WM_CREATE:
    {
        //버튼 생성
        hButton = CreateWindowW(
            L"button",
            L"buttion1",
            WS_CHILD | WS_VISIBLE | BS_CHECKBOX | BS_PUSHLIKE | BS_ICON,  //토글 버튼을 사용하기 위해 스타일 추가
            20, 20, 50, 50,
            hWnd,
            NULL,
            hInst,
            NULL);
	}

 

토글 버튼 구현하기 2 - 버튼에 이미지 씌우기

기존 푸시버튼에 이미지를 씌우는 방법과 동일하게 이미지를 씌우도록 합시다.

    case WM_CREATE:
    {
        //버튼 생성
        hButton = CreateWindowW(
            L"button",
            L"buttion1",
            WS_CHILD | WS_VISIBLE | BS_CHECKBOX | BS_PUSHLIKE | BS_ICON,  //토글 버튼을 사용하기 위해 스타일 추가
            20, 20, 50, 50,
            hWnd,
            NULL,
            hInst,
            NULL);

        //이미지 로딩
        HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
        //HBITMAP hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(비트맵 값));
        //BM_SETIMAGE로 버튼에 이미지 씌우기
        SendMessageW(hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
        //SendMessageW(hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hBitmap);

        break;
    }

토글 버튼 구현하기 마지막 그리고 전체 소스코드

토글 버튼 또한 상태를 계속해서 확인해주는 과정이 필요합니다. 이 과정은 체크 버튼과 동일하기 때문에 전체 소스코드를 보여드리며 본문을 마무리하도록 하겠습니다.

// Windows 헤더 파일
#include <windows.h>
// C 런타임 헤더 파일입니다.
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include "resource.h"

// 전역 변수:
HINSTANCE hInst;                                // 현재 인스턴스입니다.
HWND hButton;
// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:

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


int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{

    //윈도우 창 구조체 정의 및 적용
    WNDCLASSEXW wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = NULL;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"Test";
    wcex.hIconSm = NULL;
    RegisterClassExW(&wcex);

    //적용한 윈도우 생성 및 업데이트
    hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
    HWND hWnd = CreateWindowW(L"Test", L"Test", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    if (!hWnd)
    {
        return FALSE;
    }
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    MSG msg;

    // 기본 메시지 루프입니다:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
    {
        //버튼 생성
        hButton = CreateWindowW(
            L"button",
            L"buttion1",
            WS_CHILD | WS_VISIBLE | BS_CHECKBOX | BS_PUSHLIKE | BS_ICON,  //토글 버튼을 사용하기 위해 스타일 추가
            20, 20, 50, 50,
            hWnd,
            NULL,
            hInst,
            NULL);

        //이미지 로딩
        HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
        //HBITMAP hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(비트맵 값));
        //BM_SETIMAGE로 버튼에 이미지 씌우기
        SendMessageW(hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
        //SendMessageW(hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hBitmap);

        break;
    }
    case WM_COMMAND:
    {
        //만약 체크가 안되어있다면 체크활성화
        if (SendMessageW(hButton, BM_GETCHECK, 0, 0) == BST_UNCHECKED) {
            SendMessageW(hButton, BM_SETCHECK, BST_CHECKED, 0);
        }

        //체크되어있다면 체크 비활성화
        else {
            SendMessageW(hButton, BM_SETCHECK, BST_UNCHECKED, 0);
        }
        break;
    }
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
728x90
반응형

Commnet

G91개발일지

Gon91(지구일)

91년생 공학엔지니어의 개발일지

TODAY :

YESTER DAY :

TOTAL :