ATL은 MS에서 나온 제품입니다.
빌더 6는 VC++ 6에 준하는 ATL을 제공하고 있습니다.
보통 COM 이나 ActiveX 를 만들때 자연스럽게 사용하게 됩니다.
자세히 알고 사용한다기 보다는 그냥 COM을 형성하기 위한 목적으로 사용하는 경우가 많지요..
하지만 순수 ATL로 COM이 아닌 일반 어플을 만들면 어떻게 될까?
그리고 그 다음은 ATL 7.1과 WTL 7.x를 붙여서 사용해 보면 어떻게 될까.. 하고 생각하다가
한번 간단한 걸로 시도해 보기로 했습니다.
ATL/WTL은 VS로 하는게 자연스럽지만 ... 빌더를 아끼는 개발자로서
빌더에서 어떻게 해보자 싶어 ... Hello world 프로그램을 ATL 로 만든 예를 제시해 봅니다.
원래 VS 2003 에서 테스트한 것인데, VS 2003에는 ATL 7.1 이 내장되어 있고
빌더는 ATL 3.x 대 버전이지만, 기본적인 것은 되므로 간단한 예제는 무리없이 컴파일 됩니다.
VS로 컴파일한 실행화일 크기는 68K 입니다. 단독 실행화일로 크기가 최소한이 되도록 옵션을 조정했습니다)
처음에 옮길 때 쉽게 테스트하기 위해 아래 예제의 빌더 소스는 합친 형태입니다.
하지만 그냥은 컴파일 되지 않고,
빌더와 VS와의 구조적 차이에서 오는 문제 때문에 조금 손을 더 보지 않을 수가 없습니다.
우선 새 프로젝트에서 Console Application으로 선택하고 VCL 사용을 안함으로 합니다.
(VCL은 필요한 경우는 알아서 사용하면 되겠죠 -..-)
그냥 순수 윈도용 프로그램을 하겠다는 상태로 프로젝트를 생성합니다.
여기에 아래 소스를 넣고 컴파일하면 실행화일이 만들어집니다.
빌더는 기본으로 AnsiString 클래스를 포함하기 때문에, 이를 인식시켜주려면
System 유닛을 포함해주어야 합니다. 그렇지 않으면 링커에서 에러를 냅니다.
#incude <system.hpp>를 반드시 해주어야 합니다.
즉 빌더는 default 치로 그냥 AnsiString을 사용할 수 있는 것입니다.
물론 System 유닛에 있는 다른 함수를 사용하는 것도 디폴트로 되어 있습니다.
그리고 rtl.lib을 포함해주어야 합니다.
단독 실행화일로 만들려면 프로젝트 옵션에서 런타임 패키지 사용안함과 링커에서 다이나믹 RTL을
사용하지 않겠다고 해주어야 합니다.
이렇게 해주어야 링크시 에러를 안내고 단독 실행화일로 만들어 낼수 있습니다.
이렇게 만들어낸 실행화일은 172K 크기군요.
VS 보다 좀 크긴 한데 빌더의 다른 기능을 붙여서 쓸수 있다는 생각을 하면 꽤 준수한 것입니다.
처음엔 소스를 그냥 옮겨 링커 에러 잡는데 몇 시간을 소비했습니다.
해외 사이트에 혹 답이 있을까 해서 돌아 댕기다가 도움을 못 얻고.... 결국 스스로 알아냈습니다.
아래는 소스입니다.
C++빌더와 VC++의 경계가 보다 크게 틔이면 좋겠군요.
//---------------------------------------------------------------------------
#include <System.hpp>
#undef MESSAGE_HANDLER
#include <atl/atlbase.h>
extern CComModule _Module;
#include <atl/atlwin.h>
#pragma hdrstop
// 메인 클래스
class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
// 윈도우 클래스명을 등록
DECLARE_WND_CLASS(_T("KTS_Hello"));
private:
// 메세지 맵
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
END_MSG_MAP()
LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&)
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(&ps);
RECT rect;
GetClientRect(&rect);
DrawText(hDC, _T("반갑습니다. ATL/WTL with C++Builder"),
-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(&ps);
return 0;
}
LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL&)
{
PostQuitMessage(0);
return 0;
}
};
//---------------------------------------------------------------------------
#pragma argsused
// main.cpp
CComModule _Module; // ATL 7.0(VS 2002) 부터는 필요없음.
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow)
{
_Module.Init(NULL, hInstance);
String ID = "Test Sample : jsdkts@korea.com"; // 빌더의 강력한 String 도 그냥 쓸수 있다우.
// 윈도우 생성
CMyWindow wnd;
wnd.Create(NULL, CWindow::rcDefault,
_T("ATL/WTL world"), WS_OVERLAPPEDWINDOW | WS_VISIBLE);
wnd.SetWindowText(ID.c_str());
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_Module.Term();
return (int)msg.wParam;
}
// 끝
이건 거저 맛보기 수준입니다. 누구나 할수 있는...
빌더에서 다른 프레임웍을 쓴다는 것은 무척 흥미있는 일입니다.
|