Search Results for 'VS.NET 2003'

ATOM Icon

1 POSTS

  1. 2007/12/30 Console에서 Dialog 생성 시 by 장현준

Console에서 Dialog 생성 시

Console project에서 Dialog를 4개 생성한 뒤 하나만 DestroyWindow를 하면 해당 Dialog보다 나중에 생성된 Dialog까지 종료되는 문제가 있었다.

예를 들면 다음과 같은 상황인데,

CDialog *pdlg[4];
int i;

i = 0;

pdlg[i] = new CDialog();
pdlg[i]->Create(IDD_DIALOG1, NULL);
pdlg[i]->ShowWindow(SW_SHOW);
pdlg[i]->MoveWindow(0, 0, 100, 100);
i++;

pdlg[i] = new CDialog();
pdlg[i]->Create(IDD_DIALOG1, NULL);
pdlg[i]->ShowWindow(SW_SHOW);
pdlg[i]->MoveWindow(100, 0, 100, 100);
i++;

pdlg[i] = new CDialog();
pdlg[i]->Create(IDD_DIALOG1, NULL);
pdlg[i]->ShowWindow(SW_SHOW);
pdlg[i]->MoveWindow(200, 0, 100, 100);
i++;

pdlg[i] = new CDialog();
pdlg[i]->Create(IDD_DIALOG1, NULL);
pdlg[i]->ShowWindow(SW_SHOW);
pdlg[i]->MoveWindow(300, 0, 100, 100);
i++;

for(i = 0; i < 4; i++)
{
	printf("Object: 0x%08X, HWND: 0x%08X\n", pdlg[i], pdlg[i]->GetSafeHwnd());
}

pdlg[1]->DestroyWindow();

for(i = 0; i < 4; i++)
{
	printf("Object: 0x%08X, HWND: 0x%08X\n", pdlg[i], pdlg[i]->GetSafeHwnd());
}


여기서 첫번째 for에서 출력되는 것과 두번째 for에서 출력되는 것을 보면
두번째 for에서 1이후의 dialog들의 핸들 값이 0x00000000으로 초기화 되는것을 볼 수 있다.

굳이 CWnd::DestroyWindow()를 호출하였을 때 뿐만이 아니라
::DestroyWindow(pdlg[1]->GetSafeHwnd())를 이용하여도 동일한 증상이 일어난다.
특히 ::DestroyWindow를 호출하였는데 나머지 값들이 변경되는 것은 정말 신기한 일인데,
처음에는 buffer overflow인가? 라는 생각을 갖고 배열 순서를 바꾸어 테스트 해본 결과, bo는 아니었다.

약 한시간 삽질한 끝에, DestroyWindow()하지 않은 Dialog들에 대해서도 CWnd::Detach()가 호출이 되었다는것을 알아내었는데, 콜스택을 따라가 보니 pdlg[1]의 DestroyWindow()에서 호출하거나 그런 일은 전혀 없었다.
다만 커널 dll 중 어디선가 호출을 하였다는 것 밖에 알 수 없었던 상황인데..

지난 금요일 devpia에 질문을 올리고 다른분이 답글을 달아 주신것을 오늘(일요일) 보았다.

"VC++ 6.0 SP2에서는 정상적으로 동작합니다. 혹시 컴파일러 문제는 아닐까요?"

라는 글과 함께.
그래서 당장 VC 6.0을 켜서 해보았는데..
동일한 코드로 작성을 하니 똑같은 증상이었다.
컴파일러 문제는 아니었군.
그러다가 순간 머릿속에 들어오는 생각.
그 사람은 TRACE로 바꾸어서 했다는 것이었다. 즉 Console 기반 프로젝트가 아니라는 것이었다.
혹시나 해서 Dialog based로 해보았더니 제대로 동작한다.
devpia에 감사하다고 답을 달면서 Console기반에서만 안된다고 하였다.

댓글을 단 뒤 갑자기 드는 생각!

여기까지 얘기 하였을 때 이 글을 보는 사람은 답을 찾았는가?

Dialog based와 Console 프로젝트의 차이점은 main wnd가 없다는 것이다.
(여기선 mfc supported된 Console project를 기반으로 설명한다)
AfxGetMainWnd() 하면 NULL이 나오는데...
이게 문제다! 라는 생각으로 당장 실천에 옮겼다.
아래와 같이 DesktopWindow의 핸들을 얻어와서 parent로 값을 넣은 결과

CWnd *pDesktop;

pDesktop = CWnd::GetDesktopWindow();


잘 동작한다~!
parent wnd문제가 맞았다.
그런데 왜 이런 일이 발생하는 것일까?
문제 해결책을 알았으니 원인을 알아내는건 비교적 쉬운일이다.
당연히 parent 문제이므로 pdlg들의 GetParent()를 출력 해보았다.
방금 생성한 Window가 Parent가 된 것을 볼 수 있었다.
그러면 parent와 child의 종속 관계에서 parent가 해제 되니 child도 해제가 되었다고 생각할 수 있다.
이왕 한김에 확실히 해보자는 생각에 AfxGetMainWnd()를 한 결과
pdlg[0]이 생성될 때에는 NULL이, pdlg[0]이 생성된 후에는 pdlg[0]의 핸들이 반환되었다.
즉 AfxGetMainWnd()가 Dialog를 생성할때마다 바뀐다는 사실.
이걸 찍어 본 이유는 새로운 윈도우 생성할 때 Parent를 NULL로 주면 AfxGetMainWnd()에서 얻어온 윈도우를
자동으로 Parent로 지정해주기 때문이다.

지금까지 AfxGetMainWnd() 값은 고정일것이라고 생각했다. 내가 이 값을 전혀 쓰지 않으므로 신경을 쓰지 않고 있었는데, MFC 내부에서 이렇게 처리하고 있을 줄이야..

framework에서 이런 삽질(?)을 해대면 -_-.. 진짜 난감하다.
크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 장현준

2007/12/30 15:48 2007/12/30 15:48
, , ,
Response
No Trackback , No Comment
RSS :
http://b4you.net/blog/rss/response/160


블로그 이미지

빗소리를 먹는 사람.

- 장현준

Notices

Archives

Authors

  1. 장현준

Recent Trackbacks

  1. 듀얼클러치의 생각 rsvin28's me2DAY 2009

Calendar

«   2012/02   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29      

Site Stats

Total hits:
158019
Today:
89
Yesterday:
228