태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.


뜬금없지만 DrawText()의 원형을 보자.

TextOut()함수와 더불어 자주 문자열을 출력하는 함수로 쓰인다.

이 함수는 다양한 옵션을 정하여 문자열을 출력해주는 함수이다.

========================================================

virtual int DrawText(LPCTSTR lpszString, int nCount, LPRECT lpRect, UINT nFormat);

int DrawText(const CString& str, LPRECT lpRect, UINT nFormat);

========================================================

첫번쨰는 TextOut() 함수처럼 출력할 문자열의 길이를 명시하지만

일반적으로는 두번째 원형을 사용한다고 한다.

str인자는 출력할 문자열이며, lpRect인자는 문자열을 출력할 대상 사각형의 좌표가 된다.

이전 글의 예제에는 이 사각형의 좌표가 m_BtnRect(CRect)인 경우가 있었다. 

nFormat 인자에는 출력의 옵션이 들어가게 된다. 이 옵션값에 따라 출력할때의 모양이 달라지게 되며 이것이

가장 이 함수에서 중요하다고 할 수 있다.



프로젝트명을 DrawTextDemo로 하고 SDI문서를 평소의 속성대로 정해준 후

OnPaint() 핸들러 함수를 만들고 다음과 같이 코딩을 해보자.

///////////////////////////////////////////////

void CDrawTextDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.

CRect Rect(50,50,250,100);
dc.FillSolidRect(&Rect, RGB(192,192,192));

CFont Font;
LOGFONT lf;
::ZeroMemory(&lf, sizeof(lf));
lf.lfHeight = 24;
wsprintf(lf.lfFaceName, TEXT("%s"), TEXT("Arial"));

Font.CreateFontIndirect(&lf);
CFont* pOldFont = dc.SelectObject(&Font);

dc.SetTextColor(RGB(192,0,0));//문자열의 색상을 붉은색으로 바꾼다.

dc.DrawText(TEXT("Test button"), &Rect, DT_CENTER | DT_SINGLELINE | DT_VCENTER);

dc.SelectObject(pOldFont);

}
 ////////////////////////////////////////

이 코드에서 잘 봐야하는점은 역시 DrawText 쪽이다. 속성이 3가지 주어져 있음을 알 수 있다.

첫번째 센터 는 중앙정렬, 두번째는 제어 문자 \n을 처리해주는 것, 세번째는 세로로도 중앙정렬을 하라는 속성이다.

출력 화면은 다음과 같다.



세로로 중앙정렬을 하여 출력할 것이라면 반드시 한 행만 출력해야 한다고 한다.

다음으로는 적용 가능한 다른 옵션에 따른 출력방식이다.

DT_BOTTOM | DT_SINGLELINE | DT_RIGHT 조합인 경우에는 다음과 같으며

DT_BOTTOM의 경우도 마찬가지로 DT_SINGLELINE 을 써주어야 한다.





출력 문자열을 TEXT("Text\nbutton")으로 변경하고 옵션을 DT_RIGHT만 정의하면 다음과 같이 출력된다.




말줄임표 옵션은 두가지가 있다.

DT_END_ELLIPSIS 나 DT_PATH_ELLIPSIS 옵션이 바로 그것이다.

이유는 모르겠지만 DT_PATH_ELLIPSIS 는 작동이 이상하게 안되서..

DT_END_ELLIPSIS  만 출력화면을 나타내었다.[텍스트는 일부러 상자 범위 이상의 길이가 되어야 하므로 바꾸었다.]

 

 
마지막으로 DT_WORDBREAK 형식을 지정하면 다음행으로 단어단위의 줄바꿈이 이루어진다.

 쓴 코드는 다음과 같다.

dc.DrawText(TEXT("This is the test string!!!!!!"), &Rect, DT_WORDBREAK);

출력화면.

 

마지막으로 사용한 파일 업로드 까지 마치면 이번 글도 끝. 

 


**공부에 도움이 되었다면 손가락 버튼을 클릭해주심 좋겠습니다.**   
저작자 표시 비영리
신고
Posted by 졸가메

이번에는 컨트롤 버튼 [누르면 작동하는 일반적인 버튼들] 을 구현하는 코드이다.

코딩해야 하는 부분이 많다. 

일단 프로젝트 속성은 전과 같고.



