컴퓨터/Win32-API
이전에는 간단한 푸시버튼에 대해서만 다뤘습니다.
하지만 체크 버튼과 토글 버튼 또한 사용빈도가 높고 다양한 형태의 프로그래밍을 할 때 필요한 요소입니다.
본문에서는 체크버튼과 토글 버튼을 직접 구현해 보도록 합시다.
우선 체크 버튼과 토글 버튼이 무엇인지부터 알아보도록 합시다.
사실 기능은 똑같은 녀석이라고 봐도 무방합니다. 버튼의 상태를 체크의 형태로 표시할 것이냐, 눌림의 상태로 표시할 것이냐입니다.
간단하게 예시를 들어 확인해 보도록 합시다.
여기서 중요한 점은 두 버튼 모두 버튼이 2가지의 상태를 가지고 있다는 것입니다.
선택이 됐다 또는 선택이 되지 않았다.
이 부분에 유의해서 직접 구현해 보도록 합시다.
체크 버튼을 구현하기 위해서 버튼을 생성하는 과정에서 체크박스의 스타일을 정의해 주면 됩니다.
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를 발생하기 때문에 해당 영역에서 처리를 해주어야 합니다.
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;
}
사실 체크 버튼과 토글 버튼은 똑같은 개념입니다. 다만, 체크 버튼에 이미지를 사용할 수 있도록 설정해 주면 됩니다.
따라서 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);
}
기존 푸시버튼에 이미지를 씌우는 방법과 동일하게 이미지를 씌우도록 합시다.
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;
}
WindowsAPI - 실습 - 그림판 구현하기 2 ( 프로젝트 구조 설계 및 시작) (0) | 2022.04.14 |
---|---|
WindowsAPI - 실습 - 그림판 구현하기 1 (개요) (0) | 2022.04.13 |
Win32_API - 아이콘 버튼 (버튼에 이미지를 설정하기) (0) | 2022.04.08 |
Win32_API - GDI로 자유곡선 그리기3 (비트맵을 저장해서 쓰자) (0) | 2022.04.01 |
Win32_API_GDI로 자유곡선 그리기2(지우기/지우개 기능 추가) (0) | 2022.03.30 |
91년생 공학엔지니어의 개발일지
TODAY :
YESTER DAY :
TOTAL :
Commnet