인프런 커뮤니티 질문&답변
pOldPen = dc.SelectObject(); 관련 질문
해결된 질문
작성
·
262
·
수정됨
0
안녕하세요 선생님
강의에서 옛날 윈도우(XP)에서는 pOldPen = dc.SelectObject()를 안해주면 문제가 생길수 있고, 요즘 윈도우즈에서는 괜찮을거라고 하셨는데요.
이부분에 대해서 조금 더 자세하게 알고 싶습니다.
테스트용으로 코드를 작성했습니다.
void CPenBrushDemoView::OnPaint()
{
CPaintDC dc(this); // device context for painting
CBrush NewBrush;
//비트맵 클래스 객체를 선언하여 비트맵 리소스 로딩.
CBitmap Bmp;
Bmp.LoadBitmap(IDB_BITMAP1);
//로딩된 비트맵 리소스로 패턴 브러시 생성.
NewBrush.CreatePatternBrush(&Bmp);
CBrush* pOldBrush = dc.SelectObject(&NewBrush);
//클라이언트 뷰 클래스의 클라이언트 영역 크기를 알아내고
//그 크기에 해당하는 네모를 그림.
CRect Rect;
GetClientRect(&Rect);
dc.Rectangle(&Rect);
dc.SelectObject(pOldBrush);
DWORD style[] = {6, 3};
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(255, 0, 0);
// 여기서부터...
CPen* pOldPen;
CPen FirstPen;
{
FirstPen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT,
20, &lb, 2, style);
pOldPen = dc.SelectObject(&FirstPen);
dc.MoveTo(40, 40);
dc.LineTo(240, 40);
}
CPen SecondPen;
{
SecondPen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT,
40, &lb, 2, style);
dc.SelectObject(&SecondPen);
dc.MoveTo(40, 240);
dc.LineTo(240, 240);
}
{
CPen ThirdPen;
ThirdPen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT,
60, &lb, 2, style);
dc.SelectObject(&ThirdPen);
dc.MoveTo(40, 440);
dc.LineTo(240, 440);
}
dc.MoveTo(40, 640);
dc.LineTo(240, 640);
dc.SelectObject(pOldPen);
}
위 코드에서는 총 4개의 직선을 그리고 있습니다.
여기서, CPen ThirdPen은 스코프 안에서 소멸자가 불러질 때 DeleteObject()가 실행되면서 gdi는 없어집니다. 하지만 디바이스컨텍스트(dc)는 계속 해당 gdi를 가리키고 있습니다. 그런데 그 이후에 dc는 지워진 gdi의 방식대로 직선을 그리고 있습니다.(dc.MoveTo(40, 640); dc.LineTo(240, 640);) dc가 가리키고 있던 gdi가 지워졌는데도 불구하고 어떻게 기존의 방식대로 그릴수 있는지 이유를 모르겠습니다.
그리고 위의 코드에서,
dc.MoveTo(40, 440);
dc.LineTo(240, 440);
를 지우게 되면 ...
{
CPen ThirdPen;
ThirdPen.CreatePen(PS_GEOMETRIC | PS_USERSTYLE | PS_ENDCAP_FLAT,
60, &lb, 2, style);
dc.SelectObject(&ThirdPen);
// dc.MoveTo(40, 440);
// dc.LineTo(240, 440);
}ThirdPen이 스코프를 벗어난 이후 마지막 직선은 ThirdPen의 방식이 아닌 SecondPen의 방식으로 그려지고 있습니다. 좀 전의 위에서 동작한 방식과 일관성이 맞지 않는것같아요.
질문글이 길어서 요약을 해보자면..
2개의 소스코드가 사소한 차이가 있는데 왜 DC가 동작하는 방식이 다를까요?
DC와 GDI에 대한 저의 생각에서 혹시 오류가 있을까요?
퀴즈
윈도우 그래픽 시스템에서 GDI의 주된 역할은 무엇일까요?
3D 게임 그래픽 가속
하드웨어와 독립적인 그래픽 출력 추상화
파일 시스템 관리
네트워크 통신 제어
답변 1
1
저도 정확히는 알 수 없습니다. 그러려면 윈도우 GDI 관련 요소를 디버깅하고 분석해야 하기 때문입니다. 그러나 추정은 해볼 수 있을 것 같습니다. 조금 이상한(?) 실험용 코드입니다만...추정으로 말씀드리자면 아마도 지역변수로 선언된 CPen 클래스 인스턴스들이 아직 메모리에 남아있어서 발생한 문제로 보입니다.
모든 지역변수는 Stack 메모리를 사용합니다. 그리고 스택은 스코프를 벗어날 때 크기가 줄어듭니다. 하지만 그렇다고 기존 값을 모두 0으로 Clear하지도 않습니다. 그리고 우연히 위치가 맞는 지점에서 값을 읽는다면 기존의 값이 그대로 출력되기도 합니다. 이와 같은 문제는 자동변수인 지역변수의 주소나 참조를 반환했을 때 발생하는 문제와 매우 흡사합니다.
참고하시기 바랍니다. 😄