┌ VirtualButtonView.h 파일의 수정부분  ┐

#pragma once


class CVirtualButtonView : public CView
{
protected: // serialization에서만 만들어집니다.
CVirtualButtonView();
DECLARE_DYNCREATE(CVirtualButtonView)

// 특성입니다.
public:
CVirtualButtonDoc* GetDocument() const;
//추가부분 시작

CRect m_BtnRect;        // 버튼이 그려질 위치
BOOL m_bClicked;        // 버튼이 클릭된 상태인지 나타내는 플래그

//추가부분 종료


 //////////////////////////////////////////////////////////


CVirtualButtonView::CVirtualButtonView()
{
// TODO: 여기에 생성 코드를 추가합니다.

//추가부분 시작

m_BtnRect = CRect(10,10,210,40);
m_bClicked = FALSE;

//추가부분 종료
}


///////////////////추가 수정 부분 /////////////////// 

다음으로는 왼클릭 버튼의 작업에 따른 두 메시지 핸들러 함수의 코딩이다.

먼저 다운 키부터.

// CVirtualButtonView 메시지 처리기

void CVirtualButtonView::OnLButtonDown(UINT nFlags, CPoint point)
{

if(m_BtnRect.PtInRect(point))
{//버튼이 위치한 영역을 클릭하였는가?


m_bClicked = !m_bClicked;
RedrawWindow(&m_BtnRect); // 플래그를 토글하고 윈도우를 다시 그린다.
}

CView::OnLButtonDown(nFlags, point);

}

/////////////////////////////////////////////////

그다음은 업 키 .

////////////////////////////////////////////////

void CVirtualButtonView::OnLButtonUp(UINT nFlags, CPoint point)
{

if(m_bClicked)
{//버튼이 위치한 영역인가?

m_bClicked = !m_bClicked;
RedrawWindow(&m_BtnRect);
// 플래그를 토글하고 윈도우를 다시 그린다.
}

if(m_BtnRect.PtInRect(point))
{
AfxMessageBox(L"버튼을 클릭했습니다.");
}

CView::OnLButtonUp(nFlags, point);
}

/////////////////////////////////////////////////


클릭에 관한  메시지 출력을 다 코딩했으니 이제 메인이 되는 프린트  함수를 등록하자.



void CVirtualButtonView::OnPaint()
{
CPaintDC dc(this); // device context for painting

CRect Rect(m_BtnRect);//시스템이 정의한 버튼 색상으로 버튼의 영역을 칠한다. ?
Rect += CRect(1,1,1,1);
dc.Rectangle(&Rect);
dc.FillSolidRect(&m_BtnRect, ::GetSysColor(COLOR_BTNFACE));

if(m_bClicked)//버튼이 눌려진 상태
{
dc.Draw3dRect(m_BtnRect,
::GetSysColor(COLOR_3DSHADOW), // 왼쪽/위쪽 이 어두운 색.
::GetSysColor(COLOR_3DLIGHT));  // 오른쪽/아래쪽 이 밝은 색.
}
else
{ //버튼이 눌린 상태가 아닌 경우(평상시 상태)
dc.Draw3dRect(m_BtnRect,
::GetSysColor(COLOR_3DLIGHT),
::GetSysColor(COLOR_3DSHADOW));
}


dc.SetBkColor(::GetSysColor(COLOR_BTNFACE));
dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
        //시스템이 정하는 버튼 관련 색상으로 텍스트를 그린다.

if(m_bClicked)
{
CRect Rect = m_BtnRect;
//눌러진 상태면 글씨가 출력되는 위치를 1픽셀 조절한다.

Rect += CRect(0,0,2,2);
dc.DrawText(L"Test button", &Rect,
DT_CENTER | DT_SINGLELINE | DT_VCENTER);

}
else
{
dc.DrawText(L"Test button", &m_BtnRect,
DT_CENTER | DT_SINGLELINE | DT_VCENTER);
}

}
///////////////////////////////////////////////////////////

코딩이 완료되었으므로 출력화면을 보자.

ㄴ 일반적인 클릭 후 화면

