2. “Hello World!” in ATL
为了避免创建ATL COM EXE SERVER的开销和更好地说明Win32与ATL的内在关系,本例程序基于 1.1
创建一个Win32 Project的程序创建。
对于ATL Windows编程陌生的,于此处不必过于在意,稍后在3.
对Win32和ATL的初步观察和比较会做一定的讲解。
2.1 修改stdafx.h
在1.1创建的Win32代码中移除或注释掉stdafx.h中的:
// Windows Header Files:
#include
<windows.h>
// C RunTime Header Files
#include
<stdlib.h>
#include
<malloc.h>
#include
<memory.h>
#include
<tchar.h>
并在
stdafx.h
中添加如下的
include
语句:
#include
<atlbase.h>
extern
CComModule _Module;
#include
<atlcom.h>
#include
<atlwin.h>
#include
"CWellcomeWindow.h"
2.2 添加CWellcomeWindow.h
#pragma
once
#include
"stdafx.h"
class
CWellcomeWindow : public CWindowImpl<CWellcomeWindow,
CWindow, CFrameWinTraits> {
public
:
DECLARE_WND_CLASS(NULL);
BEGIN_MSG_MAP(CWellcomeWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
END_MSG_MAP()
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
HICON appIcon = LoadIcon(_Module.GetResourceInstance(),
MAKEINTRESOURCE(IDI_LEARNINGWTLPART1_ATL));
this->SetIcon(appIcon);
return 0;
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
PAINTSTRUCT ps;
CComBSTR wellcome(_T("Hello World!"));
HDC hdc; // = this->GetDC();
hdc = this->BeginPaint(&ps); // this->BeginPaint(&ps);
TextOut(hdc, 0, 0, wellcome, wellcome.Length());
this->EndPaint(&ps);
//this->ReleaseDC(hdc);
return 0;
}
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
::PostQuitMessage(0);
return 0;
}
};
2.3 修改win32.cpp
保留WinMain方法声明和
#include
"stdafx.h"语句将其余代码删除或注释掉。添加_Module定义,修改WndMain方法体;完成后的代码如下:
#include
"stdafx.h"
#include
"LearningWTLPart1_ATL.h"
CComModule _Module;
int
APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
_Module.Init(NULL, hInstance);
CComBSTR appTitle;
appTitle.LoadString(_Module.GetResourceInstance(), IDS_APP_TITLE);
CWellcomeWindow wnd;
wnd.Create(NULL, 0, appTitle);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_Module.Term();
return (int) msg.wParam;
}
2.4 Build与程序输出
如果在1.1
创建一个Win32 Project设置了编译器选项的,先将编译器选项设置恢复为默认值即
/TP;
程序输出如下:
以上的程序输出和 1.3 Build
与程序输出对比,似乎缺点什么?!在
Part-2再作交待。
3. ATL vs. Win32
首先,对Win32编程模型作了一个初步介绍,着重介绍ATL编程模型,这里并不存在对二者有孰优孰劣的假设;由于,对于作为M$ Windows程序员来说,或多或少、或直接或间接得都接触过Win32编程模型,故在本节中轻彼而重此。
其次,对Win32程序和ATL程序的Build过程和产生的可执行文件作一个初步的对照。
3.1 编程模型
Win32编程是整个Windows编程的基石,无论是ATL或WTL;因此,即使是ATL也必然包含Win32编程模型的基础构造块,只是ATL提供了轻量的基础构造块的封装(Encapsulation)。
Win32编程模型的基础构造块主要由Register windows class、Create window/Show window、Message loop和WndProc 4部分构成。
3.1.1 Win32基础构造块和主要流程
3.1.2 ATL基础构造块和主要流程
- CComModule::Init & CComModule::Term : 是ATL关于COM Server的部分,在这里不必关注,在后续的WTL学习中还会相应地涉及到;
- Main message loop : 在ATL中保留;
3.2 Build过程和程序输出
对Win32版与ATL版的Debug和Release分别作一个初步的对比;为说明一般性问题,在此不考虑编译器优化,因此,无论是Debug抑或Release均采用编译器默认设置。
|
Debug
|
Release
|
比重
|
Win32版
|
100K
|
68K
|
|
ATL版
|
244K
|
88K
|
D244% | R129%
|
ATL版的Release,无论是物理文件大小还是运行时空间大小或运行效率都与Win32版的Release接近,且二者除系统库外,基本上不需要其它支持库(可能msvcrt.dll,gdi32.dll等)。