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:  


▷ Script1.rc

image

▷ Resource.h

   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


▷ IDR_ACCELERATOR1

image

<실행결과>

image image

최초 그리기도구는 자유곡선으로 자유롭게 선을 그릴 수 있다.
메뉴에서 선을 선택하거나 Ctrl + L키를 누르면 선을 그릴 수 있다.
이상하게 메시지박스가 보이지 않는데 Alt키를 누르면 그 다음부터 계속 보인다;;; (땀)

imageimage 

원을 선택하고 덮어 쓰겠다고 하면,

image image

이전에 그린 원이 다음에 그린 원에 가려지고,
사각형을 선택하고 덮어 쓰지 않겠다고 하면, (원도 마찬가지)


image

이전에 그린 사각형에 겹쳐 그려진다. (겹치다와 덮다의 의미가 조금 잘 못 된것 같기도 하다…)