                              ㄴ꾹 누르고 있는 상태의 스크린샷



잘 안보이므로 돋보기 기능을 활용하여 확대해 보았다. 

해당 상태는 아직 버튼을 누르지 않은 상태. 잘 보면 테두리 안쪽이 회색으로 되어있음을 알 수 있다.
 


버튼을 누르고 있게되면 회색 부분이 흰색 부분으로 바뀐다.


마지막은 역시 파일업로드.



 

 
저작자 표시 비영리
신고
Posted by 졸가메

글꼴에 따른 문자열을 출력하는 코드이다.

프로젝트명은 TextOutDemo 이며

속성은 전과 같은 SDI 이다.

더보기



/////////////////////////////////////////////////////

void CTextOutDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting
int nY = 0;
CFont Font;
CFont* pOldFont;

LOGFONT lf;
::ZeroMemory(&lf, sizeof(lf));

wsprintf(lf.lfFaceName,TEXT("%s"), TEXT("Arial"));
//wsprintf 는 우측의 내용을 좌측에 출력하는 함수이다.
//위에 있는 코드의 내용은 lf의 글꼴명을 Arial로 한다 라는 코드이다.
 

for(int i = 10; i<25;i++)
{
lf.lfHeight= i;
nY +=i;
Font.CreateFontIndirect(&lf);
//Arial, 크기 10~24 까지 폰트 객체를 생성한다.
pOldFont = dc.SelectObject(&Font);
dc.TextOut(10,nY,TEXT("Test String!"));    //왼쪽에서 10 의 거리 위에서부터 nY의 거리의 지점에 텍스트를 출력한다.
dc.SelectObject(pOldFont);         //폰트값을 초기화한다.

//생성된 폰트로 Test String! 이라는 문자열을 출력한다.

Font.DeleteObject(); 
//폰트 객체를 삭제한다.
}//반복한다.
}


///////////////////////////////////////

출력화면

 


 x좌표는 고정되고 y좌표와 글씨 크기가 변경되어 출력되는 화면이 나온다.


////////////////////////////////////////////////////////////////////////////////////////


다음으로는 좀 더 정교한 출력을 위한 코드이다.



void CTextOutDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting

int nY = 50;
CFont Font;
CFont* pOldFont;

LOGFONT lf;
::ZeroMemory(&lf, sizeof(lf));

wsprintf(lf.lfFaceName,TEXT("%s"), TEXT("Arial"));
//wsprintf 는 우측의 내용을 좌측에 출력하는 함수이다.
//위에 있는 코드의 내용은 lf의 글꼴명을 Arial로 한다 라는 코드이다.

lf.lfHeight = 24; //글꼴의 높이를 픽셀 단위로 정하는 멤버. 값이 0이면 기본크기로 결정.[음수 사용해도 절대값으로 계산됨]
lf.lfWidth = 24;           //문자간의 장평을 결정하는 멤버
lf.lfOrientation = 50;               //글자의 각도를 0.1도 단위로 명시하는 멤버
lf.lfEscapement = 50;            //문자열의 기울기를 0.1도 단위로 명시하는 멤버
lf.lfWeight = FW_BOLD;         //글꼴의 굵기를 명시하는 멤버, 보통 0 부터 900까지의 값이며 값은 100단위로 증가. 
//보통 일반 글꼴은 400(FW_NORMAL)정도이며 흔히들 굵게 로 하는것은 700(FW_BOLD) 정도 라고 함.
lf.lfItalic = true;                     //이탤릭체 유무
lf.lfUnderline = true;               // 밑줄 유무
lf.lfStrikeOut = true;                //취소줄 유무.



Font.CreateFontIndirect(&lf);
//Arial, 크기 10~24 까지 폰트 객체를 생성한다.
pOldFont = dc.SelectObject(&Font);
dc.TextOut(100,nY,TEXT("Test String!")); //왼쪽에서 10 의 거리 위에서부터 nY의 거리의 지점에 텍스트를 출력한다.
dc.SelectObject(pOldFont);

//생성된 폰트로 Test String! 이라는 문자열을 출력한다.

Font.DeleteObject();
//폰트 객체를 삭제한다.
}


여러 글꼴의 속성에관한 멤버들을 사용한 코드이다.

내용은 주석으로 처리해두었으니 그걸 보면 된다.


출력하면 코딩된 속성이 다 들어가버린 문자열이 나온다.




다음은 탭 이 먹히는 텍스트 아웃 과 먹히지 않는 텍스트 아웃의 비교 코드이다.

void CTextOutDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting


CFont Font;

