2011년9월14일_winAPI_윈도우즈API정복 p.175 과제 RopMode2에 그리기모드 선택 MessageBox추가
● 전체소스코드
▷ main.cpp
1: // winAPI p.175 RopMode2 과제
2: // 2011년 9월 9일 작성
3: #include <windows.h> // 모든 API함수들의 원형과 사용하는 상수들이 정의되어 있음.
4: #include "MsgProc.h" //add
5: #include "resource.h" //자동으로 만들어지는 헤더파일.
6:
7: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //메시지처리함수
8: HINSTANCE g_hlnst; //핸들 인스턴스
9: LPCTSTR lpszClass = TEXT("RopMode2"); //윈도우 제목으로 사용되는 const char * (문자열)
10:
11: //add
12: typedef struct MESSAGEMAP {
13: UINT iMessage;
14: LRESULT (*lpfnMsgProc)(HWND, WPARAM, LPARAM);
15: } MESSAGEMAP;
16:
17: //시작함수.
18: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
19: {
20: HWND hWnd;
21: MSG Message;
22: WNDCLASS WndClass;
23: g_hlnst = hInstance;
24: HACCEL hAccel;
25:
26: WndClass.cbClsExtra = 0;
27: WndClass.cbWndExtra = 0;
28: WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
29: //WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
30: WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
31: WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
32: WndClass.hInstance = hInstance;
33: WndClass.lpfnWndProc = WndProc;
34: WndClass.lpszClassName = lpszClass;
35: WndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
36: WndClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
37: RegisterClass(&WndClass);
38:
39:
40: hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
41: CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
42: NULL, (HMENU)NULL, hInstance, NULL);
43:
44: ShowWindow(hWnd, nCmdShow);
45:
46: hAccel =LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
47: while(GetMessage(&Message, NULL, 0, 0)) {
48: if(!TranslateAccelerator(hWnd, hAccel, &Message))
49: {
50: TranslateMessage(&Message);
51: DispatchMessage(&Message);
52: }
53: }
54:
55: return (int)Message.wParam;
56: }
57:
58: //운영체제가 호출하는 CALLBACK함수 (메시지 처리)
59: LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
60: {
61: //add
62: int i;
63:
64: static MESSAGEMAP MessageMaps[] = {
65: {WM_CREATE, OnCreate},
66: {WM_COMMAND, OnCommand},
67: {WM_LBUTTONDOWN, OnLButtonDown},
68: {WM_RBUTTONDOWN, OnRButtonDown},
69: {WM_MOUSEMOVE, OnMouseMove},
70: {WM_LBUTTONUP, OnLButtonUp},
71: {WM_LBUTTONDBLCLK, OnLButtonDBLCLK},
72: {WM_PAINT, OnPaint},
73: {WM_DESTROY, OnDestroy}
74: };
75:
76: for(i = 0 ; i < sizeof(MessageMaps) / sizeof(MessageMaps[0]) ; ++i)
77: {
78: if(MessageMaps[i].iMessage == iMessage)
79: {
80: return (*MessageMaps[i].lpfnMsgProc)(hWnd, wParam, lParam);
81: }
82: }
83: /////////////////////////////////
84:
85: return(DefWindowProc(hWnd, iMessage, wParam, lParam));
86: }
▷ MsgProc.h와 MsgProc.cpp
1: //MsgProc.h
2: #ifndef __MSGPROC_H_
3: #define __MSGPROC_H_
4:
5: #include <windows.h>
6: #include "resource.h"
7:
8: LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam);
9: LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam);
10: LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
11: LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
12: LRESULT OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam);
13: LRESULT OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam);
14: LRESULT OnLButtonDBLCLK(HWND hWnd, WPARAM wParam, LPARAM lParam);
15: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam);
16: LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam);
17:
18:
19: extern HINSTANCE g_hlnst;
20:
21: #endif
1: //MsgProc.cpp
2:
3: #include "MsgProc.h"
4:
5:
6: int sx, sy, oldx, oldy;
7: int iTool = 0; //0-자유곡선, 1-선, 2-원, 3-사각형
8: int iMode = 0; //0-브러시 투명, 1-브러시 화이트(디폴트)
9: BOOL bNowDraw = FALSE;
10:
11:
12: LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam)
13: {
14: return 0;
15: }
16:
17: LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
18: {
19: int iRet;
20:
21: if(ID_GLIGI_EXIT != LOWORD(wParam)) // 윈도우 닫기인 경우 메시지박스를 띄우지 않음.
22: {
23: iRet = MessageBox(hWnd, TEXT("그림을 덮어 씁니까?"), TEXT("메시지 박스"), MB_YESNO | MB_ICONQUESTION);
24:
25: switch(iRet)
26: {
27: case IDYES:
28: iMode = 1; // 덮어 쓰기 모드
29: break;
30:
31: case IDNO:
32: iMode = 0; // 겹쳐 쓰기 모드
33: break;
34:
35: default:
36: break;
37: }
38: }
39:
40: switch(LOWORD(wParam)) // 선택한 메뉴 검사
41: {
42: case ID_GLIGI_FREE: //자유곡선
43: iTool = 0;
44: break;
45:
46: case ID_GLIGI_LINE: //선
47: iTool = 1;
48: break;
49:
50: case ID_GLIGI_ELLIPSE: //원
51: iTool = 2;
52: break;
53:
54: case ID_GLIGI_RECT: //사각형
55: iTool = 3;
56: break;
57:
58: case ID_GLIGI_EXIT: //종료
59: DestroyWindow(hWnd);
60: break;
61: }
62:
63: return 0;
64: }
65:
66: LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
67: {
68: sx = LOWORD(lParam); // 현재 x좌표 저장
69: sy = HIWORD(lParam); // 현재 y좌표 저장
70: oldx = sx; // 끝점도 동일하게
71: oldy = sy; // 끝점도 동일하게
72: bNowDraw = TRUE; // 그리기 시작.
73:
74: return 0;
75: }
76:
77: LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
78: {
79:
80: return 0;
81: }
82:
83:
84: LRESULT OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
85: {
86: HDC hdc;
87: HBRUSH MyBrush, OldBrush;
88:
89: if(bNowDraw) // 마우스 오른버튼UP전까지 그림.
90: {
91: hdc = GetDC(hWnd);
92:
93: if(0 == iMode) // 겹쳐쓰기모드이면
94: { // 투명 브러시로 안을 채운다.
95: MyBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
96: OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
97: }
98:
99: switch(iTool) //그리기 도구 검사
100: {
101: case 0: //자유곡선
102: MoveToEx(hdc, sx, sy, NULL); //과거좌표에서
103: sx = LOWORD(lParam);
104: sy = HIWORD(lParam);
105: LineTo(hdc, sx, sy); //현재 좌표까지 선을 그림.
106: break;
107:
108: case 1: //선
109: SetROP2(hdc, R2_NOT); // 반전모드
110: MoveToEx(hdc, sx, sy, NULL); // sx, sy와
111: LineTo(hdc, oldx, oldy); // oldx, oldy는 같다.
112: oldx = LOWORD(lParam);
113: oldy = HIWORD(lParam); // 최종 목적지
114: MoveToEx(hdc, sx, sy, NULL); // 과거 좌표에서
115: LineTo(hdc, oldx, oldy); // 현재 좌표까지 선을 반전 모드로 선을 그린다.
116: break;
117:
118: case 2: //원
119: SetROP2(hdc, R2_NOTXORPEN);
120: Ellipse(hdc, sx, sy, oldx, oldy);
121: oldx = LOWORD(lParam);
122: oldy = HIWORD(lParam); //최종 목적지
123: Ellipse(hdc, sx, sy, oldx, oldy); //과거좌표에서 현재좌표까지 원을 XNOR모드로 그린다.
124: break;
125:
126:
127: case 3: //사각형
128: SetROP2(hdc, R2_NOTXORPEN);
129: Rectangle(hdc, sx, sy, oldx, oldy);
130: oldx = LOWORD(lParam);
131: oldy = HIWORD(lParam); //최종 목적지
132: Rectangle(hdc, sx, sy, oldx, oldy); //과거좌표에서 현재좌표까지 사각형을 XNOR모드로 그린다.
133: break;
134:
135: }
136:
137: if(0 == iMode) //겹치기 모드인 경우 디폴트 브러시로 다시 바꾼다.
138: {
139: SelectObject(hdc, OldBrush);
140: }
141:
142: ReleaseDC(hWnd, hdc);
143: }
144:
145: return 0;
146: }
147:
148: LRESULT OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
149: {
150: HDC hdc;
151: HBRUSH MyBrush, OldBrush;
152:
153: bNowDraw = FALSE; // 그리기 중지
154:
155: hdc = GetDC(hWnd);
156:
157: if(0 == iMode) //겹치기모드인 경우
158: { //투명브러시로 안을 채운다.
159: MyBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
160: OldBrush = (HBRUSH)SelectObject(hdc, MyBrush);
161: }
162:
163: // 자유곡선을 제외한 선, 원, 사각형의 경우 도형을 남긴다.
164: switch(iTool)
165: {
166: case 0: //자유곡선
167: break;
168:
169: case 1:
170: MoveToEx(hdc, sx, sy, NULL);
171: LineTo(hdc, oldx, oldy);
172: break;
173:
174: case 2:
175: Ellipse(hdc, sx, sy, oldx, oldy);
176: break;
177:
178: case 3:
179: Rectangle(hdc, sx, sy, oldx, oldy);
180: break;
181:
182: }
183:
184: if(0 == iMode) //겹치기모드인 경우 디폴트 브러시로 다시 바꾼다.
185: {
186: SelectObject(hdc, OldBrush);
187: }
188:
189: ReleaseDC(hWnd, hdc);
190:
191:
192: return 0;
193: }
194:
195: LRESULT OnLButtonDBLCLK(HWND hWnd, WPARAM wParam, LPARAM lParam)
196: {
197: InvalidateRect(hWnd, NULL, TRUE); //더블 클릭을 하면 화면을 지우고 다시 그린다.
198: return 0;
199: }
200:
201:
202: LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
203: {
204:
205: return 0;
206: }
207:
208: LRESULT OnDestroy(HWND hWnd, WPARAM wParam, LPARAM lParam)
209: {
210: PostQuitMessage(0);
211: return 0;
212: }
213:
1: //{{NO_DEPENDENCIES}}
2: // Microsoft Developer Studio generated include file.
3: // Used by Script1.rc
4: //
5: #define IDR_MENU1 101
6: #define IDR_ACCELERATOR1 102
7: #define ID_GLIGI_FREE 40001
8: #define ID_GLIGI_LINE 40002
9: #define ID_GLIGI_ELLIPSE 40003
10: #define ID_GLIGI_RECT 40004
11: #define ID_GLIGI_EXIT 40005
12:
13: // Next default values for new objects
14: //
15: #ifdef APSTUDIO_INVOKED
16: #ifndef APSTUDIO_READONLY_SYMBOLS
17: #define _APS_NEXT_RESOURCE_VALUE 103
18: #define _APS_NEXT_COMMAND_VALUE 40006
19: #define _APS_NEXT_CONTROL_VALUE 1000
20: #define _APS_NEXT_SYMED_VALUE 101
21: #endif
22: #endif
<실행결과>
최초 그리기도구는 자유곡선으로 자유롭게 선을 그릴 수 있다.
메뉴에서 선을 선택하거나 Ctrl + L키를 누르면 선을 그릴 수 있다.
이상하게 메시지박스가 보이지 않는데 Alt키를 누르면 그 다음부터 계속 보인다;;; (땀)
이전에 그린 원이 다음에 그린 원에 가려지고,
사각형을 선택하고 덮어 쓰지 않겠다고 하면, (원도 마찬가지)
이전에 그린 사각형에 겹쳐 그려진다. (겹치다와 덮다의 의미가 조금 잘 못 된것 같기도 하다…)