Overview 화면출력 HCI Programming 2 (321190) 2007년가을학기 10/4/2007 박경신 윈도우의화면출력원리이해 GDI (Graphic Device Interface) DC (Device Context) CDC 클래스를이용한화면출력기법 다양한 DC 클래스 GDI 그래픽함수 각종 GDI 객체를생성하고사용하는방법 GDI Object (CPen, CBrush, CFont, 등등 ) Stock GDI Object 2 GDI 와디바이스컨텍스트 출력시스템을설계할때고려할사항 모니터, 비디오카드, 프린터등출력에사용되는주변장치가변경되는경우에도프로그램을수정할필요가없어야함 여러프로그램이화면을분할해서사용하므로하나의프로그램이출력을하는데있어서제약을가해야함 즉, 화면이나기타출력장치를직접접근 (Direct Access) 하거나독점해서사용하는것을운영체제차원에서막아야함 GDI 와디바이스컨텍스트 화면출력할때고려할사항 클라이언트영역에출력하려면화면에해당하는윈도우위치를알아야함 화면에여러개의윈도우가있을때출력결과가다른윈도우의영역을침범하지않아야함 현재출력할화면이다른윈도우에가려졌다면출력을할수없어야함 Device Context (DC) 사용 3 4
GDI 와디바이스컨텍스트 GDI (Graphics Device Interface) 운영체제의하위시스템중하나로 DLL 로존재 (GDI32.DLL) 응용프로그램의요청을받아서실제출력장치에대한출력담당 응용프로그램에대한독립적인그래픽동작수행 장치에의존하지않으므로장치가변경되더라도프로그램의수정이불필요 멀티태스킹을위한분할처리를하는운영체제에서하나의응용프로그램이출력장치를독점하지못하도록운영체제를통하여장치에간접접근 응용프로그램 장치독립적 GDI 장치의존적 출력장치 ( 화면, 프린터등 ) 5 GDI 와디바이스컨텍스트 DC (Device Context) GDI 가생성하고관리하는데이터구조체 DC 를통해멀티태스킹 ( 멀티스레딩 ) GUI 환경에서발생할수있는여러상황을고려하여출력가능 예, 출력영역, 원점정보, 그래픽정보 ( 글꼴, 펜, 브러시 ) 기능 응용프로그램의출력에대한허가를얻고, 그려지는영역을결정하는역할 윈도우의클리핑영역 ( 즉, 응용프로그램의출력허용영역 ) 관리 그래픽정보관리 ( 펜, 브러시, 글꼴, 비트맵, 팔레트 ) DC 를얻고나면, 반드시작업완료시해제필요 6 GDI 와디바이스컨텍스트 윈도우응용프로그램의출력과정 출력하기전에윈도우운영체제에게 DC 요청 DC요청 운영체제의 GDI는내부적으로 DC를만든후 DC 핸들 ( 즉, HDC 타입, 32비트포인터 ) 을해당응용프로그램에게넘겨줌 HDC반환 응용프로그램에서는받은 DC 핸들을출력관련 API 함수를호출할때사용하고, 출력관련 API 함수를호출하면 GDI가이를처리 API(HDC,..) GDI는해당응용프로그램이넘겨준 DC 핸들로내부데이터를참조하여다양한상황을고려해서출력출력응용프로그램 Invalid Region ( 무효영역 ) 메모장이그림판의일부를가리고있다가가려진부분이드러나는경우 ( 두가지방법이존재 ) 운영체제가가려진부분을메모리에임시저장해두었다가다시화면을복구 운영체제가화면복구를직접담당하는것 화면에다시그려야할부분을프로그램에알려주면프로그램이알아서다시그림 화면복구를각응용프로그램이담당하고운영체제는복구해야할시점과복구할영역정보전달하는것 디바이스컨텍스트 GDI 장치드라이버 출력장치 ( 화면, 프린터등 ) OS 7 8
Invalid Region ( 무효영역 ) 화면을다시그려야하는상황 무효영역을다시그리기위해서해당응용프로그램으로 WM_PAINT 메시지를보내어처리될수있도록함 WM_PAINT 메시지를받으면 ::BeginPaint() 호출 다시그려야하는영역 ( 즉, 무효영역 ) 에대한정보획득 이영역에출력할수있는 HDC 획득 화면출력이끝나면 ::EndPaint() 호출 WM_PAINT 메시지발생상황 윈도우가생성될때 윈도우의크기가변경될때 최소화또는최대화되었을때 다른윈도우가가렸다가드러날때 Invalid Region ( 무효영역 ) 무효영역생성 응용프로그램내에서강제적으로 WM_PAINT 메시지를발생시키기위한함수배경을지울것인지? // 전체영역무효화 void CWnd::Invalidate (BOOL berase = TRUE); // 일부사각영역만무효화 void CWnd::InvalidateRect (LPCRECT lprect, BOOL berase = TRUE); 무효화할영역의좌표 9 10 Invalid Region ( 무효영역 ) WM_PAINT 메시지처리 출력할내용이없어도반드시 HelloSDK BeginPaint 를호출할것. 그렇치않으면 OS가계속무효영역이존재하는것으로 case WM_PAINT: 간주함 hdc = BeginPaint(hwnd, &ps); // DC를얻음 TextOut(hdc, 100, 100, str, lstrlen(str)); // 출력 EndPaint(hwnd, &ps); // DC 반환 return 0; HelloMFC DC 를얻고반환하는작업이 CDC 클래스의생성자와소멸자에서수행 출력방법비교 SDK 윈도우운영체제에게 DC를요청 운영체제로부터받은 DC 핸들을사용하여출력 운영체제에게 DC 사용이끝났음을알림 MFC DC 객체생성 DC 객체의멤버함수를호출하여출력 void CMainFrame::OnPaint() { char *msg = "Hello, MFC"; CPaintDC dc(this); dc.textout(100, 100, msg); MFC 에서는 WM_PAINT 이벤트가발생하면 OnPaint() 가수행됨. 내부적으로 BeginPaint/EndPaint 호출 11 MFC 의 CDC 파생클래스를이용하면 DC 를편리하게다룰수있음 12
다양한 DC 클래스 다양한 DC 클래스 클래스계층도 클래스이름 CPaintDC 용도 클라이언트영역에출력할때 (WM_PAINT 메시지핸들러에서만사용 ) CClientDC 클라이언트영역에출력할때 (WM_PAINT 메시지핸들러를제외한다른모든곳에서사용 ) CWindowDC 윈도우의전체영역 ( 클라이언트영역 + 비클라이언트영역 ) 에출력할때 CMetaFileDC 메타파일 (Metafile) 에출력할때 13 14 CPaintDC 클래스 WM_PAINT 메시지가발생했을때다시그려져야할영역 (Invalid Rectangle) 에대한 DC 관리 WM_PAINT 메시지핸들러인 OnPaint() 함수에서사용 내부적으로 BeginPaint() 함수를호출하고소멸자는 EndPaint() 함수를호출 CPaintDC 사용예 void CChildView::OnPaint() { CPaintDC dc(this); // View 의 client 영역에출력할수있도록 DC 개체생성 // 출력작업... CPaintDC 클래스 CPaintDC 는 WM_PAINT 메시지가발생할때마다호출 윈도우크기가변경하는등의상황에서도항상표시됨 (100, 100) (300, 300) void CChildView::OnPaint() { CPaintDC dc(this); dc.rectangle(100, 100, 300, 300); 15 16
CClientDC 클래스 클라이언트영역만을표시하는 DC 관리 일시적으로윈도우의클라이언트영역에서그래픽개체를사용할경우에이용 생성자에서 GetDC 함수를호출하여 DC 를얻고, 소멸자에서 ReleaseDC 함수를호출하여 DC 를해제 생성시출력대상이되는윈도우의핸들값을인자로사용 CClientDC 사용예 void CChildView::OnLButtonDown(UINT nflags, CPoint point) { CClientDC dc(this); // 현재 View 객체의클라이언트영역의 DC생성 // 출력작업... 17 CClientDC 클래스 화면에왼쪽마우스버튼을누르면그점을중심으로반지름이 30 인원이그려지는예 void CChildView::OnLButtonDown(UINT nflags, CPoint point) { CClientDC dc(this); dc.ellipse(point.x-30, point.y-30, point.x+30, point.y+30); CWnd::OnLButtonDown(nFlags, point) 18 CWindowDC 클래스 윈도우전체영역 ( 비클라이언트 + 클라이언트 ) 에그래픽요소를출력하고자할때사용 CWindowDC 사용방법 CPaintDC, CClientDC 클래스와동일 원점위치 (0, 0) CWindowDC (0, 0) CPaintDC, CClientDC 19 CMetaFileDC 클래스 메타파일 (Metafile) GDI 명령어를저장할수있는파일 CMetaFileDC 사용방법 CMetaFileDC 객체를만든후 CMetaFileDC::Create() 호출 메타파일객체를일반적인디바이스컨텍스트객체로간주하고출력관련멤버함수를호출 CMetaFileDC::Close() 를호출하면윈도우운영체제가내부적으로메타파일을만든후메타파일핸들 (HMETAFILE 타입 ) 을리턴 CDC::PlayMetaFile() 로메타파일을실행 CMetaFileDC mdc; // 메타파일 DC 객체 ( 순수한 C++ 객체 ) 생성 mdc.create(); // 메타파일 DC( 운영체제가인식하는 ) 생성 mdc.ellipse(0, 50, 50, 100); // 메타파일에출력 mdc.rectangle(50, 50, 100, 100); // 메타파일에출력 HMETAFILE m_hmf = mdc.close(); // 메타파일핸들저장.. CClientDC dc(this); 20 dc.playmetafile(m_hmf); // 메타파일실행
CDC 그래픽함수 CDC 그래픽함수 점찍기이름 GetPixel() SetPixel() SetPixelV() 기능 화면의특정위치에해당하는점의색을얻는다. 화면의특정위치에원하는색의점을찍으며원래의점의색을리턴한다. SetPixel 과기능은동일하지만 SetPixel 함수와달리원래의점의색을리턴하지않으므로속도가더빠르다. 선그리기 이름 MoveTo() LineTo() 한번의호출로선을그리는함수는제공하지않으며다음두단계를거쳐야함 기능 현재위치를옮긴다. 현재위치로부터특정위치까지선을그린후현재위치를갱신한다. 21 dc.moveto(100, 100); dc.lineto(200, 200); (100, 100) (200, 200) 22 CDC 그래픽함수 도형그리기 CDC 그래픽함수 텍스트출력함수 이름 기능 이름 기능 Rectangle() 사각형을그린다. TextOut() 특정위치에문자열을출력한다. Ellipse() 사각형에내접하는타원을그린다. DrawText() 사각형을기준으로문자열을출력한다. Polyline() 다각선을그린다. SetTextColor() 문자의색을바꾼다. Polygon() 다각형을그린다. SetBkColor() 문자의배경색을바꾼다. PolyBezier() 베지어곡선을그린다. SetTextAlign() 기준위치에대한문자열의정렬방식을정한다. 23 24
void CGDITestView::OnDraw(CDC* pdc) { CString str; int cx, cy, x1, x2, y1, y2; CRect rect; GetClientRect(&rect); // 클라이언트영역의크기얻기 cx = rect.width() / 2; cy = rect.height() / 2; // 클라이언트영역중간위치얻기 str.format(" 화면중간위치 (%d:%d)", cx,cy); pdc->textout(0, 0, str); // 문자열출력 // 원그리기 ( 클라이언트영역에내접하는원 ) pdc->ellipse(rect); // 문자열출력 pdc->drawtext(str, rect, DT_CENTER DT_VCENTER DT_SINGLELINE); // 선그리기, 화면높이의중간위치에서화면폭의중간위치까지선그리기 pdc->moveto(0, cy); pdc->lineto (cx, cy); // 다각형그리기, 꼭지점의좌표값 3개로삼각형그리기 CPoint ptdata1[3]={cpoint(100,100), CPoint(150,50), CPoint(200,100); pdc->polygon(ptdata1, 3); // 베지어곡선그리기 CPoint ptdata2[4]={cpoint(100,200), CPoint(150,100), CPoint(200,300),CPoint(250,200); pdc->polybezier(ptdata2, 4); 25 매핑모드 (Mapping Mode) 주어진좌표가화면상실제어디에해당하는지결정하는방법 논리좌표 ( 논리단위 ) GDI 그래픽함수들이사용하는모든좌표 CDC 에서사용하는윈도우좌표 물리좌표 ( 장치단위 ) 실제화면에출력되는좌표 ( 픽셀단위 ) CWnd 에서사용하는좌표 뷰포트 (viewport) : 물리좌표가사용되는영역 매핑모드관련함수 SetMapMode(int fnmapmode ); int GetMapMode(); 사용자정의매핑모드를이용할경우범위지정함수 SetWindowExt() : 논리단위의범위지정함수 SetViewPortExt() : 장치단위의범위지정함수 26 매핑모드종류 매핑모드단위 x 축 y 축 MM_TEXT 1 픽셀 (1:1 로 mapping) +x +y MM_LOMETRIC 0.1 mm +x -y MM_HIMETRIC 0.01 mm ( 장치의해상도를 +x -y MM_LOENGLISH 0.01 인치 고려하여 +x -y 논리단위를 MM_HIENGLISH 0.001 인치 장치단위로매핑 ) +x -y MM_TWIPS 1/1440 인치 +x -y MM_ISOTROPIC 사용자정의 ( 가로, 세로길이동일 ) 사용자정의 사용자정의 MM_ANISOTROPIC 사용자정의사용자정의사용자정의 물리좌표와원점 스크린좌표와클라이언트좌표스크린좌표의원점클라이언트좌표의원점 SetMapMode(value) 27 28
좌표변환 DC 의속성함수 좌표변환함수 논리좌표 <-> 장치좌표 void LPtoDP(LPPOINT lppoints, int ncount = 1); void DPtoLP(LPPOINTlpPoints, intncount= 1); 클라이언트좌표 <-> 스크린좌표 장치좌표 void ScreenToClient(LPPOINT lppoint); void ClientToScreen(LPPOINT lppoint); 클라이언트좌표 CWnd::ScreenToClient CWnd:: ClientToScreen 스크린좌표 CDC::DPtoLP CDC::LPtoDP 논리좌표 속성 초기값 텍스트색상 검정색 배경색상 흰색 배경모드 OPAQUE 매핑모드 MM_TEXT 그리기모드 R2_COPYPEN 현재위치 (0, 0) 펜 BLACK_PEN 브러시 WHITE_BRUSH 폰트 SYSTEM_FONT 비트맵 없음 팔레트 없음 영역 없음 속성을얻는함수 GetTextColor() GetBkColor() GetBkMode() GetMapMode() GetROP2() GetCurrentPosition() SelectPalette() 속성을변경하는함수 SetTextColor() SetBkColor() SetBkMode() SetMapMode() SetROP2() MoveTo() SelectPalette() 29 이속성에따라 GDI 출력함수의결과가달라짐 30 그리기모드 (DrawMode) 펜, 브러시에적용되는연산 - SetROP2(int ndrawmode) 그림을그릴때사용하는색상 (S) 와스크린원래색상 (D) 의혼합방법 그리기모드 연산 그리기모드 연산 R2_NOP D = D R2_NOT D = ~D R2_BLACK D = BLACK R2_WHITE D = WHITE R2_COPYPEN D = S R2_NOTCOPYPEN D = ~S R2_MERGEPENNOT D = ~D S R2_MASKPENNOT D = ~D & S R2_MERGENOTPEN D = ~S D R2_MASKNOTPEN D = ~S & D R2_MERGEPEN D = D S R2_NOTMERGEPEN D = ~(D S) R2_MASKPEN D = D & S R2_NOTMASKPEN D = ~(D & S) R2_XORPEN D = S ^ D R2_NOTXORPEN D = ~(S ^ D) 바탕색복원에이용 ( 같은그림을두번그리기 ) S (Source) //Raster Operation (DrawMode) 예 CClientDC dc(this); CColorDialog dlgcolor; // 색상다이얼로그의인스턴스생성 COLORREF pencolor; // 색상다이얼로그에서색상를선택하고확인을누르면 if (dlgcolor.domodal() == IDOK) { pencolor = dlgcolor.getcolor(); // 선택한색상값을얻어PenColor에설정 CPen pen, *oldpen; pen.createpen(ps_solid, 2, pencolor); // PEN 객체생성 CPen(PenColor); oldpen = dc.selectobject(&pen); // PEN 객체등록 dc.setrop2(r2_xorpen); // XORPEN 으로설정 ( 보색으로처리 ) dc.rectangle(100, 100, 150,150); dc.setrop2(r2_black); // BLACK으로설정 dc.rectangle(150, 150, 200, 200); dc.setrop2(r2_copypen); // COPYPEN 으로설정 dc.rectangle(200, 200, 250, 250); dc.selectobject(oldpen); // PEN 객체복원 D 31(Destination) White color : RGB(255,255,255) Black color : RGB(0,0,0) 32
배경모드 (BackgroundMode) 배경에적용되는연산 - SetBkMode(int nbkmode) OPAQUE : 현재배경색 Text 를출력하거나도형을그릴때현재 DC 에설정된배경색으로칠함 TRANSPARENT : 투명배경색 Text 를출력하거나도형을그릴때배경을그대로둠 CClientDC dc(this); dc.selectstockobject(ltgray_brush); // 배경을밝은회색으로칠한다. Rect rect; GetClientRect(&rect); dc.rectangle(&rect); // 클라이언트크기의사각형을출력. dc.setbkmode(transparent); // 투명배경으로설정 dc.textout(100, 100, CString( 투명배경문자모드 ")); // 투명배경인문자열출력 GDI 객체 GDI 객체 GDI에서출력할때사용하는도구 종류 GDI 객체용도클래스이름 펜 선을그릴때 CPen 브러시 면의내부를채울때 CBrush 폰트 문자를출력할때 CFont 비트맵 픽셀의집합으로이루어진그림을다룰때 CBitmap 팔레트 출력될색의집합을다룰때 CPalette 영역 다양한형태의면을정의할때 CRgn dc.setbkmode(opaque); // 기존배경색으로복원 33 dc.textout(100, 150, CString(" 불투명배경문자모드 ")); // 초기배경색으로문자열출력 34 GDI 객체 GDI 객체 클래스계층도 MFC 는 GDI 객체를다룰수있도록 7 개의클래스를제공함. CGdiObject 는이들클래스의 Base Class 35 GDI 객체생성 GDI객체를위한각클래스의생성자나 Create함수이용 CreatePen(), CreateSolidBrush(),CreateBitmap(), CreatePalette( ), CreateFont(), CreatePolygonRgn() 객체를 Device Context에등록 CDC:: 함수이용 기존설정된객체는반환되어포인터로저장 poldgdiobj = dc.selectobject(&newgdiobj) GDI 함수로출력작업 dc.rectangle(..) Device Context에이전GDI객체로환원 dc.selectobject(poldgdiobj) 객체삭제 DeleteObject() 함수로강제삭제 36 GDI 객체가소멸될때소멸자에의한자동삭제
GDI 객체 CDC class의 SelectObject( ) - Afxwin.h 파일참조 public: virtual CGdiObject* SelectStockObject(int nindex); CPen* SelectObject(CPen* ppen); CBrush* SelectObject(CBrush* pbrush); virtual CFont* SelectObject(CFont* pfont); CBitmap* SelectObject(CBitmap* pbitmap); int SelectObject(CRgn* prgn); CGdiObject* SelectObject(CGdiObject* pobject); GDI 객체사용예 CClientDC dc(this); //CClientDC 생성 CPen mypen, *poldpen; // 새로운펜과기존의펜을저장할변수 mypen.createpen(ps_dot, 1, RGB(0,0,255)); // 파란점선을갖는펜객체를생성 poldpen = dc.selectobject(&mypen); // DC에새로운펜을설정 dc.rectangle(..); // 출력작업 ( 사각형이파란점선으로그려짐 ) dc.selectobject(poldpen); // DC 에기존의펜을복원 37 38 펜 선이나영역의경계선을그릴때사용 선의두께, 색상, 선의스타일설정 생성방법 생성자 ( 방법1) 또는 CreatePen ( 방법2) 이용 // 방법 1 CPen pen(ps_solid, 2, RGB(255, 0, 0)); // 방법2 CPen pen; pen.createpen(ps_solid, 2, RGB (255, 0, 0)); 펜스타일 펜 사용예 1 CPaintDC dc(this); // DC 생성 CPen pen(ps_solid, 1, RGB(0, 0, 255)); // 펜객체생성 CPen *poldpen = dc.selectobject(&pen); // DC에새로운펜객체설정 dc.rectangle(100, 100, 200, 200); // 사각형그리기 dc.selectobject(poldpen); // 이전펜객체복원 사용예 2 실제로는이전펜의주소를저장하고마지막으로펜을원상복구하는부분을생략해도무방함 CPaintDC dc(this); // DC 생성 CPen pen(ps_solid, 1, RGB(0, 0, 255)); // 펜객체생성 dc.selectobject(&pen); // 펜선택 dc.rectangle(100, 100, 200, 200); // 사각형그리기 39 40
브러시 영역의내부를채울때사용 영역에채워질색, 패턴등을설정 종류 브러시종류 솔리드 (Solid, 속이채워짐 ) 해치 (Hatch, 교차된평행선무늬 ) 패턴 (Pattern, 비트맵의반복무늬 ) 생성예 CBrush brush(rgb(255, 0, 0)); CreateSolidBrush(RGB(255, 0, 0)); CBrush brush(hs_diagcross, RGB(255, 0, 0)); CreateHatchBrush(HS_DIAGCROSS, RGB(255, 0, 0)); CBitmap bitmap; bitmap.loadbitmap(idb_bitmap1); CBrush brush(&bitmap); 브러시 HatchBrush style 해치브러시의스타일 HS_BDIAGONAL HS_CROSS HS_DIAGCROSS HS_FDIAGONAL HS_HORIZONTAL HS_VERTICAL 내용오른쪽에서왼쪽으로 45도내려가는빗금십자가형태의빗금 X자형태의빗금왼쪽에서오른쪽으로 45도내려가는빗금 수평으로빗금 수직으로빗금 모양 41 42 브러시 사용예 1 CPaintDC dc(this); CBrush brush(rgb(255, 0, 0)); CBrush *poldbrush = dc.selectobject(&brush); dc.ellipse(100, 100, 200, 200); dc.selectobject(poldbrush); 사용예 2 펜의경우와마찬가지로실제로는이전브러시의주소를저장하고마지막으로다시브러시를원상복구하는부분을생략해도무방함 CPaintDC dc(this); CBrush brush(rgb(255, 0, 0)); dc.selectobject(&brush); dc.ellipse(100, 100, 200, 200); 43 폰트 (Font) 문자출력을위한글자의모양, 크기를설정 Font 의종류 논리적인폰트 : 이상적인폰트에대한표현으로실제로존재하는유사한폰트를얻기위해사용 물리적인폰트 : 실제로시스템에설치되어있는폰트로실제화면에나타나는폰트 폰트를사용하는방법 폰트를출력하기위해서는원하는폰트에대해논리적인폰트를 LOGFONT타입으로기술하여생성하고 DC에폰트를설정 윈도우 GDI 의폰트맵퍼가시스템에설치되어있는폰트들중에가장가까운물리적인폰트를찾아출력 44
Logical Font 구조체 Font( 글꼴 ) 에대한정보를가지는데이터구조 typedef struct taglogfont { /* lf */ LONG lfheight; // 문자높이 LONG lfwidth; // 문자폭 LONG lfescapement; // 문자방향 LONG lforientation; // 문자회전각도 LONG lfweight; // 문자굵기 BYTE lfitalic; // 기울임꼴 BYTE lfunderline; // 밑줄 BYTE lfstrikeout; // 취소선 BYTE lfcharset; // 문자세트 BYTE lfoutprecision; // output precision BYTE lfclipprecision; // clipping precision BYTE lfquality; // output quality BYTE lfpitchandfamily; // 문자간격과글꼴패밀리 TCHAR lffacename[lf_facesize]; // 글자체이름 LOGFONT; 45 CFont 클래스 논리적폰트를생성하고관리하는클래스 새로운글꼴생성메소드 CFont::CreatePointFont(..) 폰트의크기 ( 포인트단위 ) 와이름만으로폰트를생성, 나머지는기본값으로설정 CFont::CreateFont( ) LOGFONT 구조체가가지는모든값들을직접매개변수로사용하여폰트생성 CFont::CreateFontIndirect( ) LOGFONT 구조체포인터를매개변수로사용하여폰트생성 CFont font; // CFont 객체생성 font.createfont(...); // argument가 16개로너무복잡 // font.createfontindirect(...); // CFont 객체에대해 Create*() 함수호출 // font.createpointfont(400, Arial); // 400/10 포인트크기 Arial 폰트 // font.createpointfontindirect(...); 46 Font 공통다이얼로그박스 TEXTMATRIC 구조체 Font 공통다이얼로그박스의 LOGFONT 구조체에저장된값으로논리적폰트객체생성 public: LOGFONT m_logfont; //logical font 구조체변수선언. // 폰트공통다이얼로그박스로부터 logical font 구조체얻어옴 CFontDialog dlg(&m_logfont); if (dlg.domodal() == IDOK) { dlg.getcurrentfont(&m_logfont); // 폰트공통다이얼로그박스에서선택된논리적폰트정보얻기 str.format(" 글자체 =%s, 크기 =%d", dlg.getfacename(), dlg.getsize()/10); // 글자체와크기 ( 포인트단위의 10배로얻어짐 ) 출력 47 typedef struct tagtextmetric { /* tm */ int tmheight; int tmascent; int tmdescent; int tminternalleading; int tmexternalleading; int tmavecharwidth; int tmmaxcharwidth; int tmweight; BYTE tmitalic; BYTE tmunderlined; BYTE tmstruckout; BYTE tmfirstchar; BYTE tmlastchar; BYTE tmdefaultchar; BYTE tmbreakchar; BYTE tmpitchandfamily; BYTE tmcharset; int tmoverhang; int tmdigitizedaspectx; int tmdigitizedaspecty; TEXTMETRIC; DC 에선택된논리적폰트와관련된물리적폰트의특징을나타냄 CDC::GetTextMatrics(LPTE XTMETRIC lpmetrics ) 으로얻어옴 48
void CGDITestView::OnGDITestFont() { CFont newfont, *poldfont=null; TEXTMETRIC tm; CString str; CClientDC dc(this); // 폰트공통다이얼로그박스로부터 logical font 구조체얻어옴 CFontDialog dlg(&m_logfont); if (dlg.domodal() == IDOK) { dlg.getcurrentfont(&m_logfont); str.format(" 글자체 =%s, 크기 =%d", dlg.getfacename(), dlg.getsize()/10); // logical font 구조체를이용한폰트객체생성 if (newfont.createfontindirect(&m_logfont)) { poldfont = dc.selectobject(&newfont); //DC에새로운폰트객체설정 dc.textout(10,50, str); dc.gettextmetrics(&tm); //DC의폰트정보얻어옴 str.format(" 글자크기 ( 폭 =%d, 높이 =%d)", tm.tmavecharwidth, tm.tmheight); dc.textout(10,100, str); newfont.deleteobject(); newfont.createpointfont(200, "Arial"); // 크기와글꼴만으로간단하게폰트생성, 20point dc.selectobject(&newfont); str.format(" PointFont(200, Arial)"); dc.textout(10, 150, str); if (poldfont) 49 dc.selectobject(poldfont); // 원래 font 복원 Stock GDI Object ( 내장객체 ) 이름 BLACK_PEN WHITE_PEN NULL_PEN BLACK_BRUSH DKGRAY_BRUSH GRAY_BRUSH LTGRAY_BRUSH HOLLOW_BRUSH 또는 NULL_BRUSH SYSTEM_FONT 용도 폭이 1 픽셀인검정색펜 폭이 1 픽셀인흰색펜 투명펜 검정색브러시 어두운회색브러시 회색브러시 밝은회색브러시투명브러시 윈도우운영체제가사용하는폰트예 ) 메뉴, 대화상자,... 윈도우운영체제가미리만들어서제공하는 GDI 객체 내장객체는생성과정을생략하고 CDC::SelectStockObject() 50 함수를사용하여 DC에선택한다. Stock GDI Object ( 내장객체 ) 사용예 CClientDC dc(this); // DC 생성 CBrush* pold; pold = (CBrush*)dc.SelectStockObject(GRAY_BRUSH); // 내장된회색브러시를선택 // 실제출력작업 dc.selectobject(pold); 비트맵 복잡한그림을처리할때많이사용 비트맵정보 int CBitmap::GetBitmap (BITMAP* pbitmap); typedef struct tagbitmap { int bmtype; int bmwidth; // 비트맵의폭 ( 픽셀단위 ) int bmheight; // 비트맵의높이 ( 픽셀단위 ) int bmwidthbytes; BYTE bmplanes; BYTE bmbitspixel; LPVOID bmbits; BITMAP; 51 52
비트맵 비트맵정보출력 LoadBitmap(UINT nidresource) 리소스 ID 로비트맵얻기 GetBitmap(BITMAP* pbitmap) 비트맵정보구조체얻기 CBitmap bitmap; bitmap.loadbitmap(idb_bitmap1); BITMAP bmpinfo; bitmap.getbitmap(&bmpinfo); TRACE(" 가로 = %d, 세로 = %d\n", bmpinfo.bmwidth, bmpinfo.bmheight); 비트맵 비트맵은곧바로화면에출력하는함수를제공하지않음 비트맵출력절차 CBitmap::LoadBitmap() 함수를이용하여비트맵리소스로부터읽어오기 CDC::CreateCompatibleDC() 함수를이용하여메모리 DC 를생성 CDC:: 함수를이용하여비트맵을메모리 DC 에선택 CDC::BitBlt() 또는 CDC::StretchBlt() 함수를이용하여화면에출력 CDC:: 함수를이용하여 DC 를복원 53 54 Memory Device Context 메모리의일부를마치화면처럼다룰수있도록운영체제에서제공하는개념 응용프로그램에서는메모리 DC에비트맵을선택후실제물리적인출력장치로내보냄 BitBlt 또는 StretchBlt 함수에서 Blt는 Block Transfer의약자로서이는비트맵데이터를메모리에서메모리로고속전송한다는의미 비트맵 비트맵출력함수 BitBlt 메모리 DC 에서화면 DC 로비트맵블록을그대로전송하는함수 BOOL BitBlt (int x, int y, int nwidth, int nheight, CDC* psrcdc, int xsrc, int ysrc, DWORD dwrop) ; ysrc xsrc x y nwidth nheight psrcdc ( 메모리디바이스컨텍스트 ) 55 ( 스크린디바이스컨텍스트 ) 56
비트맵 비트맵출력함수 StretchBlt 비트맵을확대하거나축소하여비트블럭을전송 BOOL StretchBlt (int x, int y, int nwidth, int nheight, CDC* psrcdc, int xsrc, int ysrc, int nsrcwidth, int nsrcheight, DWORD dwrop) ; x y nwidth nheight ( 스크린디바이스컨텍스트 ) xsrc ysrc nsrcwidth nsrcheight psrcdc ( 메모리디바이스컨텍스트 ) dwrop : 비트맵래스터오퍼레이션 SRCCOPY : 배경그림무시하고비트맵출력 SRCAND : 배경그림과 AND 57 연산 SRCPAINT : 배경그림과 OR 연산 //Bitmap 화면출력예 CClientDC dc(this); // 비트맵리소스를로드한후크기정보를얻는다. CBitmap bitmap; bitmap.loadbitmap(idb_bitmap1); // 비트맵리소스읽어오기 BITMAP bmpinfo; bitmap.getbitmap(&bmpinfo); // 비트맵정보얻기 ( 크기등 ) // 메모리디바이스컨텍스트를만든후비트맵을선택해넣는다. CDC dcmem; dcmem.createcompatibledc(&dc); dcmem.selectobject(&bitmap); // 비트맵을화면에출력한다. dc.bitblt(10, 10, bmpinfo.bmwidth, bmpinfo.bmheight, &dcmem, 0, 0, SRCCOPY); // 비트맵의원래크기유지 dc.stretchblt(100, 100, bmpinfo.bmwidth*4, bmpinfo.bmheight*6, &dcmem, 0, 0, bmpinfo.bmwidth, bmpinfo.bmheight, SRCCOPY); // 비트맵의크기를변형 58