본문 바로가기

WTL

CShellFileOpenDialog / CShellFileSaveDialog 사용하기 WTL의 CShellFileOpenDialog / CShellFileSaveDialog는 비스타 이상에서 지원되는 대화상자 컨트롤이다. 이들은 전통적인 대화 상자와 달리, 탐색기과 같은 스타일을 가진다. CShellFileOpenDialog / CShellFileSaveDialog를 사용하려면 WTL의 atldlgs.h를 먼저 포함해야 한다. 이 대화 상자들이 인스턴스화 될 때 플랫폼이 비스타 이상이 아니라면, 인스턴스의 m_spFileDlg는 널(null)이다. 플랫폼이 비스타가 아닐 수도 있다면, 윈도우 버전을 확인하는 절차가 필요할 것이다. 이들은 고전적인 대화 상자와 달리 CShellMultiFileOpenDialog와 같은 클래스가 존재하지 않으며, COM 인터페이스를 사용하여 대화 상자를 조정.. 더보기
ATL/WTL의 메세지 핸들러 매크로 MFC와 ATL/WTL에서 메세지 핸들러를 작성할 때 가장 피부로 느껴지는 차이점은 미리 정의된 메세지 매크로의 존재이다. MFC에서는 이미 잘 포장되어 있는 각각의 컨트롤들의 메세지 핸들러들이 있고, 용도에 맞게 잘 분류되어 있다. 예를 들어, 버튼 메세지에 관한 것이라면 ON_BN_CLICKED과 같은 매크로를 사용하여 메세지 맵에 추가하면 된다. 그러나, ATL/WTL에서는 그러한 지원이 좋은 편이 아니다. ATL 자체가 그러한 것을 위한 고안된 것이 아니니 어쩔 수 없고, WTL의 atlcrack.h에서 이런 용도를 위해 미리 정의해 둔 메세지 매크로를 제공하지만, MFC의 그것처럼 세세하게 구분되어 있지 않다. 예를 들어, 어떤 컨트롤을 클릭했을 때 발동되는 함수를 정의하기 위해서 COMMAND.. 더보기
ATL/WTL 멀티미디어 타이머 사용하기 WTL을 사용할 때 WM_TIMER 메세지가 때때로 오지 않을 경우가 있다. 현재 실행하고 있는 프로세스 안에서 무엇인가가 바쁘게 돌아가고 있다면 WM_TIMER 메세지가 제대로 오지 않을 수도 있다. 어떤 일을 타이머에 맞춰서 간단하게 처리하고 싶을 때, 딱 이런 목적으로 만들어진 WM_TIMER가 제대로 동작하지 않는다면 곤란할 것이다. 그러나, 다른 스레드에서 그 정도로 복잡한 일을 하고 있어서 메세지가 제대로 오지 않는다면, WM_TIMER를 쓰는 것은 맞지 않다. WM_TIMER는 메세지 처리 과정에서 우선 순위가 낮으며, 경우에 따라서 윈도우가 무시해버릴 수도 있기 때문이다. 이런 경우, 멀티미디어 타이머를 사용하는 것이 좋다. 멀티미디어 타이머는 WM_TIMER와 달리 다른 스레드에서 생성되.. 더보기
WTL C4003 error : SelectObject 계열 함수 사용에서의 에러 WTL을 사용할 때, GDI 개체를 만들고, SelectObject 계열의 함수들을 사용할 때 C4003 에러를 만나는 경우가 있다. Visual C++ 컴파일러가 주는 에러는 'warning C4003: not enough actual parameters for macro...'와 같은 것일텐데, 에러가 날 곳이 없어 보이는 워낙 단순한 함수라 당황스러울 것이다. WTL 소스 코드를 봐도 SelectObject 계열의 함수들(SelectBitmap, SelectFont..)은 함수로 구현되어 있지 매크로로 구현되어 있지 않기 때문에 더더욱 이것의 원인을 알기가 어렵다. 이 문제는, WTL이 메세지 크래킹을 지원하기 위해 포함한 windowsx.h에서 정의한 SelectObject 계열 매크로와 충돌하기.. 더보기
MFC와 ATL/WTL에서의 메세지 전달 메커니즘 C/C++을 사용하여 간단한 Windows Application을 만든다고 할 때, MFC나 ATL과 같은 커다란 라이브러리를 사용하는 것은 달갑지 않은 일이다. MFC로 빌드하여 생성되는 바이너리와 링크되는 DLL의 크기는 무시할 수 없을 정도이며, ATL의 경우 코드의 크기는 매우 작지만 단순히 코드의 크기가 이 글의 주제는 아니다. 중요한 프로젝트에 사용할 일이 아니라면, 사용자 인터페이스가 잘 포장되어 있는 이런 라이브러리를 사용하는 것이 마냥 좋다고는 할 수 없다. 편리한만큼 라이브러리 디자인의 발상과 내부 구현 기법을 지나치기 쉽기 때문이다. MFC와 ATL은 비슷한 메세지 전달 방식을 가지고 있지만, 그 구현 방법은 매우 다르다. 가장 큰 이유는 MFC가 만들어질 당시에는 C++ 표준이란게 .. 더보기
Windows Template Library Startup 3 이제 원하는 윈도우의 메세지 핸들러까지 작성했으니, 실제로 WTL 프로그램의 인스턴스화 작업을 준비해보자. PCH를 사용할 stdafx.h과 윈도우 메세지 핸들러를 구현한 mywnd.h가 준비되었다면, 다음은 MFC를 오랫동안 사용해온 사람에게는 기억에서도 흐릿할 WinMain이다. #include "stdafx.h" #include "mywnd.h" CAppModule _Module; 이제, WTL의 MFC에서의 CWinApp에 해당하는 CAppModule을 전역 변수로 선언한다. CAppModule은 ATL의 CComModule을 상속받은 것이며, CWinApp와 비슷한 역할을 하지만 그 성격은 좀 다르다. VC7 이상에서는 이것을 명시적으로 선언할 필요는 없지만, 메세지 루프를 등록하고 윈도우 메세.. 더보기
Windows Template Library Startup 2 WTL을 사용하여 윈도우를 생성하는 것은, 기본적으로 ATL의 윈도우 생성 방식과 동일하다. WTL은 어느 날 갑자기 새롭게 생긴 혁신적인 물건이 아니라, ATL의 골격에 살을 덧붙인 것이다. WTL의 interface / implementation 분리 정책은 사실 ATL에서 온 것이며, ATL이 템플릿을 적극적으로 활용하는 것 또한 HP의 STL 구현 경험에서 영향을 받은 것이다. WTL을 이해하기 위해는, 먼저 ATL의 윈도우 생성, 메세지 전달 방식을 이해해야 한다. ATL에서의 MFC CWnd와 같은 존재라면 CWindow인데, CWindow는 CWnd과 같지 않다. 인터페이스와 구현 모두를 가지고 있는 CWnd과 비교해서 CWindow는 그야말로 인터페이스만 가지고 있으며, 윈도우에 필요한 핸.. 더보기
Windows Template Library Startup 1 WTL을 프로젝트에 이용하기로 마음 먹었다면, PCH(Precompile Header)를 사용하는게 좋다. 대부분의 C++ 컴파일러가 아직 export 키워드를 구현하지 않았기 때문에, 분할 컴파일 모형을 적용할 수 없으며, 템플릿 라이브러리는 아직까지 대부분 헤더 파일만의 형태로 제공된다. 완전히 빈 상태인 stdafx.h와 같은 PCH에서 출발한다면, 다음과 같은 내용이 포함되어야 한다. stdafx.h #include // base ATl classes #include // base WTL classes #include // ATL GUI classes #include // WTL frame window classes #include // WTL enhanced msg map macros #incl.. 더보기
Windows Template Library Installation 사실, WTL과 같은 고전적인 C++ 라이브러리는 MS 입장에서는 더 이상 강력하게 추진할만한 것은 아니다. 무엇보다 .NET이란 대단한 물건을 가지게 되었기 때문인데, 기존의 MFC와 ATL 조합이 복잡하기는 해도 기존의 요구는 그런대로 처리할 수 있기 때문이다. MS에서 WTL을 공식적으로 지원하지 않으며, 오픈 소스로 공개한 것은 위와 같은 이유 때문이다. VMS 유전자를 이어받은 NT 기반 이후의 윈도우들이, 그 특성상 개발 문화가 단일화되고, 전문적이며, 무거워지는 뚜렷한 경향을 보이는 것을 생각한다면, 이러저러한 이유로 오픈 소스로 공개된 WTL은 Windows 최후의 캐주얼한 개발 문화의 상징이라 해도 될 것 같다. ATL은 COM 컴포넌트를 만드는데 대단히 유용한 툴이지만, 전통적인 윈도우.. 더보기
WTL을 사용할 때 주의할 점 Window Template Library(WTL)은 MFC에 비해 아주 작고 빠른 코드를 만들어 낼 수 있으며, 그 구조 또한 MFC와 비교되지 않을 정도로 깔끔하다. MFC 클래스들의 경우, CObject에서부터 개체를 상속 받기 때문에, CWnd에 이르러서는 엄청난 크기를 가진다. 즉, CWnd를 생성하는 것은 대단히 비싼 일이다. 반면, WTL은 interface / implementation이 엄격하게 분리된 구조로 설계되었다. CWnd에 해당하는 WTL의 CWindow은 사실 데이터멤버 밖에 가지고 있지 않으며, 크기가 매우 작다. 따라서, MFC처럼 CWnd 개체를 파라미터나 리턴값으로 사용하기 위해 상대적으로 TemporaryMap을 유지할 필요가 없으며, 이것은 MFC처럼 Idle 타임에.. 더보기