Win32_API - 아이콘 버튼 (버튼에 이미지를 설정하기)

컴퓨터/Win32-API

728x90
반응형

 

서론

Windows 응용 프로그래밍 과정에서 대표적인 컨트롤 중 하나인 버튼을 기본적인 양식대로 만들면 기능은 구현할 수 있으나 시각적으로는 부적합한 경우가 상당히 많습니다.

본문에서는 버튼 컨트롤을 마치 아이콘의 형태처럼 이미지를 씌우는 방법에 대해서 알아보고 사용해보도록 합시다.

결과 화면

버튼을 생성하는 과정이 이해가 안 되면 아래 글을 참조해주세요

 

 

Win32_API - 버튼 만들기

서론 수많은 Windows 프로그램들의 Window를 보면 다양한 기능들을 제공하는 버튼들을 많이 보았을 것입니다. 첨부된 그림처럼 Window 프로그램에는 프로그램을 제어할 수 있는 다양한 기능이 존재합

blog-of-gon.tistory.com

 

우선 이미를 준비합시다.

당연히 버튼에 사용할 이미지를 준비해야 됩니다. 이미지를 준비하고 리소스 파일에 추가해주도록 합시다.

본문에서는 그냥 실습을 위해 기본 양식을 사용합니다. 응용하시려면 Import를 이용해서 추가해 주세요.

새로 생성한 리소스를 보면 다음과 같습니다.

//Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Mywin32.rc
//
#define IDI_ICON1                       101

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        106
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

 

버튼 컨트롤 생성하기

이제 본격적으로 버튼 컨트롤을 만들고 이미지를 씌우는 과정을 거치도록 하겠습니다.

우선 버튼 컨트롤을 만들어 보도록 합시다.

    case WM_CREATE:
    {
        //버튼 생성
        HWND hButton = CreateWindowW(
            L"button",
            L"buttion1",
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON, //만약 비트맵으로 한다면 BS_BITMAP
            20, 20, 50, 50,
            hWnd,
            NULL,
            hInst,
            NULL);
        break;
    }

이때 스타일에서 BS_ICON 또는 BS_BITMAP으로 이 버튼 컨트롤은 어떤 형태로 사용할지 표시해 주어야 합니다.

 

이미지 설정해주기 기본지식 - BM_SETIMAGE

이제 생성된 버튼에 이미지를 씌어주어야 합니다. 

이미지를 설정하기 위해서는 BM_SETIMAGE 메세지에서 처리가 되어야 하므로 해당 메시지를 호출해 주어야 합니다.

 

BM_SETIMAGE 메시지를 보내려면 SendMessage 함수를 이용할 수 있습니다. 

  • SendMessage의 인자 살펴보기
SendMessageW(hWnd,Msg,wParam,lParam)
  • hWnd - 메시지를 보낼 윈도우 핸들 값
  • Msg - 메세지 값
  • wParam 값
  • lParam 값

 

  • BM_SETIMAGE 알아보기

BM_SETIMAGE의 경우도 메시지의 형태이기 때문에 wparam과 lparam값을 취할 수 있습니다.(자세히 보기)

  • wParam - 이미지의 타입의 설정 값 , 비트맵 or 아이콘을 정의해 줍니다.
    • IMAGE_BITMAP or IMAGE_ICON
  • lParam - 실제 이미지의 핸들 값 (버튼에 씌어줄 이미지 값)

위의 내용을 정리하면 SendMessage에는 다음과 같이 호출되어야 할 것입니다.

SendMessageW(버튼의 핸들 값 , BM_SETIMAGE, 이미지 타입 , 이미지 핸들 값);

 

  • 이미지 핸들 값

결국 SendMessage의 호출을 하기 위한 인자를 하나 빼고 다 확인이 되었습니다.

        SendMessageW(hButton, BM_SETIMAGE, IMAGE_ICON, 이미지의 핸들 값??);

이제 이미지의 핸들 값 즉 리소스로부터 이미지의 데이터를 소스코드위에 올려야 됩니다.

본문에서는 아이콘으로 처리를 했으니 아이콘을 핸들 값을 리소스로 부터 불러오도록 합시다.

        //이미지 로딩
        HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
        //HBITMAP hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(비트맵 값)); 비트맵으로 사용할 때

이때 LoadIcon 함수를 호출해서 리소스 상의 아이콘 데이터의 핸들 값을 받아옵니다.

 

 

이후 최종적으로 SendMessage를 호출해 주겠습니다.

        //BM_SETIMAGE로 버튼에 이미지 씌우기
        SendMessageW(hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
        //SendMessageW(hButton, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hBitmap);

 

전체 소스코드 보기

이미지를 씌우는 과정에 대해서 부분적으로 알아야 할 내용들이 많지만 결과 소스 코드는 간략하게 확인이 가능합니다.

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

// 전역 변수:
HINSTANCE hInst;                                // 현재 인스턴스입니다.

// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:

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:
    {
        //버튼 생성
        HWND hButton = CreateWindowW(
            L"button",
            L"buttion1",
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_ICON, //만약 비트맵으로 한다면 BS_BITMAP
            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_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 :