관리 메뉴

ㄴrㅎnㅂrㄹrㄱi

[강좌 10] 그래픽1 본문

API 관련/API 강좌모음

[강좌 10] 그래픽1

님투 2007. 10. 26. 03:40
반응형

[API]강좌(10)<--그래픽1





오늘부터는 그래픽 부분에 대한 강좌를 시작하겠습니다. 오늘은 점, 선, 박스를
윈도우의 작업영역에 어떻게 그릴수 있는지 부터 알아 보겠습니다. 예제는 총
세개입니다.
먼저 점을 찍는 방법부터 알아 봅시다. 아주 간단합니다. 점 찍는 함수가 있거든요.
그 함수 하나만 알면 됩니다.
COLORREF SetPixel(HDC hDC, int nX, int nY, COLORREF crColor);
디바이스 컨텍스트 핸들, 찍힐 좌표, 그리고 점의 색깔을 파라미터로 요구한다는 것
을 쉽게 짐작할수 있겠네요. 자 그러면 예제를 보도록 합시다. 아래 예제는 마우스
가 클릭된 좌표에 검정색 점을 찍는 예제입니다.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Graphic Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
static int nX, nY;
switch(message)
{
case WM_LBUTTONDOWN :
nX = LOWORD(lParam);
nY = HIWORD(lParam);
hDC = GetDC(hWnd);
SetPixel(hDC, nX, nY, RGB(0, 0, 0));
ReleaseDC(hWnd, hDC);
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
마우스가 클릭되었을때 처리하는 부분을 보도록 합시다.
case WM_LBUTTONDOWN :
nX = LOWORD(lParam);
nY = HIWORD(lParam);
hDC = GetDC(hWnd);
SetPixel(hDC, nX, nY, RGB(0, 0, 0));
ReleaseDC(hWnd, hDC);
return 0;
뭐 설명드릴 껀덕지가 없군요. 이번에는 선을 긋는 방법을 알아 봅시다. 여러분들이
어떤 종이에 선을 긋는다면 어떤 것들이 필요하겠습니까? 먼저 펜이 필요하겠죠? 윈
도우의 작업영역에 선을 그릴때도 펜이 필요합니다.
HPEN CreatePen(int fnPenStyle, int nWidth, COLORREF crColor);
위 함수를 이용해서 펜을 생성할수 있습니다. 리턴된 핸들을 SelectObject()라는 함
수를 이용해서 디바이스 컨텍스트 핸들로 선택해주면 그 펜을 사용하게 되는거죠.
선택된 펜을 이용해서 작업을 다 했다면 펜 핸들을 반환해주어야 합니다. 디바이스
컨텍스트 핸들을 이용해서 작업을 한후 반환하는것과 같은 이치죠.
BOOL DeleteObject(HGDIOBJ hgdiObj);
위 함수를 이용해서 반환해주면 됩니다. CreatePen() 함수의 파라미터에 대해 알아
봅시다. 첫번째 파라미터는 펜의 속성을 지정하는 것입니다. 물론 지정된 예약어를
지정해줌으로써 펜을 선택할수 있는 것입니다. 그 예약어와 의미는 다음과 같습니
다.
PS_DASH 점선을 의미합니다.
PS_DASHDOT 점선과 점의 혼합된 선을 의미합니다.
PS_DASHDOTDOT 점선과 점 두개 단위로 혼합된 선을 의미합니다.
PS_SOLID 실선을 의미합니다.
직접 위 예약어들을 지정하고 테스트 해보면 어떤것을 의미하는지 알게 될 겁니다.
두번째 파라미터는 선의 두께를 의미하고 세번째 파라미터는 선의 색깔을 의미합
니다.
펜을 선택하는 방법을 알았으니 이제 그 다음에 어떤 작업이 필요한지 알아 봅시다.
그려질 선의 시작 좌표가 필요하겠네요. 시작 좌표는 현재 좌표를 이동하는 함수를
이용해서 지정하면 됩니다. 실제로 선을 긋는 함수의 파라미터는 목적 좌표만을 지
정하도록 되어 있거든요. 현재 좌표를 이동하고자 하려면 아래 함수를 사용하면 됩
니다.
BOOL MoveToEx(HDC hDC, int nX, int nY, LPPOINT lpPt);
첫번째, 두번째, 세번째 파라미터가 어떤 역할을 하는지 짐작이 가죠? 좌표를 지정
하는 것입니다. 그런데 마직막 파라미터는 어떤 역할을 할까요? 아마 앞부분에서 이
POINT 구조체에 대해 설명을 드린적이 있었을 겁니다. 이것은 새로운 좌표로 이동
했을때 이동되기전의 좌표를 저장하는 역할을 하는 것입니다.
자 그러면 실제로 선을 긋는 함수에 대해 알아 봅시다.
BOOL LineTo(HDC hDC, int nX, int nY);
파라미터로 그려질 선의 목적 좌표를 지정해 주면 됩니다.
자 그러면 이 함수를 이용해서 만든 예제를 보도록 합시다. 아래 예제는 마우스로
클릭한 상태에서 드래그했을때 점선으로 선이 보여지다가 마우스의 왼쪽 버튼을
놓았을때 실선으로 선을 긋는 예제입니다. 여러분들이 사용하고 있는 그래픽 툴들
이 대부분 이런식으로 선을 그을수 있을 겁니다.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Graphic Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCTps;
HPEN hPen;
static BOOL bMouse;
static int nStartX, nStartY, nEndX, nEndY;
static POINT pt;
switch(message)
{
case WM_LBUTTONDOWN :
bMouse = TRUE;
nStartX = LOWORD(lParam);
nStartY = HIWORD(lParam);
return 0;
case WM_LBUTTONUP :
bMouse = FALSE;
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
return 0;
case WM_MOUSEMOVE :
if(bMouse)
{
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
}
return 0;
case WM_PAINT :
if(bMouse)
hPen = CreatePen(PS_DASHDOT, 0, RGB(0, 0, 0));
else
hPen = CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
hDC = BeginPaint(hWnd, &ps);
SelectObject(hDC, hPen);
MoveToEx(hDC, nStartX, nStartY, &pt);
LineTo(hDC, nEndX, nEndY);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
자 그러면 위 소스를 보도록 합시다.
case WM_LBUTTONDOWN :
bMouse = TRUE;
nStartX = LOWORD(lParam);
nStartY = HIWORD(lParam);
return 0;
먼저 마우스의 왼쪽 버튼이 눌리면 버튼이 눌렸다는 신호를 TRUE로 세팅하고 그 좌
표를 기억하고 있군요.
case WM_LBUTTONUP :
bMouse = FALSE;
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
return 0;
마우스의 왼쪽 버튼이 놓여지면 왼쪽 버튼이 눌린 상태가 아니라는 것을 알리기 위
해서 FALSE로 세팅하고 마지막 좌표값을 기억시키는 구문입니다. 그리고 마지막에
InvalidateRect()라는 함수를 사용하였는데 이 함수는 윈도우를 다시 그린다는것
을 의미하는 것입니다. 윈도우가 그려질때 WM_PAINT라는 메시지가 발생되니 위
함수 때문에 WM_PAINT 메시지 처리 부분이 실행되겠죠?
case WM_PAINT :
if(bMouse)
hPen = CreatePen(PS_DASHDOT, 0, RGB(0, 0, 0));
else
hPen = CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
hDC = BeginPaint(hWnd, &ps);
SelectObject(hDC, hPen);
MoveToEx(hDC, nStartX, nStartY, &pt);
LineTo(hDC, nEndX, nEndY);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
return 0;
자 WM_PAINT 메시지 처리 부분입니다. 한번 보세요. bMouse값에 따라 펜을 서로 다
르게 선택하고 있습니다. 위 WM_LBUTTONUP 메시지에 의하면 bMouse값을 FALSE로하
니 일반 실선의 펜을 선택하고 선을 그린다는 것을 알수 있을 겁니다. 선을 긋는
함수에 대한 것은 이미 설명 드렸을 겁니다.
case WM_MOUSEMOVE :
if(bMouse)
{
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
}
return 0;
위 메시지는 마우스가 움직일때 발생되는 메시지라고 설명 드렸죠? 왼쪽 버튼이 눌
린 상태에서 드래그 되는지 체크하기 위해서 위 조건문을 사용한 것입니다. 역시
InvalidateRect() 함수에 의해서 WM_PAINT 구문이하가 실행되겠죠? 이번에는 bMouse
값이 TRUE이므로 점선과 점으로 이루어진 선을 그을 겁니다. 그렇게 어렵지 않죠?
이번에는 박스를 어떻게 그리는지 알아 보겠습니다. 박스도 마찬가지입니다. 박스
그리는 함수 하나만 알면 간단하게 해결되죠.
BOOL Rectangle(HDC hDC, int nLeftTop, int nTop, int nRightBottom,
int nBottom);
차례로 사각 모서리의 왼쪽 위 좌표, 오른쪽 아래 좌표를 의미하는 것입니다. 사각
의 양 끝좌표를 지정해 주어서 사각형을 그리는 함수입니다. 그러면 예제를 보도록
하죠. 위 선 그리는 예제와 같은 기능을 하는 예제인데 단지 박스를 그린다는 것만
다릅니다.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Graphic Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
HPEN hPen;
static BOOL bMouse;
static int nStartX, nStartY, nEndX, nEndY;
static POINT pt;
switch(message)
{
case WM_LBUTTONDOWN :
bMouse = TRUE;
nStartX = LOWORD(lParam);
nStartY = HIWORD(lParam);
return 0;
case WM_LBUTTONUP :
bMouse = FALSE;
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
return 0;
case WM_MOUSEMOVE :
if(bMouse)
{
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
}
return 0;
case WM_PAINT :
if(bMouse)
hPen = CreatePen(PS_DASHDOT, 0, RGB(0, 0, 0));
else
hPen = CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
hDC = BeginPaint(hWnd, &ps);
SelectObject(hDC, hPen);
Rectangle(hDC, nStartX, nStartY, nEndX, nEndY);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
소스 코드가 똑같죠? 함수 하나만 다르군요.
 
그래픽에 관련된 예제인데 크게 세가지를 알아 보겠습니다. 원,
다각형, 그리고 우리가 이제껏 그린 그림의 내부를 원하는 색으로 채워 넣는 예제
를 보도록 하겠습니다. 원, 다각형까지 알아 보면 그래픽에 관련된 모든 부분을 설
명 했을거라고 생각할텐데 사실은 그렇지 않습니다. 현이나 호, 부채꼴같은 것을
그리는 함수도 있는데 글로서 설명을 드리기가 참 애매하거든요. 이 부분은 여러분
들이 관련 서적을 참고해서 스스로 익히시기 바랍니다.
먼저 첫번째 프로그램으로 원을 그리는 예제를 보도록하겠습니다. 이 원 그리는
예제도 간단합니다. 원 그리는 함수 하나만 알면 되죠.
BOOL Ellipse(HDC hDC, int nLeftTop, int nTop, int nRightBottom, int nBottom);
파라미터는 앞에서 먼저 알아본 사각형을 그리는 함수와 같습니다. 즉 위 함수를 사
용하면 사각 좌표안에 들어가는 원이 그려지는 것입니다. 아래 예제는 앞에서 알아
본 예제와 다른점은 없습니다. 단지 함수만 원을 그리는 거죠.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Graphic Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
HPEN hPen;
static BOOL bMouse;
static int nStartX, nStartY, nEndX, nEndY;
static POINT pt;
switch(message)
{
case WM_LBUTTONDOWN :
bMouse = TRUE;
nStartX = LOWORD(lParam);
nStartY = HIWORD(lParam);
return 0;
case WM_LBUTTONUP :
bMouse = FALSE;
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
return 0;
case WM_MOUSEMOVE :
if(bMouse)
{
nEndX = LOWORD(lParam);
nEndY = HIWORD(lParam);
InvalidateRect(hWnd, NULL, TRUE);
}
return 0;
case WM_PAINT :
if(bMouse)
hPen = CreatePen(PS_DASHDOT, 0, RGB(0, 0, 0));
else
hPen = CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
hDC = BeginPaint(hWnd, &ps);
SelectObject(hDC, hPen);
Ellipse(hDC, nStartX, nStartY, nEndX, nEndY);
DeleteObject(hPen);
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
설명 드릴부분이 없군요. 그렇죠? 자 이번에는 어떤 특정한 모양의 그림을 그리는
것이 아니라 불규칙한 다각형을 어떻게 그릴수 있는지 알아 봅시다.
다각형은 꼭지점으로 이루어 졌죠? 이 꼭지점을 지정한후에 이 꼭지점을 연결해 주
는 함수를 이용하게 되면 어떤 다각형이라도 그리는것이 가능합니다. 물론 지정해
준 꼭지점을 이용해서 다각형을 그리는 함수가 있습니다.
BOOL Polygon(HDC hDC, CONST POINT *lpPoints, int nCount);
두번째 파라미터는 꼭지점 정보가 들어 있는 POINT 구조체의 주소입니다. 세번째 파
라미터는 꼭지점의 개수를 의미하는 거죠. 자 그러면 실제로 예제를 봅시다. 아래
예제를 보면 금방 이해가 갈겁니다.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Graphic Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
HPEN hPen;
static POINT pt[5];
static int nCount, nX, nY;
switch(message)
{
case WM_LBUTTONDOWN :
nX = LOWORD(lParam);
nY = HIWORD(lParam);
pt[nCount].x = nX;
pt[nCount++].y = nY;
if(nCount == 5)
{
hDC = GetDC(hWnd);
hPen = CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
SelectObject(hDC, hPen);
Polygon(hDC, pt, 5);
DeleteDC(hPen);
ReleaseDC(hWnd, hDC);
nCount = 0;
}
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
위 예제가 어떤 역할을 하는건지 짐작이 갑니까? 바로 윈도우의 작업영역에 마우스
의 왼쪽 버튼을 다섯번 클릭하게 되면 클릭된 위치를 꼭지점으로 하는 다각형을 그
리는 예제입니다.
case WM_LBUTTONDOWN :
nX = LOWORD(lParam);
nY = HIWORD(lParam);
pt[nCount].x = nX;
pt[nCount++].y = nY;
마우스의 왼쪽 버튼을 누르면 그 좌표값을 저장하는 구문입니다.
if(nCount == 5)
{
hDC = GetDC(hWnd);
hPen = CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
SelectObject(hDC, hPen);
Polygon(hDC, pt, 5);
DeleteDC(hPen);
ReleaseDC(hWnd, hDC);
nCount = 0;
}
return 0;
다섯번 클릭되었을때 다각형을 그리는 구문이군요. 그렇게 어렵지는 않을 겁니다.
자 우리는 이제껏 다각형이나 선, 원, 사각형등을 그리는 에제만 보았습니다. 이제
마지막으로 이 다각형 안을 원하는 색으로 칠하는 방법을 보도록 하겠습니다. 다각
형을 그릴때에는 펜이라는 개념이 들어 갔기 때문에 원하는 색으로 펜 핸들을 얻
었는데 내부를 칠할때에는 펜을 사용하지 않습니다. 바로 브러쉬를 사용하는데 브
러쉬를 사용할때에는 브러쉬 핸들을 얻어야 합니다. 펜을 사용할때도 펜 핸들을 얻
어서 사용했죠?
HBRUSH CreateSolidBrush(COLORREF crColor);
위 함수를 이용해서 브러쉬 핸들을 얻으면 됩니다. 파라미터는 컬러입니다. 함수 이
름에서 알수 있듯이 이 함수로 얻은 브라쉬로 다각형의 내부를 칠하게 되면 내부를
선택한 브러쉬의 색깔로 완전히 채우게 됩니다. 이 함수를 이용하지 않고 않고
아래 함수를 이용해서 브러쉬 핸들을 얻게 되면 내부를 완전히 칠하지 않고 빗금같
은 형식으로 채우게 됩니다.
HBRUSH CreatHatchBrush(int fnStyle, COLORREF crColor);
첫번째 파라미터에 어떤 값을 넣는냐에 따라서 빗금치는 형식이 다른 브러쉬를 얻을
수 있습니다. 다음은 첫번째 파라미터에 들어갈수 있는 예약어입니다.
HS_HORIZONTAL 가로방향의 선을 의미합니다.
HS_BDIAGONAL 빗금을 의미합니다.
HS_VERTICAL 세로방향의 선을 의미합니다.
HS_CROSS 십자모양의 선을 의미합니다.
HS_FDIAGONAL 빗금을 의미합니다. 위의 빗금과는 방향이 반대입니다.
HS_DIAGCROSS 엑스모양의 선을 의미합니다.
위에 보면 빗금이라고 되어 있는데 말로서 설명하지니 상당히 난감하군요..
아래에 예제가 있으니 직접 눈으로 확인하시가 바랍니다. 그러면 예제를 볼까요?
아래 예제는 바로 위에서 알아본 예제와 같습니다. 단지 다른점은 그려진 다각형의
내부를 원하는 색으로 칠한다는 차이점 밖에는 없습니다.
#include <windows.h>
#include <stdlib.h>
#include <string.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain
(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArg, int nCmdShow)
{
static char szAppName[] = "Graphic Example";
HWND hWnd;
MSG msg;
WNDCLASS WndClass;
WndClass.style = CS_HREDRAW|CS_VREDRAW;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = hInstance;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = szAppName;
if(!RegisterClass(&WndClass))
return FALSE;
hWnd = CreateWindow(
szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
HBRUSH hBrush;
static POINT pt[5];
static int nCount, nX, nY, nPattern;
switch(message)
{
case WM_LBUTTONDOWN :
nX = LOWORD(lParam);
nY = HIWORD(lParam);
pt[nCount].x = nX;
pt[nCount++].y = nY;
if(nCount == 5)
{
if(nPattern == 0)
hBrush = CreateSolidBrush(RGB(0, 0, 255));
else if(nPattern == 1)
hBrush = CreateHatchBrush(HS_HORIZONTAL,
RGB(0, 0, 255));
else if(nPattern == 2)
hBrush = CreateHatchBrush(HS_BDIAGONAL,
RGB(0, 0, 255));
else if(nPattern == 3)
hBrush = CreateHatchBrush(HS_VERTICAL,
RGB(0, 0, 255));
else if(nPattern == 4)
hBrush = CreateHatchBrush(HS_CROSS,
RGB(0, 0, 255));
else if(nPattern == 5)
hBrush = CreateHatchBrush(HS_FDIAGONAL,
RGB(0, 0, 255));
else if(nPattern == 6)
hBrush = CreateHatchBrush(HS_DIAGCROSS,
RGB(0, 0, 255));
if(++nPattern == 7)
nPattern = 0;
hDC = GetDC(hWnd);
SelectObject(hDC, hBrush);
Polygon(hDC, pt, 5);
DeleteDC(hBrush);
ReleaseDC(hWnd, hDC);
nCount = 0;
}
return 0;
case WM_DESTROY :
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
우리가 알아본 내부를 칠하는 브러쉬를 어떻게 취하는지를 골고루 보여주고 있는
것입니다. 어려운게 있습니까? 없죠? 너무 쉬어서 미치겠군요.
오늘은 여기까지 끝~~~~~~~~~~~~~~~~~~~~~
추신 >
앞으로는 굉장히 어려워 집니다. 지금까지는 사실은 장난이죠..... 자! 진하게
즌비하길 바랍니다. 윈도우즈 프로그래밍은 쉽게 접근하면 굉장히 쉽고 어렵게
접근하면 굉장히 어렵거든요... 여러분들은 굉장히 쉽게 접근하고 있는 것입니다.
반응형

'API 관련 > API 강좌모음' 카테고리의 다른 글

[강좌 12] 그래픽3  (0) 2007.10.26
[강좌 11] 그래픽2  (0) 2007.10.26
[강좌 9] 메뉴2  (0) 2007.10.26
[강좌 8] 메뉴1  (0) 2007.10.26
[강좌 7] 마우스, 타이머  (0) 2007.10.26
Comments