Win32_API - GDI로 선그리기1

컴퓨터/Win32-API

728x90
반응형

서론

GDI에서는 다양한 방법으로 선 및 곡석을 그릴 수 있도록 지원해 주고 있습니다.

본문에서는 가장 기본적인 선 그리기를 위한 방법에 대해서 알아보고 사용해 보도록 합시다.

대표적으로 사용되는 MoveToEx와 LineTo 함수를 사용하여 그려보고 동작원리에 대해서 알아보도록 합시다.

 

우선 그러 봅시다.

앞서 말한 것과 같이 MoveToEx함수와 LineTo 함수를 통하여 선을 그릴 수 있습니다. 

기본적으로 WM_PAINT에서 같이 작성하면 선이 그려지는 것을 볼 수 있습니다.

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            MoveToEx(hdc, 50, 50, NULL);
            LineTo(hdc, 100, 50);
            EndPaint(hWnd, &ps);
        }
        break;

 

 

어떻게 그려지는 것인가?

GDI를 통해서 그리기 위해서는 DC를 가지고 오게 됩니다. 이 DC는 그리기 도구이며, 사용자가 적용하는 윈도에 그리기 도구를 불러오는 것입니다. 

이후 MoveToEx함수를 통해서 그리기 도구의 그리기 시작점의 위치를 설정해 줍니다.

그다음 LineTo함수를 통해서 시작점부터 목표지점까지의 Line(선)을 그려주게 됩니다. 

이런 순서를 통해서 예제와 같은 직선을 그릴 수 있게 됩니다.

 

MoveToEx함수

해당 함수의 원형을 먼저 살펴보겠습니다.

BOOL MoveToEx(
  [in]  HDC     hdc,	//DC 핸들 값
  [in]  int     x,		//x 좌표	
  [in]  int     y,		//y 좌표
  [out] LPPOINT lppt	//옵션
);

옵션 값은 이전에 있던 위치를 반환해 주기 위한 값이지만, 본문에서는 NULL로 사용하지 않겠습니다.

 

DC와 x, y의 값을 받아 위치를 설정해 주는 함수입니다.

정상적으로 작동되지 않는다면 0을 반환합니다.

 

LineTo함수

해당 함수의 원형을 먼저 살펴보겠습니다.

BOOL LineTo(
  [in] HDC hdc,
  [in] int x,
  [in] int y
);

실질적으로 선을 그려주는 함수로 MoveToEx함수로부터 설정된 시작점부터 LineTo 함수로부터 설정된 종료점까지의 선을 그려주게 됩니다.

이 함수 또한 정상적으로 작동되지 않는다면 0을 반환합니다.

 

응용해보기 - 변수 대입

만약 시작점부터 가로로 100픽셀 만큼의 선을 그리고 싶다.

또는 시작점부터 세로로 200픽셀 만큼의 선을 그리고 싶다면 어떻게 해야 될까요?

간단하게 변수로 좌표를 지정하여 사용할 수 있습니다.

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            int x, y;
            x = 50;
            y = 50;

            MoveToEx(hdc, x, y, NULL);
            LineTo(hdc, x, y+200);
            MoveToEx(hdc, x, y, NULL);
            LineTo(hdc, x+100, y);
            EndPaint(hWnd, &ps);
        }
        break;

 

응용해보기 - 선의 색

선을 그리는 것 또한 Pen을 이용하여 다양한 색상을 사용할 수도 있습니다.

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            int x, y;
            x = 50;
            y = 50;

            MoveToEx(hdc, x, y, NULL);
            LineTo(hdc, x, y+200);

            HPEN NewPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
            HPEN OldPen = (HPEN)SelectObject(hdc, NewPen);
            MoveToEx(hdc, x, y, NULL);
            LineTo(hdc, x+100, y);

            SelectObject(hdc, OldPen);
            DeleteObject(NewPen);
            EndPaint(hWnd, &ps);
        }

소스코드 전체 보기

// Windows 헤더 파일
#include <windows.h>
// C 런타임 헤더 파일입니다.
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.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:

        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            int x, y;
            x = 50;
            y = 50;

            MoveToEx(hdc, x, y, NULL);
            LineTo(hdc, x, y+200);

            HPEN NewPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
            HPEN OldPen = (HPEN)SelectObject(hdc, NewPen);
            MoveToEx(hdc, x, y, NULL);
            LineTo(hdc, x+100, y);

            SelectObject(hdc, OldPen);
            DeleteObject(NewPen);
            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 :