pOldPen = dc.SelectObject(); 관련 질문
안녕하세요 선생님
강의에서 옛날 윈도우(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에 대한 저의 생각에서 혹시 오류가 있을까요?
回答 1
1
저도 정확히는 알 수 없습니다. 그러려면 윈도우 GDI 관련 요소를 디버깅하고 분석해야 하기 때문입니다. 그러나 추정은 해볼 수 있을 것 같습니다. 조금 이상한(?) 실험용 코드입니다만...추정으로 말씀드리자면 아마도 지역변수로 선언된 CPen 클래스 인스턴스들이 아직 메모리에 남아있어서 발생한 문제로 보입니다.
모든 지역변수는 Stack 메모리를 사용합니다. 그리고 스택은 스코프를 벗어날 때 크기가 줄어듭니다. 하지만 그렇다고 기존 값을 모두 0으로 Clear하지도 않습니다. 그리고 우연히 위치가 맞는 지점에서 값을 읽는다면 기존의 값이 그대로 출력되기도 합니다. 이와 같은 문제는 자동변수인 지역변수의 주소나 참조를 반환했을 때 발생하는 문제와 매우 흡사합니다.
참고하시기 바랍니다. 😄
Reticle이 안나옵니다.
0
7
1
진행 방법 질문드립니다!
0
26
2
Singleton 관련 질문입니다.
1
27
2
2-I) 왜 이 문제가 그래프이론 카테고리에 있는지 잘 모르겠습니다.
0
54
2
AddGameFrameworkComponentReceiver vs AddExtensionHandler
0
24
0
scanf("%d\n") 의미
0
20
1
2주차 개념#12 트리 순회
0
25
2
책과 강의 질문
0
156
2
MFC로 게임 엔진 제작 질문
0
175
2
이벤트 메시지 루프의 '응답 없음'에 대하여
0
136
2
그려진 도형 선택(Z-order 변경)부분[9분59초경]
0
92
2
메모리 창을 어떡해 뛰우나요?
0
164
3
안녕하세요 선생님
0
114
1
토글메뉴(강사도 삽질) 10:30 질문 / pch.h 전역변수 선언 에러
0
171
2
CMainFrame과 CCreateDemoView와의 관계 (교과서 p80 그림3-3)
1
109
1
메시지 루프에서 메시지 처리 성능 비교: WinAPI vs MFC
0
273
3
커스텀 드로우에 대해서도 다루나요?
0
187
2
MainFrame 에서 LButtonDown 이벤트 처리 질문
0
166
1
윈도우 프로그래밍 UI 관련 질문입니다
0
230
2
유튜브 강의와 차이점
0
316
1
책 질문입니다.
0
283
2
mfc 내부에서 콜백 함수 구현 방법
0
391
1
수강기간 무제한인지 문의드립니다!
1
453
1
라디오 버튼 그룹에 대해서 질문합니다.
0
302
1