CFont* pOldFont;
LOGFONT lf;
::ZeroMemory(&lf,sizeof(lf));
lf.lfHeight = 36;
wsprintf(lf.lfFaceName, TEXT("%s"),TEXT("Arial"));
Font.CreateFontIndirect(&lf);
pOldFont = dc.SelectObject(&Font);

dc.TextOutW(20,20, TEXT("\tTest String!"));
//TextOut 을 이용하면 그냥 출력되며 '\t'가 반영되지 않는다.
int nTabStop = 40;
dc.TabbedTextOut(20,70,TEXT("\tTest String!"),1, &nTabStop, 20);
dc.TabbedTextOut(20,120,TEXT("\t\tTest String!"),1, &nTabStop, 20);
//TabbedTextOut를 이용하면 '\t' 가 들어간 문자열이 출력된다.

dc.SelectObject(pOldFont);

}


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

출력화면

 
\\\\\\\\\\\\\\\\\\\\\\\

tabbedtextout 을 사용하면 \t 의 기능이 작동하여 출력되고

그냥 textout을 사용하면 \t가 있어도 작동하지 않는다. 그 외의 특별한 내용은 없는 코드.

그냥 텍스트 아웃과 다른점은 출력시에 문자열 뿐만이 아닌 탭의 크기도 넣어주어야 한다는 것이다.



여기까지 프로젝트 파일의 업로드.


















 
저작자 표시 비영리
신고
Posted by 졸가메
실은 미완성..[4번문제가 너무 노가다성이 강해서+ 내 방식이 맞는거같아보이질 않아서..]

이지만 코드파일과 설명 올려봄미다.

으헝헝

페이지 227. 

1번 문제.

전형적인 예제를 생성하여 크기가 120 120 인 정사각형을 출력하시오.

매우 쉬운 문제.

함수 하나면 됩니다.[속성같은거 정하는게 아니니]

OnPaint

메시지핸들러를 추가해주시고


void CEXGDIView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.


dc.Rectangle(20,20,140,140); //사각형을 그리는 함수

}
 
끝.



ㄴ 출력화면.



 2번 문제.


앞서 작성한 사각형의 테두리를 3픽셀의 붉은색으로 하고 내부는 회색으로 칠하시오.


void CEXGDIView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.



LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(192,0,0);

CPen NewPen;
NewPen.CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT |PS_JOIN_MITER, 3, &lb);          
//선 속성 설정, 굵기 3의 색은 빨간색인 실선, 끝부분 처리는 뾰족함.
CPen* pOldPen = dc.SelectObject(&NewPen);

CBrush NewBrush(RGB(192,192,192));
CBrush* pOldBrush = dc.SelectObject(&NewBrush);

dc.Rectangle(20,20,140,140); //사각형을 그리는 함수


dc.SelectObject(pOldPen); //  펜속성 초기화
dc.SelectObject(pOldBrush); // 브러쉬 속성 초기화

}
 
그대로 지정해주면 됩니다. 팬 속성도 정해주고 브러쉬도 정해주고

마지막에 초기화까지 해주면 끝.



 


                                          ㄴ 출력화면.

 3번 문제. 

 임의의 육각형을 그려라..

이건 선긋기 + 랜더링 을 이용하면 됩니다.

 


void CEXGDIView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.

LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(192,0,0);

CPen NewPen;
NewPen.CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT |PS_JOIN_MITER, 3, &lb);          
//선 속성 설정, 굵기 3의 색은 빨간색인 실선, 끝부분 처리는 뾰족함.
CPen* pOldPen = dc.SelectObject(&NewPen);

CBrush NewBrush(RGB(192,192,192));
CBrush* pOldBrush = dc.SelectObject(&NewBrush);


dc.BeginPath(); //경로 시작 [추가코드]
dc.MoveTo(50,0);
dc.LineTo(150,0);
dc.LineTo(195,85);
dc.LineTo(150,170);
dc.LineTo(50,170);
dc.LineTo(0,85);
dc.LineTo(50,0); //두께가 20 픽셀인 선을 세번 그어 삼각형을 그린다.
dc.EndPath(); //경로 종료 [추가코드]
dc.StrokeAndFillPath(); //두 함수를 통하여 완성된 폐곡선을 통한 도형을 랜더링[추가코드]


