U E D R S I H C RSS
ID
Password
Join
결혼 전에는 공작, 약혼을 하면 사자, 결혼을 하면 당나귀. -스페인속담



Contents

1 개요
2 소스
2.1 pbm.hpp
2.2 pbm.cpp
2.3 main.cpp에서 윈도우 프로시져 부분만

1 개요 #

  • 수업때 진행했던 간이 그림그리기 예제입니다. win32api/간이그림툴에서 확장한 것이므로 수업때 내용을 생각하시면서 복습하시기 바랍니다.

2 소스 #

2.1 pbm.hpp #

#ifndef __PENBRUSHMANAGER_HPP__
#define __PENBRUSHMANAGER_HPP__

#include <windows.h>

#define PEN_BRUSH_MAX_NUM 3

struct PenBrushManager {
    HPEN pen[PEN_BRUSH_MAX_NUM], oldpen;
    HBRUSH brush[PEN_BRUSH_MAX_NUM], oldbrush;
    
    void init();
    void fini();
    
    void BeginPen(HDC hdc, int idx);
    void EndPen(HDC hdc);
    
    void BeginBrush(HDC hdc, int idx);
    void EndBrush(HDC hdc);
};

#endif

2.2 pbm.cpp #

#include "pbm.hpp"

void PenBrushManager::init() {
    this->pen[0] = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
    this->pen[1] = CreatePen(PS_SOLID, 2, RGB(0, 255, 0));
    this->pen[2] = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
    
    this->brush[0] = CreateSolidBrush(RGB(255, 0, 0));
    this->brush[1] = CreateSolidBrush(RGB(0, 255, 0));
    this->brush[2] = CreateSolidBrush(RGB(0, 0, 255));
}
void PenBrushManager::fini() {
    for (int i = 0; i < PEN_BRUSH_MAX_NUM; i++) {
        DeleteObject(this->pen[i]);
        DeleteObject(this->brush[i]);
    }
}
    
void PenBrushManager::BeginPen(HDC hdc, int idx) {
    oldpen = (HPEN) SelectObject(hdc, this->pen[idx]);
}
void PenBrushManager::EndPen(HDC hdc) {
    SelectObject(hdc, oldpen);
}
    
void PenBrushManager::BeginBrush(HDC hdc, int idx) {
    oldbrush = (HBRUSH) SelectObject(hdc, this->brush[idx]);
}
void PenBrushManager::EndBrush(HDC hdc) {
    SelectObject(hdc, oldbrush);
}

2.3 main.cpp에서 윈도우 프로시져 부분만 #

당연하겠지만 #include "pbm.hpp"을 추가해야 컴파일되겠죠? (의외로 간단한 것때문에 해메시는 분들이 많습니다)
/* 이 함수는 윈도우즈 함수 DispatchMessage()를 호출할 때 실행됩니다. */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static PenBrushManager pbm_;
    static RECT rc_[3];
    static int curr_pen;
    
    static POINT points[512];
	static bool	 movemodes[512];
	static int   point_num = 0;
	static bool	 prev_movemodes = 0; // 0 : MoveToEx(), 1 : LineTo()
    switch (message)                  /* 메세지에 따라 분기합니다 */
    {
            case WM_CREATE:
                SetRect(&rc_[0], 10, 10, 20, 20);
                SetRect(&rc_[1], 30, 10, 40, 20);
                SetRect(&rc_[2], 50, 10, 60, 20);
                curr_pen = 0;
                pbm_.init();
                break;
            case WM_LBUTTONDOWN:
                {
                    const POINT p = {LOWORD(lParam), HIWORD(lParam)};
                    if (PtInRect(&(rc_[0]), p)) curr_pen = 0;
                    if (PtInRect(&(rc_[1]), p)) curr_pen = 1;
                    if (PtInRect(&(rc_[2]), p)) curr_pen = 2;
                }
                break;
    		case WM_RBUTTONDOWN:
    			point_num = 0; // 모든 그림기록을 지운다. 
      		break; 
    		case WM_MOUSEMOVE:
    			// 만일 point_num가 한계를 넘어가면 그냥 break한다.
       		if ( point_num == 512 ) break; 		
       		// 좌표를 배열에 대입한다.
         	points[point_num].x = LOWORD(lParam); 
       		points[point_num].y = HIWORD(lParam);
       		movemodes[point_num] = prev_movemodes;
       		// 왼쪽 버튼을 누르고 있는 동안만 배열에 추가한다. 이렇게 하면 배열안에 공간이 절약된다. 
         	if ( (wParam & MK_LBUTTON) ) point_num++;
         	// 왼쪽 버튼이 눌려있는 여부로 현재 그릴것인지 여부를 결정한다.    		
       		prev_movemodes = (bool)(wParam & MK_LBUTTON);
       		InvalidateRect( hwnd, NULL, TRUE);
    			break;
    		case WM_PAINT :
    			{
                    PAINTSTRUCT ps;
    				HDC hdc = BeginPaint( hwnd, &ps );
    				
    				// 네모칸을 그린다. 이 부분을 선택하면 색상이 변하게 된다. 
    				for (int i = 0; i < 3; i++) {
    				    pbm_.BeginBrush(hdc, i);
    				    Rectangle(hdc, rc_[i].left, rc_[i].top, rc_[i].right, rc_[i].bottom);
    				    pbm_.EndBrush(hdc);
    				}
    				
    				// 선을 그린다. 
                    pbm_.BeginPen(hdc, curr_pen);
    				MoveToEx(hdc, points[0].x, points[0].y, NULL);
    				for (int i = 0; i < point_num; i++) {
    					if (movemodes[i])
             				LineTo(hdc, points[i].x, points[i].y);
    					else 
                            MoveToEx(hdc, points[i].x, points[i].y, NULL);
                    }
                    pbm_.EndPen(hdc);
                {
                    char buf[512];
                    sprintf(buf, "%d개 저장중", point_num);
                    TextOut(hdc, 10, 30, buf, strlen(buf));
                }
                if ( point_num == 512 ) TextOut(hdc, 10, 10, "오버플로우!", 11); 
                EndPaint( hwnd, &ps );
            }
            break;
        case WM_DESTROY:
            pbm_.fini();
            PostQuitMessage (0);       /* 메세지 큐에 WM_QUIT 메세지를 보냅니다. */
            break;
        default:                      /* 다루지 않은 메세지는 모두 운영체계에게 넘깁니다. */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2010-10-28 12:42:54
Processing time 0.5563 sec