Presentation is loading. Please wait.

Presentation is loading. Please wait.

Visual C download - Visual Studio Team System 2008 Team Suite (90-days Trial)

Similar presentations


Presentation on theme: "Visual C download - Visual Studio Team System 2008 Team Suite (90-days Trial)"— Presentation transcript:

1

2 Visual C download - Visual Studio Team System 2008 Team Suite (90-days Trial) - Service Pack 1 (Visual C Feature Pack 포함) MSDN Library for Visual Studio 2008 SP1 - 저자가 운영하는 카페

3 Part 1 Windows programming basic

4 Chapter 1 Windows programming model

5 HelloWorld 20 int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) 24 { 25 UNREFERENCED_PARAMETER(hPrevInstance); 26 UNREFERENCED_PARAMETER(lpCmdLine); 27 28 // TODO: Place code here. 29 MSG msg; 30 HACCEL hAccelTable; 31 32 // Initialize global strings 33 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 34 LoadString(hInstance, IDC_HELLOWORLD, szWindowClass, MAX_LOADSTRING); 35 MyRegisterClass(hInstance); 36 37 // Perform application initialization: 38 if (!InitInstance (hInstance, nCmdShow)) 39 { 40 return FALSE; 41 }

6 HelloWorld 43 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HELLOWORLD)); 44 45 // Main message loop: 46 while (GetMessage(&msg, NULL, 0, 0)) 47 { 48 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 49 { 50 TranslateMessage(&msg); 51 DispatchMessage(&msg); 52 } 53 } 54 55 return (int) msg.wParam; 56 }

7 Message queue 1 2 Key & mouse Message 3 System queue A B A B
Windows procedure() Message loop Application queue Notepad.exe WindowProc() B B 6 5 4 Tackmgr.exe WindowProc() A A

8 Message queue/ “No response” / WM_SHOWWINDOW

9 HelloWorld 1623 typedef struct tagMSG { 1624 HWND hwnd; 1625 UINT message; 1626 WPARAM wParam; 1627 LPARAM lParam; 1628 DWORD time; 1629 POINT pt; 1630 #ifdef _MAC 1631 DWORD lPrivate; 1632 #endif 1633 } MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;

10 HelloWorld 73 ATOM MyRegisterClass(HINSTANCE hInstance) 74 {
74 { 75 WNDCLASSEX wcex; 76 77 wcex.cbSize = sizeof(WNDCLASSEX); 78 79 wcex.style = CS_HREDRAW | CS_VREDRAW; 80 wcex.lpfnWndProc = WndProc; 81 wcex.cbClsExtra = 0; 82 wcex.cbWndExtra = 0; 83 wcex.hInstance = hInstance; 84 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLOWORLD)); 85 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 86 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 87 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HELLOWORLD); 88 wcex.lpszClassName = szWindowClass; 89 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 90 91 return RegisterClassEx(&wcex); 92 } 93

