WTL을 사용할 때, GDI 개체를 만들고, SelectObject 계열의 함수들을 사용할 때 C4003 에러를 만나는 경우가 있다. Visual C++ 컴파일러가 주는 에러는 'warning C4003: not enough actual parameters for macro...'와 같은 것일텐데, 에러가 날 곳이 없어 보이는 워낙 단순한 함수라 당황스러울 것이다.
WTL 소스 코드를 봐도 SelectObject 계열의 함수들(SelectBitmap, SelectFont..)은 함수로 구현되어 있지 매크로로 구현되어 있지 않기 때문에 더더욱 이것의 원인을 알기가 어렵다. 이 문제는, WTL이 메세지 크래킹을 지원하기 위해 포함한 windowsx.h에서 정의한 SelectObject 계열 매크로와 충돌하기 때문이다. 즉, 이 문제는 컴파일러에 의한 처리보다 전처리기에 의한 처리가 먼저 일어나기 때문에, 컴파일러가 정확한 원인을 추측하지 못하는 것이다. 이것을 해결하려면, 프리 컴파일 헤더나 해당 소스 코드에 _INC_WINDOWSX를 정의 해주면 된다.
WTL의 atlgdi.h를 살펴보면, 이 정의가 포함되면 메세지 크래커에 포함된 SelectObject 계열 매크로를 undef 하게 되며, 정상적으로 WTL이 래핑한 함수들을 사용할 수 있게 된다. WTL 헤더 파일들은 무엇 때문인지 이 정의를 자동으로 포함하고 있지 않다. 이 문제는 Meyers나 Sutter와 같은 C++ 대가들이 조언하고 있는, '전역 범위의 매크로 사용은 최대한 피하라'의 좋은 사례라 할 수 있을 것이다.
WTL 소스 코드를 봐도 SelectObject 계열의 함수들(SelectBitmap, SelectFont..)은 함수로 구현되어 있지 매크로로 구현되어 있지 않기 때문에 더더욱 이것의 원인을 알기가 어렵다. 이 문제는, WTL이 메세지 크래킹을 지원하기 위해 포함한 windowsx.h에서 정의한 SelectObject 계열 매크로와 충돌하기 때문이다. 즉, 이 문제는 컴파일러에 의한 처리보다 전처리기에 의한 처리가 먼저 일어나기 때문에, 컴파일러가 정확한 원인을 추측하지 못하는 것이다. 이것을 해결하려면, 프리 컴파일 헤더나 해당 소스 코드에 _INC_WINDOWSX를 정의 해주면 된다.
WTL의 atlgdi.h를 살펴보면, 이 정의가 포함되면 메세지 크래커에 포함된 SelectObject 계열 매크로를 undef 하게 되며, 정상적으로 WTL이 래핑한 함수들을 사용할 수 있게 된다. WTL 헤더 파일들은 무엇 때문인지 이 정의를 자동으로 포함하고 있지 않다. 이 문제는 Meyers나 Sutter와 같은 C++ 대가들이 조언하고 있는, '전역 범위의 매크로 사용은 최대한 피하라'의 좋은 사례라 할 수 있을 것이다.