Win32_API - 색상표 만들기(스크롤 바 추가하기)

컴퓨터/Win32-API

728x90
반응형

 

서론

색상표에 스크롤 바를 추가해서 조금 더 효율적으로 색상을 변경을 해보도록 합시다.

 

  • 기존 버전
 

Win32_API - 실습 - 색상표 만들기

서론 지금까지 배운 포스트들을 정리하면서 간단하게 RGB 개념을 적용해 3가지 인풋 박스에 R G B 순으로 숫자를 입력하고 색상을 표여주는 프로그램을 만들어 보도록 합시다. 전체 프로젝트 파일

blog-of-gon.tistory.com

  • 추가할 내용
 

Win32_API - 막대바 컨트롤(Scroll Bar)

서론 다양한 응용프로그램에서 Scroll Bar의 사용빈도는 매우 높습니다. 본문에서는 Scroll Bar를 Win32를 통해 만드는 방법과 정보에 대해서 알아보고, 간단한 실습 코드를 작성해 보겠습니다. 0. 사전

blog-of-gon.tistory.com

  • GitHub으로 소스코드 보기
 

GitHub - Gon-91/Win32API-Lean

Contribute to Gon-91/Win32API-Lean development by creating an account on GitHub.

github.com

1. 스크롤바 생성 및 범위 지정

우선 스크롤바를 제어하기 쉽도록 전역 변수를 만들어 주겠습니다.

HWND hscrollR, hscrollG, hscrollB;