dc.SelectObject(pOldPen); //  펜속성 초기화
dc.SelectObject(pOldBrush); // 브러쉬 속성 초기화

}

moveto 와 lineto  를 이용하여 도형을 그리고 시작과 끝을 beginpath 와 endpath로 묶고 마지막에 랜더링함수 사용.

다각형의 그림을 그릴때 씁니다.




  4번 문제. 
 

사각형을 그리되 모서리부분을 둥글게 코드를 짜고 RoundRect() 함수를 사용하지 않고 코딩하라.

실은 완벽하게 풀진 못했습니다만. 보기에는 얼추 해낸듯한 코드를 보여드립니다.



void CEXGDIView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.


CRect PieRect(50,50,70,70);
dc.Rectangle(50,50,150,150); //사각형을 그리는 함수

dc.Pie(PieRect,CPoint(PieRect.CenterPoint().x,PieRect.top),CPoint(PieRect.left, PieRect.CenterPoint().y)); //내각이 90도인 부채꼴



CPen NewPen(PS_SOLID, 2, RGB(250,250,250));
CPen* pOldPen = dc.SelectObject(&NewPen);


dc.MoveTo(50,50);//시작 좌표
dc.LineTo(50,57);// 끝 좌표
dc.MoveTo(50,50);//시작 좌표
dc.LineTo(57,50);// 끝 좌표

dc.MoveTo(51,60);//시작 좌표
dc.LineTo(60,60);// 끝 좌표
dc.MoveTo(60,51);//시작 좌표
dc.LineTo(60,60);// 끝 좌표
//왼쪽 위 좌표

dc.SelectObject(pOldPen);  


 

마지막으로 전체 파일 업로드. 

 
저작자 표시 비영리
신고
Posted by 졸가메
프로젝트명은 TriangleDemo로 

옵션은 전과 같은 SDI

생성 옵션 보기



본 코드는 삼각형을 그려보는 코드이다

일단 무조건 코딩을 한다.
///////////////////////////////////////////////////
void CTriangleDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting

DWORD style[] = {6,3};
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(192,192,192);

CPen NewPen;
NewPen.CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT,20,&lb);
CPen* pOldPen = dc.SelectObject(&NewPen);

CBrush NewBrush(RGB(0,0,192));//청색 브러시를 선택하여 삼각형을 칠한다.
CBrush* pOldBrush =dc.SelectObject(&NewBrush);

dc.MoveTo(190,40);
dc.LineTo(290,190);
dc.LineTo(90,190);
dc.LineTo(190,40);
//두께가 20 픽셀인 선을 세번 그어 삼각형을 그린다.

dc.SelectObject(pOldBrush);
dc.SelectObject(pOldPen);
//기본값으로 재설정한다.

dc.MoveTo(190,40);
dc.LineTo(290,190);
dc.LineTo(90,190);
dc.LineTo(190,40);
//기본값으로 삼각형을 덧씌워 그린다.


}
/////////////////////////////////////////////////

 이 코드를 짜서 돌려보면

뭔가 이상한 점을 눈치 챌것이다.

분명 코드는 많은데 결국 작동하는 코드는 적다는 것.

출력화면을 보자.



분명 펜 뿐만 아니라 브러쉬 도 설정했지만

도형 내의 색이 칠해지지 않았고, 끝부분도 좀 매끄럽게 이어지는 느낌이 없다.

코드에 수정을 가해서 다음과 같이 다시 코딩을 하면.



void CTriangleDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting

DWORD style[] = {6,3};
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(192,192,192);

CPen NewPen;
NewPen.CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_MITER,20,&lb); //PS_JOIN_MITER가 추가되었다.[추가코드]
CPen* pOldPen = dc.SelectObject(&NewPen);

CBrush NewBrush(RGB(0,0,192));//청색 브러시를 선택하여 삼각형을 칠한다.
CBrush* pOldBrush =dc.SelectObject(&NewBrush);

dc.BeginPath(); //경로 시작 [추가코드]
dc.MoveTo(190,40);
dc.LineTo(290,190);
dc.LineTo(90,190);
dc.LineTo(190,40); //두께가 20 픽셀인 선을 세번 그어 삼각형을 그린다.
dc.EndPath(); //경로 종료 [추가코드]
dc.StrokeAndFillPath(); //두 함수를 통하여 완성된 폐곡선을 통한 도형을 랜더링[추가코드]