11 HelloWorld 134 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 135 { 136 int wmId, wmEvent; 137 PAINTSTRUCT ps; 138 HDC hdc; 139 140 switch (message) 141 { 142 case WM_COMMAND: 143 wmId = LOWORD(wParam); 144 wmEvent = HIWORD(wParam); 145 // Parse the menu selections: 146 switch (wmId) 147 { 148 case IDM_ABOUT: 149 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; 151 case IDM_EXIT: DestroyWindow(hWnd); break; 154 default: return DefWindowProc(hWnd, message, wParam, lParam); 156 } 157 break;

12 HelloWorld 158 case WM_PAINT: 159 hdc = BeginPaint(hWnd, &ps);
160 // TODO: Add any drawing code here... 161 EndPaint(hWnd, &ps); 162 break; 163 case WM_DESTROY: 164 PostQuitMessage(0); 165 break; 166 default: 167 return DefWindowProc(hWnd, message, wParam, lParam); 168 } 169 return 0; 170 } 171

13 CALLBACK & Call convention
124 // 125 // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) 126 // 127 // PURPOSE: Processes messages for the main window. 128 // 129 // WM_COMMAND - process the application menu 130 // WM_PAINT - Paint the main window 131 // WM_DESTROY - post a quit message and return 132 // 133 // 134 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

14 CALLBACK & Call convention
122 #elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) 123 #define CALLBACK __stdcall 124 #define WINAPI __stdcall 125 #define WINAPIV __cdecl 126 #define APIENTRY WINAPI 127 #define APIPRIVATE __stdcall 128 #define PASCAL __stdcall 129 #else

15 실습문제 자신의 이름의 머리 글자로 지금까지 설명한 예제 프로젝트를 생성하고 코드를 확인합니다. _tWinMain( ) 함수에서 액셀러레이터 키와 관련한 코드를 삭제해 봅시다. WM_DESTROY 메시지가 발생했을 때 프로그램이 종료되지 않도록 메시지 프로시저 함수를 수정해 봅시다. [About] 메뉴를 선택하면 정보 화면이 나오지 않고 프로그램이 종료되도록 코드를 수정해 봅시다.

16 Chapter 2 MFC CWnd class

17 CWnd class CObject CCmdTarget CWnd

18 CWnd::Create() 102 103 int CCreateDemoView::OnCreate(LPCREATESTRUCT lpCreateStruct) 104 { 105 if (CView::OnCreate(lpCreateStruct) == -1) 106 return -1; 107 108 m_wndChild.Create(TEXT("STATIC"), TEXT("DEMO"), WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(30, 30, 180, 180), this, 1234); 111 112 return 0; 113 } 114

19 CWnd::Create() View window (CCreateDemoView class) Parent window
Left top (0, 0) “WS_BORDER” window style Point A Left top (30, 30) “STATIC” class window Point B Right bottom (180, 180)

20 CWnd::Create() virtual BOOL Create( LPCTSTR lpszClassName, // 윈도우 클래스 이름 LPCTSTR lpszWindowName, // 윈도우 텍스트 DWORD dwStyle, // 윈도우 스타일 Const RECT& rect, // 윈도우 좌표 CWnd* pParentWnd, // 부모 윈도우 UINT nID, // 윈도우 리소스 ID CCreateContext* pContext = NULL // 생성 컨텍스트(Context) );

21 Window Message 2430 /* 2431 * Window Styles 2432 */ 2433 #define WS_OVERLAPPED 0x L 2434 #define WS_POPUP 0x L 2435 #define WS_CHILD 0x L 2436 #define WS_MINIMIZE 0x L 2437 #define WS_VISIBLE 0x L 2438 #define WS_DISABLED 0x L 2439 #define WS_CLIPSIBLINGS 0x L 2440 #define WS_CLIPCHILDREN 0x L 2441 #define WS_MAXIMIZE 0x L 2442 #define WS_CAPTION 0x00C00000L /*WS_BORDER|WS_DLGFRAME */ 2443 #define WS_BORDER 0x L

22 Windows coordination & position
Width 150 Point A Left top (30, 30) Height 150 Point B Right bottom (180, 180)

23 Windows coordination & position

24 CCreateDemoView 예제를 스스로 만들어 봅시다.
실습문제 CCreateDemoView 예제를 스스로 만들어 봅시다. 2. 책의 예제와 동일하게 뷰 클래스에 CWnd 클래스 객체를 멤버로 선언하고 윈도우를 생성합니다. 생성할 윈도우의 클래스는 CButton 클래스로 하고 왼쪽 위의 좌표가 (50, 50)이고 폭과 높이는 각각 200, 100이 되도록 합시다. 3. 2번 실습이 끝났으면 새로운 CWnd 클래스 객체의 멤버를 뷰 클래스에 선언하여 CEdit 클래스를 가진 새로운 자식 윈도우를 생성해 봅시다. 그래서 뷰(View) 화면에 두 개의 자식 윈도우가 나타나도록 해봅시다. 4. 두 자식 윈도우 중 한 윈도우의 부모 윈도우를 바탕 화면이 되도록 코드를 추가해 봅시다.

25 Chapter 3 MFC UI framework basic

26 SDI Framework CMainFrame Top frame window Menu CMainFrame window
CToolBar m_wndToolBar (CMainFrame class member) CCreateDemoView Default view window CStatusBar m_wndStatusBar (CMainFrame class member) CWnd m_wndChild (CCreateDemoView class member)

27 SDI Framework CCreateDemoApp CMainFrame m_wndToolBar m_wndToolBar
Child & member CMainFrame m_wndToolBar m_wndToolBar Child CCreateDemoView CCreateDemoDoc Child & member m_wndChild

28 SDI Framework CFrameWnd CView CWinApp theApp CDocument AfxGetMainWnd()
CFrameWnd::GetActiveView() CFrameWnd CWndThread::m_pMainWnd CMainFrame CFrameWnd:: GetActiveDocument() CWnd::GetParentFrame() AfxGetApp() CView CWinApp CSdiDemoVew CSdiDemoApp theApp CDocument::m_viewList.GetHead() CDocument CSdiDemoDoc CView::GetDocument()

29 Single Document Interface
76 77 // 응용 프로그램의 문서 템플릿을 등록합니다. 문서 템플릿은 78 // 문서, 프레임 창 및 뷰 사이의 연결 역할을 합니다. 79 CSingleDocTemplate* pDocTemplate; 80 pDocTemplate = new CSingleDocTemplate( 81 IDR_MAINFRAME, 82 RUNTIME_CLASS(CCreateDemoDoc), 83 RUNTIME_CLASS(CMainFrame), // 주 SDI 프레임 창입니다. 84 RUNTIME_CLASS(CCreateDemoView)); 85 if(!pDocTemplate) 86 return FALSE; 87 AddDocTemplate(pDocTemplate);

30 Single Document Interface
CObject CCmdTarget CWinThread CWinApp

31 CWinApp 멤버 변수 기능 m_hInstance
현재 응용 프로그램의 인스턴스 핸들입니다. WinMain( ) 함수의 첫 번째 파라미터인 hInstance와 같은 것입니다. m_lpCmdLine WinMain( ) 함수의 lpCmdLine 파라미터와 같은 것입니다. 프로그램을 실행하였을 때 명령줄(Command-line) 정보가 들어 있습니다. m_nCmdShow WinMain( ) 함수의 마지막 파라미터인 nCmdShow와 같은 것입니다. m_pActiveWnd 응용 프로그램의 최상위 프레임 윈도우에 대한 포인터입니다. SDI 구조에서 이 값은 CMainFrame 클래스 객체의 포인터입니다. m_pszAppName 응용 프로그램의 제목에 해당하는 문자열의 포인터입니다. CreateDemo 예제의 경우 이 값이 CreateDemo였습니다. 문자열의 좀더 정확한 정보는 문자열 테이블(String Table)에 들어 있는 AFX_IDS_APP_TITLE에 해당하는 값입니다. m_pszExeName 빌드한 실행 파일에서 확장자( .exe)를 제외한 파일명입니다.

32 CreateDemo 46 BOOL CCreateDemoApp::InitInstance( ) 47 {
47 { 48 // 응용 프로그램 매니페스트가 ComCtl32.dll 버전6 이상을 사용하여 비주얼 스타일을 49 // 사용하도록 지정하는 경우, Windows XP 상에서 반드시 InitCommonControlsEx( )가 필요합니다. 50 // InitCommonControlsEx( )를 사용하지 않으면 창을 만들 수 없습니다. 51 INITCOMMONCONTROLSEX InitCtrls; 52 InitCtrls.dwSize = sizeof(InitCtrls); 53 // 응용 프로그램에서 사용할 모든 공용 컨트롤 클래스를 포함하도록 54 // 이 항목을 설정하십시오. 55 InitCtrls.dwICC = ICC_WIN95_CLASSES; 56 InitCommonControlsEx(&InitCtrls); 57 58 CWinApp::InitInstance( ); 59

33 CFrameWnd CObject CCmdTarget CWnd CFrameWnd

34 CFrameWnd & Control bar windows
Menubar window Toolbar windows Controlbar windows

35 CreateDemo 41 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
42 { 43 if (CFrameWnd::OnCreate(lpCreateStruct) == -1) 44 return -1; 45 46 if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || 47 !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) 48 { 49 TRACE0("도구 모음을 만들지 못했습니다.\n"); 50 return -1; // fail to create 51 } 52 59 60 // TODO: 도구 모음을 도킹할 수 없게 하려면 이 세 줄을 삭제하십시오. 61 m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); 62 EnableDocking(CBRS_ALIGN_ANY); 63 DockControlBar(&m_wndToolBar); 64 65 66 return 0; 67

36 CDocument CObject CCmdTarget CDocument

37 35 BOOL CCreateDemoDoc::OnNewDocument( ) 36 {
CDocument 35 BOOL CCreateDemoDoc::OnNewDocument( ) 36 { 37 if (!CDocument::OnNewDocument( )) 38 return FALSE; 39 40 // TODO: 여기에 재초기화 코드를 추가합니다. 41 // SDI 문서는 이 문서를 다시 사용합니다. 42 43 return TRUE; 44 } 45

38 HelloSdi 35 BOOL CHelloSdiDoc::OnNewDocument( ) 36 {
36 { 37 if (!CDocument::OnNewDocument( )) 38 return FALSE; 39 40 reinterpret_cast<CEditView*>(m_viewList.GetHead( ))->SetWindowText(NULL); 41 42 AfxMessageBox(TEXT("새로운 빈 문서를 열었습니다.")); 43 44 return TRUE; 45 } 46

39 HelloSdi 74 //ChellosdiDoc 명령 75 76 BOOL CHelloSdiDoc::OnOpenDocument(LPCTSTR lpszPathName) 77 { 78 if (!CDocument::OnOpenDocument(lpszPathName)) 79 return FALSE; 80 81 AfxMessageBox(TEXT("사용자가 문서를 열었습니다.")); 82 83 return TRUE; 84 } 85

40 HelloSdi 35 BOOL CHelloSdiDoc::OnNewDocument( ) 36 {
36 { 37 if (!CDocument::OnNewDocument( )) 38 return FALSE; 39 40 reinterpret_cast<CEditView*>(m_viewList.GetHead( ))->SetWindowText(NULL); 41 42 // AfxMessageBox(TEXT("새로운 빈 문서를 열었습니다.")); 43 SetModifiedFlag(TRUE); 44 45 return TRUE; 46 } 47

41 Message map 14 // CMainFrame 15
16 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) 17 18 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) 19 ON_WM_CREATE( ) 20 ON_WM_CLOSE( ) 21 END_MESSAGE_MAP( ) 22 94 95 // CMainFrame 메시지 처리기 96 97 void CMainFrame::OnClose( ) 98 { 99 AfxMessageBox(TEXT("WM_CLOSE 발생")); 100 CFrameWnd::OnClose( ); 101 } 102

42 실습문제 임의의 SDI 프로젝트를 만들고 CDocument 클래스에 OnOpenDocument( ), OnCloseDocument( ) 가상 함수를 재정의해 봅시다. 재정의한 함수에 AfxMessageBox( ) 함수를 이용하여 임의의 메시지 상자를 출력하도록 해봅시다. CMainFrame 클래스의 코드를 수정하여 도구 모음과 상태 표시줄을 제거해 봅시다. 응용 프로그램의 자체 객체(CWinApp 클래스를 상속받은 클래스)에 ExitInstance( ) 함수를 재정의하여 등록해 봅시다. char*형의 전역 변수를 선언하고 InitInstance( ) 함수에서 이 변수에 256바이트 길이의 메모리를 할당한 후 임의의 문자열을 저장하도록 하고 ExitInstance( ) 함수에서 메모리를 해제하도록 해봅시다. 5번 실습을 마친 상태에서 메인 프레임 윈도우가 화면에 나타나기 전에 문자열을 메시지 상자를 이용해서 출력해 봅시다. 너무나 다양한 곳에 코딩이 가능하겠지만 어디가 적합한 위치인지 스스로 고민해서 코딩해봅시다.

43 Chapter 4 MFC SDI application flow

44 01: Function: CSdiSeqApp::CSdiSeqApp( )
Initialization 01: Function: CSdiSeqApp::CSdiSeqApp( ) 02: Function: CSdiSeqApp::InitInstance( ) 03: Function: CSdiSeqDoc::CSdiSeqDoc(void) 04: Function: CMainFrame::CMainFrame(void) 05: Function: CMainFrame::LoadFrame( ) 06: Function: CMainFrame::PreCreateWindow( ) 07: Function: CMainFrame::PreCreateWindow( ) 08: Function: CMainFrame::OnCreate( ) 09: Function: CMainFrame::OnCreateClient( ) 10: Function: CSdiSeqView::CSdiSeqView( ) 11: Function: CSdiSeqView::Create( ) 12: Function: CSdiSeqView::PreCreateWindow( ) 13: Function: CSdiSeqView::OnCreate( ) 14: Function: CSdiSeqView::OnShowWindow( ) 15: CMainFrame::OnCreateClient( ) - Return 16: CMainFrame::OnCreate( ) - Return

45 17: Function: CSdiSeqDoc::OnNewDocument( )
Initialization & Run 17: Function: CSdiSeqDoc::OnNewDocument( ) 18: Function: CSdiSeqView::OnInitialUpdate( ) 19: Function: CMainFrame::OnActivateApp( ) 20: Function: CMainFrame::OnActivate( ) 21: Function: CMainFrame::OnShowWindow( ) 22: Function: CSdiSeqView::GetDocument( ) 23: Function: CSdiSeqApp::Run( )

46 24: Function: CMainFrame::OnClose( )
Close & Destruction 24: Function: CMainFrame::OnClose( ) 25: Function: CMainFrame::OnShowWindow( ) 26: Function: CMainFrame::OnActivate( ) 27: Function: CMainFrame::OnActivateApp( ) 28: Function: CMainFrame::DestroyWindow( ) 29: Function: CMainFrame::OnDestroy( ) 30: Function: CSdiSeqView::OnDestroy( ) 31: Function: CSdiSeqView::PostNcDestroy( ) 32: Function: CSdiSeqView::~CSdiSeqView( ) 33: Function: CMainFrame::OnNcDestroy( ) 34: Function: CMainFrame::PostNcDestroy( ) 35: Function: CMainFrame::~CMainFrame( ) 36: CMainFrame::OnNcDestroy( ) - Return 37: Function: CSdiSeqDoc::~CSdiSeqDoc( ) 38: CMainFrame::OnClose( ) - Return 39: Function: CSdiSeqApp::ExitInstance( ) 40: CSdiSeqApp::Run( ) - Return

47 Window area Client view window Client area Non-client area
Frame window Client area Non-client area

48 Window message processing
Message queue PostMessage() 2 1 A B C D SendMessage() Message loop CMainFrame 3 CMainFrame::PreTranslateMessage() 4 CMainFrame::WindowProc() 5 CMainFrame message handler function

49 Chapter 5 Keyboard & Message

50 WM_KEYDOWN & OnKeyDown()
115 116 void CKeyMoveView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 117 { 118 CPoint ptChild; //차일드 윈도우의 좌표. 119 CRect Rect; //차일드 윈도우의 좌표 및 크기. 120 121 //차일드 윈도우의 두 좌표 정보(스크린 기준)를 알아 온다. 122 m_wndChild.GetWindowRect(&Rect); 123 ptChild.x = Rect.left; 124 ptChild.y = Rect.top; 125 126 //스크린 기준 좌표를 클라이언트 뷰 기준의 좌표로 환산한다. 127 ScreenToClient(&ptChild); 128 129 switch(nChar) 130 { 131 case VK_LEFT: //왼쪽 화살표를 누른 경우. 132 ptChild.x -= 10; //10픽셀만큼 x좌표 값 감소. 133 break; 134

51 WM_KEYDOWN & OnKeyDown()
135 case VK_RIGHT: //오른쪽 화살표를 누른 경우. 136 ptChild.x += 10; //10픽셀만큼 x좌표 값 증가. 137 break; 138 } 139 140 //변경된 새 좌표로 차일드 윈도우를 이동시킨다. 141 m_wndChild.SetWindowPos(&CWnd::wndTop, ptChild.x, ptChild.y, 0, 0, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE); 143 144 CView::OnKeyDown(nChar, nRepCnt, nFlags); 145 } 146

52 Virtual key code 372 /* 373 * Virtual Keys, Standard Set 374 */
372 /* 373 * Virtual Keys, Standard Set 374 */ 375 #define VK_LBUTTON 0x01 376 #define VK_RBUTTON 0x02 377 #define VK_CANCEL 0x03 378 #define VK_MBUTTON 0x04 /* NOT contiguous with L & RBUTTON */ 379 380 #if(_WIN32_WINNT >= 0x0500) 381 #define VK_XBUTTON1 0x05 /* NOT contiguous with L & RBUTTON */ 382 #define VK_XBUTTON2 0x06 /* NOT contiguous with L & RBUTTON */ 383 #endif /* _WIN32_WINNT >= 0x0500 */ 384

53 OnKeyDown() VK_RIGHT VK_NUMPAD6 VK_RIGHT + Control key + Alt key
Transition code Previous key state Context code Extended Key VK_RIGHT 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 OS Not use Scan code 0x01 0x4D VK_NUMPAD6 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 OS Not use Scan code 0x00 0x4D VK_RIGHT + Control key + Alt key 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 OS Not use Scan code 0x21 0x4D

54 Window coordination X Axis Y Axis A (0, 0) Y = 150 Y = 250 Y = 350
B C X = 300 X = 400 D VK_LEFT VK_RIGHT Y Axis

55 KeyMove 117 void CKeyMoveView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 118 { 119 CPoint ptChild; //차일드 윈도우의 좌표 120 CRect Rect; //차일드 윈도우의 좌표 및 크기 121 122 //차일드 윈도우의 두 좌표 정보(스크린 기준)를 알아 온다. 123 m_wndChild.GetWindowRect(&Rect); 124 ptChild.x = Rect.left; 125 ptChild.y = Rect.top; 126

56 KeyMove 126 127 //스크린 기준 좌표를 클라이언트 뷰 기준의 좌표로 환산한다.
127 //스크린 기준 좌표를 클라이언트 뷰 기준의 좌표로 환산한다. 128 ScreenToClient(&ptChild); 129 130 switch(nChar) 131 { 132 case VK_LEFT: //왼쪽 화살표를 누른 경우 133 ptChild.x -= 10; //10픽셀만큼 X좌표 값 감소 134 break; 135 136 case VK_RIGHT: //오른쪽 화살표를 누른 경우. 137 ptChild.x += 10; //10픽셀만큼 X좌표 값 증가 138 break; 139 } 140 141 //변경된 새 좌표로 차일드 윈도우를 이동시킨다. 142 m_wndChild.SetWindowPos(&CWnd::wndTop, ptChild.x, ptChild.y, 0, 0, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOSIZE); 144

57 const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags
::SetWindowPos() BOOL SetWindowPos( const CWnd* pWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags ); 의미 wndBottom Z-order를 최하위로 합니다. wndTop Z-order를 최상위로 합니다. wndTopMost Z-order를 최상위로 하고 시스템 윈도우 속성을 갖습니다. wndNoTopMost 일반 윈도우 중 최상위 윈도우가 되도록 합니다. 의미 SWP_HIDEWINDOW 윈도우가 화면에서 사라지도록 합니다. SWP_SHOWWINDOW 윈도우가 화면에 보이도록 합니다. SWP_NOACTIVATE 윈도우를 활성화하지 않습니다. SWP_NOMOVE 윈도우의 위치를 변경하지 않습니다. (x, y 무시) SWP_NOREDRAW 윈도우를 다시 그리지 않습니다. SWP_NOSIZE 윈도우의 크기를 변경하지 않습니다. (cx, cy 무시) SWP_NOZORDER 윈도우의 Z-order를 변경하지 않습니다. (pWndInsertAfter 무시)

58 KeyMove 151 void CKeyMoveView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 152 { 153 CString strText = TEXT(""); 154 strText.Format(TEXT("%c"), nChar); 155 156 //입력한 키가 Enter, Back Space, ESC 키가 아니면 157 //해당 ASCII 문자로 차일드 윈도우 텍스트를 변경한다. 158 if(nChar != VK_RETURN && nChar != VK_BACK && nChar != VK_ESCAPE) 159 { 160 m_wndChild.SetWindowText(strText); 161 } 162 163 CView::OnChar(nChar, nRepCnt, nFlags); 164 } 165

59 KeyMove 165 166 void CKeyMoveView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 167 { 168 CString strMessage = TEXT(""); 169 171 WORD wResult = ::GetKeyState(VK_SPACE); 172 BYTE byHigh = HIBYTE(wResult); 174 if(byHigh & 0x01) 175 { 176 strMessage += TEXT("Alt + Space, "); 179 wResult = ::GetKeyState(VK_CAPITAL); 180 //하위 바이트의 1번 비트가 1이면 토글 키가 켜진 상태 181 BYTE byLow = LOBYTE(wResult); 182 if(byLow & 0x01) strMessage += TEXT("CAPS LOCK ON"); 183 else strMessage += TEXT("CAPS LOCK OFF"); 184 185 AfxMessageBox(strMessage); 186 } 187 188 CView::OnSysKeyDown(nChar, nRepCnt, nFlags); 189 } 190

60 KeyMove 191 void CKeyMoveView::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags) 192 { 193 if(nChar == VK_RETURN) 194 AfxMessageBox(TEXT("Alt + Enter")); 195 else if(nChar == 's' || nChar == 'S') 196 AfxMessageBox(TEXT("Alt + S")); 197 else if(nChar == 'x' || nChar == 'X') 198 AfxMessageBox(TEXT("Alt + X")); 199 200 CView::OnSysChar(nChar, nRepCnt, nFlags); 201 } 202

61 KeyMove 예제에서 자식 윈도우가 위아래로 이동할 수 있도록 코드를 추가해 봅시다.
실습안내 KeyMove 예제에서 자식 윈도우가 위아래로 이동할 수 있도록 코드를 추가해 봅시다. 2. KeyMove 예제를 수정하여 Control 키와 방향키를 함께 눌렀을 때는 윈도우의 이동 폭이 더 커지도록 해봅시다. 3. KeyMove 예제를 응용하여 방향키를 누르면 자식 윈도우의 위치가 바뀌는 것이 아니라 윈도우의 크기가 커지거나 작아지도록 해봅시다. 4. [Alt + F4] 키를 누르면 WM_CLOSE 메시지가 발생하고 프로그램이 종료됩니다. 유사하게 [Alt + X] 키를 누르면 프로그램을 종료하도록 예제를 작성해 봅시다.

62 Chapter 6 Mouse & Message

63 MouseMsg 100 // CmouseMsgView 메시지 처리기 101
102 void CMouseMsgView::OnPaint( ) 103 { 104 CPaintDC dc(this); // device context for painting 105 106 CString strData = _T(""); 107 strData.Format(_T("X:%03d, Y:%03d"), m_ptMouse.x, m_ptMouse.y); 108 109 dc.TextOut(10, 10, strData); 110 } 111 112 113 void CMouseMsgView::OnMouseMove(UINT nFlags, CPoint point) 114 { 115 m_ptMouse = point; 116 RedrawWindow( ); 117 118 CView::OnMouseMove(nFlags, point); 119 } 120

64 MouseMsg 155 156 BOOL CMouseMsgView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 157 { 158 CString strTmp = _T(""); 159 strTmp.Format(TEXT("OnMouseWheel( ) zDelta : %d\n"), zDelta); 160 TRACE(strTmp); 161 162 return CView::OnMouseWheel(nFlags, zDelta, pt); 163 } 164

65 MouseCombi – Click vs Double click

66 MouseCombi 106 107 void CMouseCombiView::OnLButtonDown(UINT nFlags, CPoint point) 108 { 109 // m_ptItemText 값을 기준으로 64픽셀 내에서 110 // 마우스 왼쪽 버튼이 클릭된 것인가? 111 if(point.x >= m_ptItemText.x - 32 && 112 point.x <= m_ptItemText.x + 32 && 113 point.y >= m_ptItemText.y - 32 && 114 point.y <= m_ptItemText.y + 32) 115 { 116 m_bDragFlag = true; 117 RedrawWindow( ); 118 } 119 120 CView::OnLButtonDown(nFlags, point); 121 } 122

67 MouseCombi 122 123 void CMouseCombiView::OnLButtonUp(UINT nFlags, CPoint point) 124 { 125 // 드래그 중이었는가? 126 if(m_bDragFlag) 127 { 128 // 버튼에서 손을 뗐으므로 드래그가 끝났다고 판단한다. 129 m_bDragFlag = false; 130 // 드래그가 끝난 이 좌표가 드롭된 좌표이다. 131 m_ptItemText = point; 132 RedrawWindow( ); 133 } 134 135 CView::OnLButtonUp(nFlags, point); 136 } 137

68 MouseCombi 154 155 void CMouseCombiView::OnMouseMove(UINT nFlags, CPoint point) 156 { 157 if(m_bDragFlag) 158 { 159 //드래그 중인 좌표로 아이템 텍스트를 이동시켜 출력한다. 160 m_ptItemText = point; 161 RedrawWindow( ); 162 } 163 164 CView::OnMouseMove(nFlags, point); 165 } 166

69 MouseCombi

70 MouseCombi 32 33 void CTrackWnd::OnMouseMove(UINT nFlags, CPoint point) 34 { 35 if(m_bTrack == FALSE) 36 { 37 TRACKMOUSEEVENT MouseEvent; 38 ::ZeroMemory(&MouseEvent, sizeof(MouseEvent)); 39 40 MouseEvent.cbSize = sizeof(MouseEvent); 41 MouseEvent.dwFlags = TME_LEAVE; 42 MouseEvent.hwndTrack = m_hWnd; 43 MouseEvent.dwHoverTime = 0; 44 45 m_bTrack = ::_TrackMouseEvent(&MouseEvent); 46 if(m_bTrack) 47 { 48 SetWindowText(TEXT("Tracking!")); 49 } 50 } 51 52 CWnd::OnMouseMove(nFlags, point); 53 } 54

71 MouseCombi 55 56 void CTrackWnd::OnMouseLeave( ) 57 {
57 { 58 TRACKMOUSEEVENT MouseEvent; 59 ::ZeroMemory(&MouseEvent, sizeof(MouseEvent)); 60 61 MouseEvent.cbSize = sizeof(MouseEvent); 62 MouseEvent.dwFlags = TME_CANCEL; 63 MouseEvent.hwndTrack = m_hWnd; 64 65 ::_TrackMouseEvent(&MouseEvent); 66 67 m_bTrack = FALSE; 68 SetWindowText(TEXT("WM_MOUSELEAVE")); 69 70 CWnd::OnMouseLeave( ); 71 } 72

72 실습안내 1. MouseCombi 예제를 개선하여 클라이언트 뷰 윈도우 영역 밖으로 드래그를 할 수 없도록 코드를 수정해 봅시다. 2. MouseCombi 예제의 클라이언트 뷰 클래스에 CTrackWnd 클래스처럼 마우스 이벤트를 추적하는 코드를 추가해 봅시다. 3. CWnd 클래스의 WindowFromPoint( ) 멤버 함수에 대해 알아보고 MouseCombi 예제에 새로운 기능을 추가하여 다른 윈도우의 핸들을 알아내는 코드를 추가해 봅시다. 참고로 이런 기능은 ShowMeToLoop 예제에서 이미 구현한 것입니다.

73 Chapter 7 Graphics Device Interface basic

74 GDI & DC Application GetDC() ReleaseDC() GDI 32 User mode DirectX
Kernel mode Graphics Engine (GDI) VGA Driver Printer Driver

75 GDI & DC Redraw area

76 WM_PAINT & Redarw

77 WM_PAINT & OnPaint() 115 116 void CRedrawDemoView::OnPaint( ) 117 {
117 { 118 CPaintDC dc(this); // device context for painting 119 120 dc.Rectangle(120, 10, 220, 110); 121 } 122

78 WM_PAINT & OnPaint() 파생 클래스 의미 CClientDC 윈도우의 클라이언트 영역으로 한정되는 DC입니다.
CWindowDC 윈도우의 모든 영역(비클라이언트 영역 포함)에 대한 DC입니다. 이 DC를 이용하면 다른 윈도우에 대해서 그리기가 가능합니다. CPaintDC CClientDC 클래스와 유사하지만, 내부적으로 BeginPaint( )/EndPaint( ) 함수를 호출하여 WM_ERASEBKGND 메시지가 발생한다는 것이 다릅니다. CMetaFileDC WMF(Window Meta File), EMF(Enhanced Meta File) 파일에 대한 DC입니다.

79 WM_PAINT & OnPaint() 115 116 void CRedrawDemoView::OnPaint( ) 117 {
117 { 118 CPaintDC dc(this); // device context for painting 119 120 // 두께가 3픽셀인 붉은 색 펜을 생성한다. 121 CPen NewPen(PS_SOLID, 3, RGB(192, 0, 0)); 122 // 생성한 펜을 DC의 현재 펜으로 변경하고 기존 펜 객체에 대한 123 // 포인터를 별도로 저장해둔다. 124 CPen* pOldPen = dc.SelectObject(&NewPen); 125 126 // 그리기 작업을 수행한다. 127 dc.Rectangle(120, 10, 220, 110); 128 129 // 예전 펜을 현재 펜으로 바꾼다. 130 dc.SelectObject(pOldPen); 131 } 132

80 MoveTo() / LineTo() 100 101 // CPenBrushDemoView 102
103 void CPenBrushDemoView::OnPaint( ) 104 { 105 CPaintDC dc(this); // device context for painting 106 107 CPen NewPen(PS_SOLID, 20, RGB(192, 192, 192); 108 CPen* pOldPen = dc.SelectObject(&NewPen); 109 110 // 두께가 20픽셀인 선을 긋는다. 111 dc.MoveTo(40, 40); // 시작 좌표 112 dc.LineTo(240, 40); // 끝 좌표 113 114 dc.SelectObject(pOldPen); 115 116 // 본래의 펜(두께1, 검정)으로 동일한 선을 겹쳐 긋는다. 117 dc.MoveTo(40, 40); // 시작 좌표 118 dc.LineTo(240, 40); // 끝 좌표 119 } 120

81 CPen A (40, 40) B (240, 40)

82 CPen 값 의미 PS_SOLID 일반 실선입니다. PS_DASH 대시(Dash)를 점선처럼 열거합니다. PS_DOT 점선.
PS_DASHDOT 대시와 점 한 번씩을 번갈아서 출력합니다. PS_DASHDOTDOT 대시 한 번에 점을 두 번을 번갈아서 출력합니다. PS_INSIDEFRAME 도형을 그릴 때 두꺼운 펜(2픽셀 이상)이 도형의 경계 좌표를 벗어나지 않도록 합니다. (다음 절 각종 도형 그리기에 자세한 코드 예가 있습니다.) PS_NULL 투명한 선을 긋습니다. 따라서 화면에는 아무것도 보이지 않습니다. 도형을 그릴 때 테두리를 없애기 위해 의도적으로 사용하기도 합니다.

83 Geometric pen 101 // CpenBrushDemoView 메시지 처리기 102
103 void CPenBrushDemoView::OnPaint( ) 104 { 105 CPaintDC dc(this); // device context for painting 106 107 LOGBRUSH lb; 108 lb.lbStyle = BS_SOLID; 109 lb.lbColor = RGB(192, 192, 192); 110 111 CPen arNewPen[3]; 112 CPen* pOldPen = NULL; 113 arNewPen[0].CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_ROUND, 20, &lb); 114 arNewPen[1].CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_SQUARE, 20, &lb); 115 arNewPen[2].CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT, 20, &lb); 116

84 Geometric pen 101 // CPenBrushDemoView 메시지 처리기 102
103 void CPenBrushDemoView::OnPaint( ) 104 { 105 CPaintDC dc(this); // device context for painting 106 // PS_USERSTYLE 예 107 DWORD style[] = {6, 3}; 108 LOGBRUSH lb; 109 lb.lbStyle = BS_SOLID; 110 lb.lbColor = RGB(255, 0, 0); 111 112 CPen NewPen; 113 NewPen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT, , &lb, 2, style); 115 CPen* pOldPen = dc.SelectObject(&NewPen); 116 117 // 두께가 20픽셀인 선을 긋는다. 118 dc.MoveTo(40, 40); // 시작 좌표 119 dc.LineTo(240, 40); // 끝 좌표 120 121 dc.SelectObject(pOldPen); 122 } 123

85 Geometric pen

86 Hatch brush 101 // CPenBrushDemoView 메시지 처리기 102
103 void CPenBrushDemoView::OnPaint( ) 104 { 105 CPaintDC dc(this); // device context for painting 106 107 CBrush NewBrush(HS_CROSS, RGB(192, 0, 0)); 108 CBrush* pOldBrush = dc.SelectObject(&NewBrush); 109 110 dc.Rectangle(20, 20, 140, 140); 111 112 dc.SelectObject(pOldBrush); 113 } 114

87 Bitmap brush 101 // CPenBrushDemoView 메시지 처리기 102
103 void CPenBrushDemoView::OnPaint( ) 104 { 105 CPaintDC dc(this); // device context for painting 106 107 CBrush NewBrush; 108 // 비트맵 클래스 객체를 선언하여 비트맵 리소스 로딩 109 CBitmap Bmp; 110 Bmp.LoadBitmap(IDB_BITMAP1); 111 // 로딩된 비트맵 리소스로 패턴 브러시 생성. 112 NewBrush.CreatePatternBrush(&Bmp); 113 CBrush* pOldBrush = dc.SelectObject(&NewBrush); 114 115 // 클라이언트 뷰 클래스의 클라이언트 영역 크기를 알아내고 116 // 크기에 해당하는 네모를 그림. 117 CRect Rect; 118 GetClientRect(&Rect); 119 dc.Rectangle(&Rect); 120 121 dc.SelectObject(pOldBrush); 122 } 123

88 TriangleDemo A Z C B

89 TriangleDemo 스타일 결과 화면 PS_JOIN_BEVEL PS_JOIN_ROUND PS_JOIN_MITER

90 TriangleDemo S (PieRect.CenterPoint().x, 20) A (20, 20) 270º
E (140, PieRect.CenterPoint().y) PieRect.CenterPoint() S’ (PieRect.CenterPoint().x, 140) B (140, 140)

91 실습안내 1. 전형적인 SDI 형식의 예제를 생성하여 크기가 120 * 120인 정사각형을 화면에 출력하는 코드를 작성해 봅시다. 2. 앞에서 작성한 사각형의 테두리를 3픽셀의 붉은색으로 하고 내부는 회색으로 칠하도록 코드를 추가합시다. 3. 임의의 육각형을 출력하는 코드를 작성해 봅시다. 4. 다음 그림은 MSN 메신저 화면입니다. 클라이언트 뷰 영역을 보면 모서리가 둥근 형태입니다. 이와 같은 모양을 구현하되 RoundRect( ) 함수를 사용하지 않고 구현해 봅시다.

92 Font

93 LOGFONT 1197 typedef struct tagLOGFONTW 1198 { 1199 LONG lfHeight;
1198 { LONG lfHeight; LONG lfWidth; LONG lfEscapement; LONG lfOrientation; LONG lfWeight; BYTE lfItalic; BYTE lfUnderline; BYTE lfStrikeOut; BYTE lfCharSet; BYTE lfOutPrecision; BYTE lfClipPrecision; BYTE lfQuality; BYTE lfPitchAndFamily; WCHAR lfFaceName[LF_FACESIZE]; 1213 } LOGFONTW, *PLOGFONTW, NEAR *NPLOGFONTW, FAR *LPLOGFONTW; 1214 #ifdef UNICODE 1215 typedef LOGFONTW LOGFONT;

94 TabbedTextOut() Tab size : 40 Tab size : 40 * 2 CSize (244, 36)

95 VirtualButton

96 VirtualButton 100 101 // CVirtualButtonView 메시지 처리기 102
103 void CVirtualButtonView::OnLButtonDown(UINT nFlags, CPoint point) 104 { 105 // 버튼이 위치한 영역을 클릭하였는가? 106 if(m_BtnRect.PtInRect(point)) 107 { 108 // 플래그를 토글하고 윈도우를 다시 그린다. 109 m_bClicked = !m_bClicked; 110 RedrawWindow(&m_BtnRect); 111 } 112 113 CView::OnLButtonDown(nFlags, point); 114 } 115

97 VirtualButton 116 117 void CVirtualButtonView::OnLButtonUp(UINT nFlags, CPoint point) 118 { 119 // 버튼이 위치한 영역인가? 120 if(m_bClicked) 121 { 122 // 플래그를 토글하고 윈도우를 다시 그린다. 123 m_bClicked = !m_bClicked; 124 RedrawWindow(&m_BtnRect); 125 } 126 127 if(m_BtnRect.PtInRect(point)) 128 { 129 AfxMessageBox(L"버튼을 클릭했습니다."); 130 } 131 132 CView::OnLButtonUp(nFlags, point); 133 } 134

98 VirtualButton 135 136 void CVirtualButtonView::OnPaint( ) 137 {
137 { 138 CPaintDC dc(this); // device context for painting 139 // 시스템이 정의한 버튼 색상으로 버튼의 영역을 칠한다. 140 CRect Rect(m_BtnRect); 141 Rect += CRect(1, 1, 1, 1); 142 dc.Rectangle(&Rect); 143 dc.FillSolidRect(&m_BtnRect, ::GetSysColor(COLOR_BTNFACE)); 144 145 if(m_bClicked) // 눌려진 상태 146 { 147 dc.Draw3dRect(m_BtnRect, 148 ::GetSysColor(COLOR_3DSHADOW), // 왼쪽/위쪽이 어두운 색 149 ::GetSysColor(COLOR_3DLIGHT)); // 오른쪽/아래쪽이 밝은 색 150 } 151 else // 평상시 상태 152 { 153 dc.Draw3dRect(m_BtnRect, ::GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW)); 156 }

99 VirtualButton 157 158 // 시스템이 정하는 버튼 관련 색상으로 텍스트를 그린다.
158 // 시스템이 정하는 버튼 관련 색상으로 텍스트를 그린다. 159 dc.SetBkColor(::GetSysColor(COLOR_BTNFACE)); 160 dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT)); 161 162 if(m_bClicked) 163 { 164 CRect Rect = m_BtnRect; 165 // 눌려진 상태면 글씨가 출력되는 위치를 1픽셀 조절한다. 166 Rect += CRect(0, 0, 2, 2); 167 dc.DrawText(L"Test button", &Rect, DT_CENTER | DT_SINGLELINE | DT_VCENTER); 169 } 170 else 171 { 172 dc.DrawText(L"Test button", &m_BtnRect, DT_CENTER | DT_SINGLELINE | DT_VCENTER); 174 } 175 } 176

100 VirtualButton – Draw3dRect()
COLOR_3DSHADOW COLOR_3DLIGHT

101 실습안내 1. “\t이것은 실습을 위한\n문자열입니다.”라는 문자열을 TextOut( ), TabbedTextOut, DrawText( ) 함수를 이용하여 각각 출력하는 예제를 작성해 봅시다. 2. 1번 문자열을 출력할 때 이탤릭(Italic), 굵게(Bold), 밑줄이 들어가도록 글꼴을 변경해 봅시다. 3. 다음 버튼은 전형적인 윈도우 XP 스타일의 버튼 컨트롤입니다. VirtualButton 예제의 코드를 수정하여 다음과 같은 모양을 하도록 수정해 봅시다. 4. 바탕 화면이나 윈도우 탐색기의 파일 목록처럼 뷰(View) 영역을 선택(드래그)하면 해당 영역을 회색으로 채우고 그 중앙에 자신의 이름을 출력하는 예제를 작성해 봅시다. 참고로 3, 4번은 난이도가 비교적 높으므로 시간을 갖고 천천히 코드를 작성하기 바랍니다.

102 Chapter 8 Bitmap & Handling of image file

103 One pixel ( 4/8/16/24/32 bits RGB Color)
Bitmap image 48 pixels 48 X bits bitmap 48 pixels One pixel ( 4/8/16/24/32 bits RGB Color)

104 BmpDisplayDemo 103 void CBmpDisplayDemoView::OnPaint( ) 103 {
103 { 104 CPaintDC dc(this); // device context for painting 105 106 CDC MemDC; 107 BITMAP bmpInfo; 108 // 화면 DC와 호환되는 메모리 DC를 생성한다. 109 MemDC.CreateCompatibleDC(&dc); 110 // 비트맵 리소스를 로딩한다. 111 CBitmap bmp; 112 CBitmap* pOldBmp = NULL; 113 bmp.LoadBitmap(IDB_Test_Image); 114 // 로딩된 비트맵의 정보를 알아본다. 115 bmp.GetBitmap(&bmpInfo); 116 // 메모리 DC에 선택한다. 117 pOldBmp = MemDC.SelectObject(&bmp); 118 // 메모리 DC에 들어 있는 비트맵을 화면 DC로 복사하여 출력한다. 119 dc.BitBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &MemDC,0, 0, SRCCOPY); 121 122 MemDC.SelectObject(pOldBmp); 122 }

105 CDC::BitBlt() Memoy DC = CreateCompatibleDC( Display DC ) Memory DC Display DC 250 pixels S (350, 200) 250 pixels T (200, 200) 300 pixels 300 pixels dc.BitBlt(200, 200, 250, 300, &MemDC, 350, 200, SRCCOPY);

106 CDC::StretchBlt() Memory DC Display DC 250 pixels S (350, 200)
&MemDC, 350, 200, 250, 300, SRCCOPY);

107 BmpDisplayDemo 117 118 dc.StretchBlt(20, 20,
bmpInfo.bmWidth * 2, bmpInfo.bmHeight * 2, &MemDC, , 0, bmpInfo.bmWidth, bmpInfo.bmHeight, SRCCOPY); // 래스터 연산 값 124 125 //※마지막 인자를 제외하면 StretchBlt( ) 함수와 거의 동일 126 dc.TransparentBlt(20, 100, bmpInfo.bmWidth * 2, bmpInfo.bmHeight * 2, &MemDC, , 0, bmpInfo.bmWidth, bmpInfo.bmHeight, RGB(0, 0, 0)); // 투명 처리될 색상의 RGB 값 132 133 MemDC.SelectObject(pOldBmp); 134 } 135

108 BmpDisplayDemo

109 BmpDisplayDemo 125 //※마지막 인자를 제외하면 StretchBlt( ) 함수와 거의 동일
126 BLENDFUNCTION bf; 127 bf.BlendOp = AC_SRC_OVER; 128 bf.BlendFlags = 0; 129 bf.SourceConstantAlpha = 50; // 0: 투명255: 불투명 130 bf.AlphaFormat = 0; 131 // 반투명 이미지를 출력한다. 132 dc.AlphaBlend(20, 100, 133 bmpInfo.bmWidth * 2, bmpInfo.bmHeight * 2, 134 &MemDC, , 0, 136 bmpInfo.bmWidth, bmpInfo.bmHeight, 137 bf); // BLENDFUNCTION 구조체

110 Src.Red * (SCA/255.0) + Dst.Red * (1.0 - (SCA/255.0))
CDC::AlphaBlend() Source bitmap image Destination pixel Source pixel 24bits RGB( 192, 192, 192) 24bits RGB( 192, 0, 0) SAC(SourceConstantAlpha) = 50 New destination pixel Src.Red * (SCA/255.0) + Dst.Red * (1.0 - (SCA/255.0)) R (192) 192 * (50 / 255.0) * (1.0 – ( 50 / 255.0)) G (154) 0 * (50 / 255.0) * (1.0 – ( 50 / 255.0)) B (154) 0 * (50 / 255.0) * (1.0 – ( 50 / 255.0))

111 CDC::AlphaBlend() Opaque 48 pixels 48 pixels Transparent Alpha blend

112 ImgOutDemo 105 106 void CImgOutDemoView::OnPaint( ) 107 {
107 { 108 CPaintDC dc(this); // device context for painting 109 110 // 로드할 이미지 파일의 경로 111 CString strImagePath = _T("IMG_0076.jpg"); 112 // 이미지 파일을 로드 113 CImage Image; 114 HRESULT hResult = Image.Load(strImagePath); 115 if(FAILED(hResult)) 116 { 117 CString strtmp = _T("ERROR: Failed to load "); 118 strtmp += strImagePath + _T("\n"); 119 TRACE(strtmp); 120 return; 121 } 122 123 // 화면 DC에 출력 124 Image.BitBlt(dc.m_hDC, 0, 0); 125 } 126

113 ImgOutDemo 103 104 // CimgOutDemoView 메시지 처리기 105
106 void CImgOutDemoView::OnPaint( ) 107 { 108 CPaintDC dc(this); // device context for painting 109 110 CImage Image; 111 // 비트맵 리소스를 로드하여 출력한다. 112 Image.LoadFromResource(AfxGetInstanceHandle( ), IDB_Image_Test); 113 Image.BitBlt(dc.m_hDC, 0, 0); 114 } 115

114 ImgOutDemo 105 106 void CImgOutDemoView::OnPaint( ) 107 {
107 { 108 CPaintDC dc(this); // device context for painting 109 110 CImage Image; 111 // 비트맵 리소스를 로드하여 DIB를 만든다. 112 Image.LoadFromResource(AfxGetInstanceHandle( ), IDB_Image_Test); 113 114 // 비트맵 이미지에 대한 DC를 생성한다. 115 CDC* pDC = CDC::FromHandle(Image.GetDC( )); 116 // 이 이미지 DC에 문자열을 출력한다. 117 pDC->SetBkMode(TRANSPARENT); 118 pDC->TextOut(200, 30, TEXT("CImage sample!")); 119 Image.ReleaseDC( ); 120 121 // 이미지를 화면 DC에 출력한다. 122 Image.BitBlt(dc.m_hDC, 0, 0); 123 // 화면 DC에 문자열을 출력한다. 124 // dc.SetBkMode(TRANSPARENT); 125 // dc.TextOut(200, 30, TEXT("CImage sample!")); 126 } 127

115 CImage::BitBlt() - BOOL BitBlt(HDC hDestDC, int xDest, int yDest, DWORD dwROP = SRCCOPY) const throw( ); - BOOL BitBlt(HDC hDestDC, const POINT& pointDest, DWORD dwROP = SRCCOPY ) const throw( ); - BOOL BitBlt(HDC hDestDC, int xDest, int yDest, int nDestWidth, int nDestHeight, int xSrc, int ySrc, DWORD dwROP = SRCCOPY) const throw( ); - BOOL BitBlt(HDC hDestDC, const RECT& rectDest, const POINT& pointSrc, DWORD dwROP = SRCCOPY ) const throw( );

116 Color space R C + Y M B G G B M Y C R RGB color CMYK color

117 SaveGrayDemo 300 300 200 300 200 300 Gray image

118 SaveGrayDemo 101 #endif //_DEBUG 102
103 inline void RGBtoGray(COLORREF& rgb) 104 { 105 BYTE byGray = (GetRValue(rgb) * 30 GetGValue(rgb) * 59 GetBValue(rgb) * 11) / 100; 108 109 rgb = RGB(byGray, byGray, byGray); 110 } 111

119 SaveGrayDemo 113 114 void CSaveGrayDemoView::OnLButtonDown(UINT nFlags, CPoint point) 115 { 116 // 바탕 화면 윈도우 객체에 대한 포인터를 얻음 117 CWnd* pWndDesktop = GetDesktopWindow( ); 118 CWindowDC ScrDC(pWndDesktop); // 바탕 화면 윈도우 DC 119 CClientDC dc(this); // 뷰 윈도우 DC 120 121 // 바탕 화면 크기 및 색상수와 동일한 비트맵 이미지를 만든다. 122 CImage Image; 123 Image.Create(300, 300, ScrDC.GetDeviceCaps(BITSPIXEL)); 124 125 // 이미지 DC와 화면 DC에 바탕 화면 윈도우 DC를 출력한다. 126 CDC* pDC = CDC::FromHandle(Image.GetDC( )); 127 pDC->BitBlt(0, 0, 300, 300, &ScrDC, 0, 0, SRCCOPY); 128 Image.ReleaseDC( ); 129

120 SaveGrayDemo 130 // 일부(200 * 200)를 흑백 이미지로 변환 131 COLORREF rgb;
130 // 일부(200 * 200)를 흑백 이미지로 변환 131 COLORREF rgb; 132 for(int x = 0; x < 200; x++) // 폭 133 { 134 for(int y = 0; y < 200; ++y) // 높이 135 { rgb = Image.GetPixel(x, y); // Gray RGB 값으로 변환 RGBtoGray(rgb); Image.SetPixel(x, y, rgb); 140 } 141 } 142 143 // 흑백으로 변환된 이미지를 화면 DC에 출력 144 Image.BitBlt(dc.m_hDC, 0, 0); 145 146 CView::OnLButtonDown(nFlags, point); 147 } 148

121 SaveGrayDemo 148 149 void CSaveGrayDemoView::OnRButtonDown(UINT nFlags, CPoint point) 150 { 151 // 바탕 화면 윈도우 객체에 대한 포인터를 얻음 152 CWnd* pWndDesktop = GetDesktopWindow( ); 153 CWindowDC ScrDC(pWndDesktop); // 바탕 화면 윈도우 DC 154 CClientDC dc(this); // 뷰 윈도우 DC 155 156 // 바탕 화면 윈도우의 크기를 알아낸다. 157 CRect Rect; 158 pWndDesktop->GetWindowRect(&Rect); 159 160 // 바탕 화면 크기 및 색상 수와 동일한 비트맵 이미지를 만든다. 161 CImage Image; 162 int cx = Rect.Width( ); // 바탕 화면 폭 163 int cy = Rect.Height( ); // 바탕 화면 높이 164 Image.Create(cx, cy, ScrDC.GetDeviceCaps(BITSPIXEL)); 165

122 SaveGrayDemo 166 // 이미지 DC와 화면 DC에 바탕 화면 윈도우 화면을 출력한다.
167 CDC* pDC = CDC::FromHandle(Image.GetDC( )); 168 pDC->BitBlt(0, 0, cx, cy, &ScrDC, 0, 0, SRCCOPY); 169 dc.BitBlt(0, 0, cx, cy, pDC, 0, 0, SRCCOPY); 170 Image.ReleaseDC( ); 171 172 // JPEG 형식으로 바탕 화면 이미지를 저장한다. 173 Image.Save(TEXT("Desktop.jpg"), Gdiplus::ImageFormatJPEG); 174 // 저장된 이미지를 뷰어를 실행하여 보여준다. 175 ::ShellExecute( NULL, TEXT("open"), TEXT("Desktop.jpg"), NULL, NULL, SW_SHOW); 178 179 CView::OnRButtonDown(nFlags, point); 180 } 181

123 실습안내 1. 새 프로젝트를 만들고 임의의 BMP 파일을 리소스로 등록한 후 클라이언트 뷰 윈도우에 출력하는 프로그램을 작성해 봅시다. 2. 1번에서 작성한 예제에 사진과 함께 자신의 이름을 출력하도록 예제를 수정해 봅시다. 단, 반드시 화면 DC에 직접 이름을 출력하지 말아야 합니다. 3. 임의의 두 이미지 파일을 열어서 한 화면에 겹쳐서 출력하는 예제를 작성해 봅시다. 단, 겹쳐 있더라도 두 이미지가 어느 정도 식별할 수 있도록 반투명하게 처리해야 합니다. 4. 두 이미지를 겹쳐서 출력하되 다음 그림과 같이 문자열 부분을 투명하게 처리하도록 해봅시다.

124 Chapter 9 Using Graphics Device Interface

125 TextRgn 103 void CTextRgnView::OnPaint() 104 {
104 { 105 CPaintDC dc(this); // device context for painting 106 // 임의의 두 사각형을 107 // 각기 다른 색상(붉은색과 회색)으로 칠한다. 108 CRect rectLeft = CRect(50, 50, 250, 150); 109 CRect rectRight = CRect(250, 50, 450, 150); 110 dc.FillSolidRect(&rectLeft, RGB(192, 0, 0)); 111 dc.FillSolidRect(&rectRight, RGB(192, 192, 192)); 112 113 // 앞서 만든 두 사각형을 별도의 영역으로 만든다. 114 CRgn rgnLeft, rgnRight; 115 rgnLeft.CreateRectRgnIndirect(rectLeft); 116 rgnRight.CreateRectRgnIndirect(rectRight); 117 118 / /DC의 폰트를 Arial Black(높이72)으로 바꾼다. 119 LOGFONT lf; 120 ::ZeroMemory(&lf, sizeof(lf)); 121 lf.lfHeight = 72; 122 wsprintf(lf.lfFaceName, _T("%s"), _T("Arial Black")); 123 CFont NewFont; 124 NewFont.CreateFontIndirect(&lf); 125 CFont* pOldFont = dc.SelectObject(&NewFont);

126 TextRgn 126 127 dc.SetBkMode(TRANSPARENT);
128 // dc.TextOut(60, 65, TEXT("TEST STRING")); 129 130 // 왼쪽 영역을 선택하여 문자열을 출력한다. 131 dc.SetTextColor(RGB(192, 192, 192)); 132 dc.SelectClipRgn(&rgnLeft); 133 dc.TextOut(60, 65, TEXT("TEST STRING")); 134 135 // 오른쪽 영역을 선택하여 문자열을 출력한다. 136 dc.SetTextColor(RGB(192, 0, 0)); 137 dc.SelectClipRgn(&rgnRight); 138 dc.TextOut(60, 65, TEXT("TEST STRING")); 139 140 dc.SelectObject(pOldFont); 141 } 142

127 TextRgn

128 Ignored area TextRgn A (50, 50) C (250, 50) rectLeft rectRight
B (250, 150) D (450, 150) rgnLeft rgnRight Ignored area

129 ImageRgn 118 119 void CImageRgnView::OnPaint( ) 120 {
120 { 121 CPaintDC dc(this); // device context for painting 122 // 반투명하게 배경 이미지를 출력 123 m_ImgSample.AlphaBlend(dc.m_hDC, 0, 0, 50); 124 // 원으로 된 윈도우 영역을 선택 125 CRgn Rgn; 126 Rgn.CreateEllipticRgn(m_rectVisible.left, m_rectVisible.top, m_rectVisible.right, m_rectVisible.bottom); 130 dc.SelectClipRgn(&Rgn); 131 // 투명하지 않은 이미지를 다시 한번 출력 132 m_ImgSample.BitBlt(dc.m_hDC, 0, 0); 133 } 134

130 FrameRgn 64 65 // 두 영역 및 조합된 영역을 주어진 좌표로 생성한다.
65 // 두 영역 및 조합된 영역을 주어진 좌표로 생성한다. 66 m_RgnRect1.CreateRectRgn(0, 0, 100, 100); 67 m_RgnRect2.CreateRectRgn(70, 70, 170, 170); 68 //※ 이 영역은 조합된 결과가 저장될 영역이므로 좌표는 의미가 없다. 69 m_RgnTotal.CreateRectRgn(0, 0, 0, 0); 70 71 // 두 영역을 조합한 새로운 영역을 만든다. 72 m_RgnTotal.CombineRgn(&m_RgnRect1, &m_RgnRect2, RGN_XOR); 73 // 조합된 영역이 CMainFrame 윈도우의 영역이 되도록 한다. 74 SetWindowRgn((HRGN)m_RgnTotal, TRUE); 75 76 return 0; 77 } 78

131 DrawModeDemo m_ptDragEnd m_ptBegin m_ptEnd m_ptDragBegin

132 DrawModeDemo 150 151 void CDrawModeDemoView::DrawInvertLine(CPoint point) 152 { 153 CClientDC dc(this); 154 // 두께가 40인 펜을 생성한다. 155 CPen NewPen(PS_SOLID, 40, RGB(0, 128, 0)); 156 CPen* pOldPen = (CPen*)dc.SelectObject(&NewPen); 157 // 그리기 모드를 반전 모드로 변경한다. 158 dc.SetROP2(R2_NOT); 159 160 // 기존에 반전된 선이 그려진 좌표에 한번 더 반전된 선을 그린다. 161 // 따라서 반전된 이미지가 원래대로 복원된다. 162 dc.MoveTo(m_ptDragBegin); 163 dc.LineTo(m_ptDragEnd); 164 165 m_ptDragEnd = point; 166 167 // 새 좌표로 반전된 선을 그려서 이미지를 반전시킨다. 168 dc.MoveTo(m_ptDragBegin); 169 dc.LineTo(m_ptDragEnd); 170 171 dc.SelectObject(pOldPen); 172 } 173

133 DrawModeDemo 195 void CDrawModeDemoView::OnRButtonDown(UINT nFlags, CPoint point) 196 { 197 / /바탕 화면 윈도우에 대한 포인터를 얻는다. 198 CWnd* pWnd = GetDesktopWindow( ); 199 CWindowDC dc(pWnd); 200 CPen NewPen(PS_SOLID, 10, RGB(0, 0, 0)); 201 CPen* pOldPen = (CPen*)dc.SelectObject(&NewPen); 202 203 int nPrevMode = dc.SetROP2(R2_NOTXORPEN); 204 205 // 바탕 화면 윈도우에 그리기를 수행한다. 206 for(int i = 0; i < 300; i += 3) 207 { 208 dc.Rectangle(20, 10, i, i); 209 ::Sleep(5); 210 dc.Rectangle(20, 10, i, i); 211 } 212 213 dc.SelectObject(pOldPen); 214 dc.SetROP2(nPrevMode); 215 pWnd->RedrawWindow( ); 216 217 CView::OnRButtonDown(nFlags, point); 218 }

134 DrawModeDemo

135 Map mode m_nZoomRate == 50 m_nZoomRate == 100 A (-300, -300) B(0, 0)

136 MapModeDemo 101 102 // CMapModeDemoView 메시지 처리기 103
104 void CMapModeDemoView::OnPaint( ) 105 { 106 CPaintDC dc(this); // device context for painting 107 108 dc.SetMapMode(MM_ISOTROPIC); 109 // 논리적인 화면 DC의 크기를 100*100으로 고정한다. 110 dc.SetWindowExt(100, 100); 111 // 뷰 포트의 크기를 변경한다. 112 dc.SetViewportExt(m_nZoomRate, m_nZoomRate); 113 // 픽셀 단위 좌표로 (300, 300)이 논리적 좌표 (0, 0)이 되도록 한다. 114 dc.SetViewportOrg(300, 300); 115

137 MapModeDemo 116 // X, Y축을 교차하는 선을 그린다.
117 CPen NewPen(PS_SOLID, 15, RGB(192, 0 , 0)); 118 CPen* pOldPen = dc.SelectObject(&NewPen); 119 dc.MoveTo(-100, 100); 120 dc.LineTo(100, -100); 121 dc.SelectObject(pOldPen); 122 123 // X, Y축에 대한 선을 그린다. 124 dc.MoveTo(-1024, 0); 125 dc.LineTo(1024, 0); 126 dc.MoveTo(0, -1024); 127 dc.LineTo(0, 1024); 128 129 // 비트맵을 (20, 20) 좌표에 출력한다. 130 CImage Image; 131 Image.LoadFromResource(AfxGetInstanceHandle( ), IDB_Sample); 132 Image.BitBlt(dc.m_hDC, 20, 20); 133 134 // (0, 0)을 기준으로 각 분면에 문자열을 출력한다. 135 dc.TextOut(20, 30, _T("Test1")); 136 dc.TextOut(-50, 30, _T("Test2")); 137 dc.TextOut(-50, -30, _T("Test3")); 138 dc.TextOut(20, -30, _T("Test4")); 139 }

138 Viewport m_nZoomRate = 300 SetWindowExt(100, 100) A (-300, -300)

139 PrintDemo 49 void CPrintDemoView::OnDraw(CDC* pDC) 50 {
50 { 51 CPrintDemoDoc* pDoc = GetDocument( ); 52 ASSERT_VALID(pDoc); 53 if (!pDoc) 54 return; 55 56 // 화면 정보 출력 57 CString strtmp = _T(""); strtmp.Format( _T("Pixel (HORZRES:%d VERTRES:%d), mm(HORZSIZE:%d VERTSIZE:%d)"), 59 pDC->GetDeviceCaps(HORZRES), // 픽셀 단위 수평 해상도 60 pDC->GetDeviceCaps(VERTRES), // 픽셀 단위 수직 해상도 61 pDC->GetDeviceCaps(HORZSIZE), // mm 단위 수평 길이 62 pDC->GetDeviceCaps(VERTSIZE)); // mm 단위 수직 길이 63 64 pDC->TextOut(10, 10, strtmp); 65 pDC->MoveTo(0, 130); 66 pDC->LineTo(pDC->GetDeviceCaps(HORZRES), 130); 67 }

140 PrintDemo

141 for(int i = 0; i < MaxPage; ++i)
PrintDemo OnPreparePrinting() SetMaxPage(3) Client View OnDraw() OnPaint() Document OnBeginPrinting() Page 1 for(int i = 0; i < MaxPage; ++i) OnDraw() OnPrint() Page 2 OnEndPrinting() Page 3 PRINT COMPLETE!

142 PrintDemo


Download ppt "Visual C download - Visual Studio Team System 2008 Team Suite (90-days Trial)"

Similar presentations


Ads by Google