이후 WM_CREATE: 알림 시점에서 스크롤바를 생성하고 범위를 지정해 주도록 합시다.

    case WM_CREATE:

        heditR = CreateWindowW(L"edit", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_NUMBER, 30, 40, 50, 25, hWnd, (HMENU)1, hInst, NULL);
        heditG = CreateWindowW(L"edit", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_NUMBER, 30, 70, 50, 25, hWnd, (HMENU)2, hInst, NULL);
        heditB = CreateWindowW(L"edit", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_NUMBER, 30, 100, 50, 25, hWnd, (HMENU)3, hInst, NULL);
        
        hscrollR = CreateWindowW(L"scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, 200, 410, 300, 20, hWnd, (HMENU)11, hInst, NULL);
        SetScrollRange(hscrollR, SB_CTL, 0, 255, TRUE);
        hscrollG = CreateWindowW(L"scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, 200, 450, 300, 20, hWnd, (HMENU)12, hInst, NULL);
        SetScrollRange(hscrollG, SB_CTL, 0, 255, TRUE);
        hscrollB = CreateWindowW(L"scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, 200, 490, 300, 20, hWnd, (HMENU)13, hInst, NULL);
        SetScrollRange(hscrollB, SB_CTL, 0, 255, TRUE);
        
        break;

 

2. 스크롤바 제어하기

WM_HSCROLL 알림에서 각각의 스크롤에 대한 제어를 해보도록 합시다.

    case WM_HSCROLL:
        int temppos;

        if ((HWND)lParam == hscrollR) temppos = R;
        if ((HWND)lParam == hscrollG) temppos = G;
        if ((HWND)lParam == hscrollB) temppos = B;
        
        switch (LOWORD(wParam))
        {
        case SB_LINELEFT:
            temppos = max(0, temppos - 1);
            break;
        case SB_PAGELEFT:
            temppos = max(0, temppos - 5);
            break;
        case SB_LINERIGHT:
            temppos = min(255, temppos + 1);
            break;
        case SB_PAGERIGHT:
            temppos = min(255, temppos + 5);
            break;
        case SB_THUMBTRACK:
            temppos = HIWORD(wParam);
            break;
        }

        if ((HWND)lParam == hscrollR) {
            SetScrollPos(hscrollR, SB_CTL, temppos, TRUE);
            R = temppos;
        }

        if ((HWND)lParam == hscrollG) {
            SetScrollPos(hscrollG, SB_CTL, temppos, TRUE);
            G = temppos;
        }
        if ((HWND)lParam == hscrollB) {
            SetScrollPos(hscrollB, SB_CTL, temppos, TRUE);
            B = temppos;
        }

        InvalidateRect(hWnd, NULL, TRUE);
        UpdateWindow(hWnd);
        break;

여기서 특이한 점은 lparam으로 윈도의 핸들 값을 전달하기 때문에 위와 같은 소스코드로 작성하게 됩니다.

 

동작 완료 확인 및 전체 소스코드

이제 스크롤 바를 이용하여 조금 더 쉽게 색삭표 제어가 가능해졌습니다.

전체 소스코드는 아래와 같습니다.


#include <windows.h>

#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include "resource.h"


HINSTANCE hInst;
HWND heditR, heditG, heditB;
HWND hscrollR, hscrollG, hscrollB;
int R, G, B;

// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
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 = MAKEINTRESOURCE(IDR_MENU1);
    wcex.lpszClassName = L"ColorTable";
    wcex.hIconSm = NULL;
    RegisterClassExW(&wcex);
    //적용한 윈도우 생성 및 업데이트
    hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
    HWND hWnd = CreateWindowW(L"ColorTable", L"ColorTable", 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)
{
    HDC hdc;
    WCHAR editword[10];
    switch (message)
    {
    case WM_CREATE:

        heditR = CreateWindowW(L"edit", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_NUMBER, 30, 40, 50, 25, hWnd, (HMENU)1, hInst, NULL);
        heditG = CreateWindowW(L"edit", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_NUMBER, 30, 70, 50, 25, hWnd, (HMENU)2, hInst, NULL);
        heditB = CreateWindowW(L"edit", NULL, WS_BORDER | WS_CHILD | WS_VISIBLE | ES_RIGHT | ES_NUMBER, 30, 100, 50, 25, hWnd, (HMENU)3, hInst, NULL);
        
        hscrollR = CreateWindowW(L"scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, 200, 410, 300, 20, hWnd, (HMENU)11, hInst, NULL);
        SetScrollRange(hscrollR, SB_CTL, 0, 255, TRUE);
        hscrollG = CreateWindowW(L"scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, 200, 450, 300, 20, hWnd, (HMENU)12, hInst, NULL);
        SetScrollRange(hscrollG, SB_CTL, 0, 255, TRUE);
        hscrollB = CreateWindowW(L"scrollbar", NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ, 200, 490, 300, 20, hWnd, (HMENU)13, hInst, NULL);
        SetScrollRange(hscrollB, SB_CTL, 0, 255, TRUE);
        
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            hdc = BeginPaint(hWnd, &ps);

            //RGB 표시를 하기 위한 텍스트
            TextOutW(hdc, 10, 45, L"R", 1);
            TextOutW(hdc, 10, 75, L"G", 1);
            TextOutW(hdc, 10, 105, L"B", 1);

            //적용된 값 표시를 하기 위한 텍스트
            wsprintf(editword, L"R : %d", R);
            TextOutW(hdc, 100, 45, editword, lstrlenW(editword));
            wsprintf(editword, L"G : %d", G);
            TextOutW(hdc, 100, 75, editword, lstrlenW(editword));
            wsprintf(editword, L"B : %d", B);
            TextOutW(hdc, 100, 105, editword, lstrlenW(editword));

            //색 칠하기
            HBRUSH newBrush = CreateSolidBrush(RGB(R, G, B));
            HBRUSH OldBrush = (HBRUSH)SelectObject(hdc, newBrush);
            Rectangle(hdc, 200, 50, 500, 400);
            SelectObject(hdc,OldBrush);
            DeleteObject(newBrush);
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_COMMAND:

        switch (HIWORD(wParam))
        {
        case EN_CHANGE:

            //R 처리
            if (LOWORD(wParam) == 1) {

                int num = 0;
                if (GetWindowTextW(heditR, editword, GetWindowTextLengthW(heditR) + 1) != NULL) {
                    num = _wtoi(editword);
                }

                if (0 <= num && num <= 255) {
                    R = num;
                }
                else {
                    MessageBox(hWnd, L"0 ~ 255의 숫자만 입력할 수 있습니다.", L"경고", NULL);
                }
                InvalidateRect(hWnd, NULL, TRUE);
            }

            //G 처리
            if (LOWORD(wParam) == 2) {
                GetWindowTextW(heditG, editword, GetWindowTextLengthW(heditG) + 1);
                int num = _wtoi(editword);

                if (0 <= num && num <= 255) {
                    G = num;
                }
                else {
                    MessageBox(hWnd, L"0 ~ 255의 숫자만 입력할 수 있습니다.", L"경고", NULL);
                }
                InvalidateRect(hWnd, NULL, TRUE);
            }

            //B 처리
            if (LOWORD(wParam) == 3) {
                GetWindowTextW(heditB, editword, GetWindowTextLengthW(heditB) + 1);
                int num = _wtoi(editword);

                if (0 <= num && num <= 255) {
                    B = num;
                }
                else {
                    MessageBox(hWnd, L"0 ~ 255의 숫자만 입력할 수 있습니다.", L"경고", NULL);
                }
                InvalidateRect(hWnd, NULL, TRUE);
            }

            break;
        }
        break;
    case WM_HSCROLL:
        int temppos;

        if ((HWND)lParam == hscrollR) temppos = R;
        if ((HWND)lParam == hscrollG) temppos = G;
        if ((HWND)lParam == hscrollB) temppos = B;
        
        switch (LOWORD(wParam))
        {
        case SB_LINELEFT:
            temppos = max(0, temppos - 1);
            break;
        case SB_PAGELEFT:
            temppos = max(0, temppos - 5);
            break;
        case SB_LINERIGHT:
            temppos = min(255, temppos + 1);
            break;
        case SB_PAGERIGHT:
            temppos = min(255, temppos + 5);
            break;
        case SB_THUMBTRACK:
            temppos = HIWORD(wParam);
            break;
        }

        if ((HWND)lParam == hscrollR) {
            SetScrollPos(hscrollR, SB_CTL, temppos, TRUE);
            R = temppos;
        }

        if ((HWND)lParam == hscrollG) {
            SetScrollPos(hscrollG, SB_CTL, temppos, TRUE);
            G = temppos;
        }
        if ((HWND)lParam == hscrollB) {
            SetScrollPos(hscrollB, SB_CTL, temppos, TRUE);
            B = temppos;
        }

        InvalidateRect(hWnd, NULL, TRUE);
        UpdateWindow(hWnd);
        break;
    
    case WM_SETTEXT:
        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 :