dc.SelectObject(pOldBrush);
dc.SelectObject(pOldPen);
//기본값으로 재설정한다.

dc.MoveTo(190,40);
dc.LineTo(290,190);
dc.LineTo(90,190);
dc.LineTo(190,40);
//기본값으로 삼각형을 덧씌워 그린다.

}

///////////////////////////////
주석의 설명대로 
젤 위에 추가한 속성 코드는 연결부분의 처리에 관한 속성이고

그다음으로 dc.BeginPath(); 는 곡선간의 연결을 총해 dc.EndPath();와 합쳐져서 하나의 폐곡선을 만든다.

마지막으로  dc.StrokeAndFillPath(); 를 통해 랜더링을 해주면 브러쉬가 작동하게 된다.


////////////////////////////
출력화면은 이렇게 나온다.

 
/////////////////////


여기서 쓰인 선의 결합에 관한 스타일의 종류를 보자.


선의 결합 3속성 보기





또다른 도형을 그리는 코딩 방법으로는 배열과 폴리곤 함수를 사용하는 것이다.

그럴 경우 위와 같은 긴 코딩이 필요 없이 간단하게 특정 도형을 그려낼 수 있다.[대신 선을 그려서 만드는 복잡한 도형은 안된다.]

/*
dc.BeginPath(); //경로 시작 [추가코드]
dc.MoveTo(190,40);
dc.LineTo(290,190);
dc.LineTo(90,190);
dc.LineTo(190,40); //두께가 20 픽셀인 선을 세번 그어 삼각형을 그린다.
dc.EndPath(); //경로 종료 [추가코드]
dc.StrokeAndFillPath(); //두 함수를 통하여 완성된 폐곡선을 통한 도형을 랜더링[추가코드]
*/

POINT arPt[3] ={{190,40}, {290,190}, {90,190}};
dc.Polygon(arPt,3);

/////////////////////////////////////////////

위의 것들을 모두 주석처리 해버리고 아래의 코드만으로도 삼각형이 그려진다.[채색도 되는건 당연하다.]


같은 방법으로 Rectangle() 함수와 Polygon() 함수로 사각형을 구현하면 다음과 같다.

/////////////////////////////////
void CTriangleDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting

DWORD style[] = {6,3};
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(192,192,192);

CPen NewPen;
NewPen.CreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_MITER,20,&lb); //PS_JOIN_MITER가 추가되었다.[추가코드]
CPen* pOldPen = dc.SelectObject(&NewPen);

CBrush NewBrush(RGB(0,0,192));//청색 브러시를 선택하여 삼각형을 칠한다.
CBrush* pOldBrush =dc.SelectObject(&NewBrush);


POINT arPt[4] = {{20,20} , {140,20}, {140, 140}, {20,140}}; //배열을 사용해서 4개의 점을 설정한다.
dc.Polygon(arPt,4); //폴리곤 함수를 사용해서 해당 배열을 연결하여 사각형을 그린다.

dc.Rectangle(CRect(180,20,300,140)); //함수를 사용해서 사각형을 그린다.



dc.SelectObject(pOldBrush);
dc.SelectObject(pOldPen); //기본값으로 재설정한다.

}

///////////////////
기존의 삼각형은 주석처리 하여 치워버렸다.

이렇게 하면 두께가 20인 픽셀인 선으로 둘러쌓인 [모서리는 각지게 속성이 정해진] 속이 색칠된 사각형이 두개 완성된다.

ㄴ출력화면

/////////////////////////////////////////////////////////////////////////////////

이번에는  사각형을 지우고[주석처리를 하든 지우든..] 원을 그려보자

코드는 다음과 같다.

void CTriangleDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting

CBrush NewBrush(RGB(0,192,192));
CBrush* pOldBrush = dc.SelectObject(&NewBrush); //브러시를 선택하여 도형을 칠한다.


dc.Rectangle(20,20,140,140); //사각형을 그리는 함수는
dc.Ellipse(20,20,140,140); //원을 그리는 함수와 사각형을 그리는 함수는 인자가 같다.

dc.SelectObject(*pOldBrush);//브러쉬 초기화

}

/////////////////////////////////

출력화면은 다음과 같다.
     


좌측은 코드 그대로 썼을 경우의 출력화면이고 우측은 원을 그리는 함수의 크기는 그대로 유지하고 위치만 우측으로 이동시킨 출력화면이다.[이해를 돕기 위해 일부러 나누어 보았다.]


이번에는 원이 아닌 부채꼴을 그리는 코드를 알아보자.


코드가 복잡해도 긁지 말고 직접 치는것이 이해에 도움이 된다. 사소한 것이지만 긁기보다는 직접 치도록 하자.


 void CTriangleDemoView::OnPaint()

{

CPaintDC dc(this); // device context for painting


CBrush NewBrush(RGB(0,192,192));

CBrush* pOldBrush = dc.SelectObject(&NewBrush); //브러시를 선택하여 도형을 칠한다.


CRect PieRect(20,20,140,140);

dc.Pie(PieRect, 

CPoint(PieRect.CenterPoint().x,PieRect.top),

CPoint(PieRect.right, PieRect.CenterPoint().y)); //내각이 270도인 부채꼴



PieRect = CRect(150,20,270,140);

dc.Pie(PieRect, 

CPoint(PieRect.right, PieRect.CenterPoint().y),

CPoint(PieRect.CenterPoint().x,PieRect.top)); //내각이 90도인 부채꼴

dc.SelectObject(pOldBrush);//브러쉬 초기화

}


////////////////////////////////////////////////////

출력화면은 다음과 같다.

 



이 코드에서 쓰이는 CDC 클래스의 함수인 Pie()함수는 두가지로 다중정의되어있고 MFC에서는 지금 사용한 것과 같은 형식을 가장 많이 사용한다.

이 함수는 4개의 좌표를 인자로 받기 때문에 복잡하며 각 인자를 따로 보면 이해가 쉽지 않다. 고 한다.

코드 내부에서 쓰인 함수 중 CenterPoint() 함수는 받은 값들의 중간값을 계산해내는 함수이다. 여기서는 계산 결과가 (20 + 140) / 2  인 80 의 값이 나온다. 

그러니까 어떤 방식이냐면

1. 원이 들어갈 사각형의 위치와 크기를 정한다.

2. 부채꼴이 시작될 위치와 끝날 위치를 정한다.

3. Pie함수에 사각형, 시작위치, 끝위치 를 인자로 집어넣는다.

라는 순서이다


이렇게 하면 될걸 뭘 그리 복잡하게 여러줄로 표현하는지 모르겠다.?

CPoint 속에 들어있는 인자 중 PieRect  구조체는 CRect 의 형식을 띄고 있다는 점에서 

숫자가 아니고 문자로 표현되어 아마 어렵게 느껴지는 것 일 지도 모르겠다.


//////////////////////////////////////////////////

마지막의 마지막으로 끝부분이 부채꼴 모양인 사각형을 그리는 함수에 대해 알아보자.

코드는 다음과 같다.

 void CTriangleDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting


DWORD style[] = {3,3}; //사용자 정의 스타일 배열 3,3
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(192,0,0);


CPen NewPen;
NewPen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT |PS_JOIN_MITER, 3, &lb, 2, style);          //선 속성 설정, 굵기 3의 색은 빨간색인, 유저스타일 실선, 끝부분 처리는 뾰족함.
CPen* pOldPen = dc.SelectObject(&NewPen);


CBrush NewBrush(RGB(192,192,192));       //브러쉬 색 설정
CBrush* pOldBrush =dc.SelectObject(&NewBrush);

dc.RoundRect(CRect(20,20,140,140), CPoint(20,20));      //끝부분이 부채꼴인 사각형을 그리는 함수
        //사각형의 4개의 점과 내각이 90도인 부채꼴의 둥근 정도를 명시하는 좌표로 인자가 이루어져있다.
 
dc.SelectObject(pOldBrush); //브러시 초기화
dc.SelectObject(pOldPen); //펜 초기화

}

/////////////////////////////

출력화면

 

 이번 글에 사용된 코드 파일.

[맨 마지막의 코드만 활성화 되어있고 나머지 코드들은 모두 주석처리 되어있으니 임의로 주석을 설정/해제 하면서 보면 되지만 왠간하면 직접 치면서 따라하는걸 추천함.]


 

GDI는 정말 양이 많다. 으으.
저작자 표시 비영리
신고
Posted by 졸가메


티스토리 툴바