WTL(1)_ATL GUI Classes

WTL for MFC Programmers, Part I - ATL GUI Classes

README.TXT

WTL的使用环境: vc2005 Express和vc6的用户需要注意,  文章是wtl7.1在vc6.0-7.0下测试的, vc7.0-8.0下未知.

WTL的前提知识:  windows API, MFC, 消息处理, c++模板类, ATL类等.

Introduction to the Series

WTL有很多强悍的MFC's GUI类, 但是WTL程序更小。

如果你像我一样学习过MFC的GUI,那么你将很容易使用WTL中这些缩水了的控件,像MFC的消息过滤机制。

如果你想我一样,想把MFC的GUI通过几百K就加载到程序中。

但是,WTL也有一些障碍需要跨越:

o  ATL模板看起来很怪

o  没有ClassWizard支持, 所以手写message maps是必要的。

o  MSDN没有提供文档, 你需要在一些地方找到,甚至是查看WTL源代码.

o  没有标志性的书籍与教程可以买到...

o  MSDN没有官方支持

o  ATL/WTL 窗口程序完全不同于MFC窗口程序, 你并不能将所有MFC的知识搬移过来

WTL的好处:

o  没有复杂的doc/view框架去学习 和 围绕其工作

o  有一些重要的UI特征来自MFC, 例如: DDX/DDV 和 "update command UI"功能

o  MFC一些特征的深入(例如, 更灵活的splitter窗口)

o  更小。 比MFC

o  你可以自己修改WTL-BUG 并且 不影响显存的apps(比起替换MFC/CRT DLLs来修改一个bug in app, 并且使得其他apps也被破坏)

o  如果你仍需要MFC, MFC和ATL/WTL可以并存。(for a prototype at work, I ended up creating an MFC CFrameWnd that contained a WTL CSplitterWindow, which contained MFC CDialogs -- that wasn't me showing off, it was modifying existing MFC code but using the nicer WTL splitter).)

Introduction to Part I

开始WTL前要先复习一下ATL, WTL是一个ATL的附加集合,

如果你是个严禁的MFC程序员,那么你可能还没有进入ATL GUI类。

首先介绍一些 写ATL程序前 必要的点ATL模板,和ATL窗口类

ATL Background

ATL and WTL history

ATL 是ActiveX的库

Since ATL's goal is to make writing COM objects and ActiveX controls easier

Since ATL is really about writing COM objects, it only has the most basic of GUI classes, the equivalent of MFC's CWnd and CDialog

WTL3.0, 7.0命名都是跟随ATL3.0,7.0的

ATL-style templates

ATL中两个不同:

1. 刚声明的类,可以马上出现在继承列表

class CMyWnd : public CWindowImpl<CMyWnd>
{
...
};

2. ATL中的动态绑定:

o  节省空间, 无虚表

o  编译时确定, 可优化

o  不会因为引用空而异常

o  不用指针

ATL Windowing Classes

好的, 背景已经说的足够多了, 是时候深入ATL了。 

ATL被设计为严格的 接口/实现 分离,窗口类的设计自然如此。

这很像COM, 接口和实现分开,可能有很多个实现。

CWindow类

有一个(HWND)类型的全局m_hWnd变量

 有一个operator HWND操作

CWindows的创建很廉价,方便

Cwindows超过作用域后 关联的窗口不销毁

CWindowImpl特征

包含:

registration class

subclassing

message map

WindowProc()

CDialogImpl, CAxDialogImpl特征

总有两个分离的对话框类:

CDialogImpl, CAxDialogImpl

前者简单窗口,后者包含ActiveX控件的窗口

Defining a Window Implementation

任何非对话框窗口必须继承于CWindowImpl:

1. 窗口定义

2. message map

3. default styles to window, called the window traits

  窗口样式宏

DECLARE_WND_CLASS     定义窗口名
DECLARE_WND_CLASS_EX    定义类样式,背景颜色等其他属性

   消息映射

BEGIN_MSG_MAP(CMyWindow)
END_MSG_MAP()

  有很多预定义样式, 类似如下:

typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE>
CFrameWinTraits;

Filling in the message map

ATL消息映射 是WTL不友好的特性之一, 同时其他一些特性被WTL大大改进。
ClassView 给你增加消息 处理的能力, 但ATL没有消息相关的宏,传入参数自动解包的宏,MFC有。
ATL中只有3种消息处理WM_NOTIFY, WM_COMMOND,     和其他所有消息
对应NOTIFY_HANDLER, COMMAN_ID_HANDLER, MESSAGE_HANDLER, CHAIN_MSG_MAP,
来让我们添加WM_CLOSE和WM_DESTROY处理,为我们的窗口。

you set bHandled to FALSE. 可以在自己的处理函数完成后, 交给系统默认处理函数。在MFC下是显示调用return WinDefine(xxx,xxx,xxx,xxx);

Advanced Message Maps and Mix-in Classes

一点重要的不同ATL可以在任何C++类里处理消息, 不像MFC消息处理被分为CWnd过滤到CCmdTarget, 外加一些类有PreTranslateMessage()过滤方法。
这个特征 让我们可以写出混合类, 以至我们可以很容易的在 继承类中 增加窗口特征。
A base class with a message map is usually a template that takes the derived class name as a template parameter, so it can access members of the derived class like m_hWnd (the HWND member in CWindow). Let's look at a mix-in class that paints the window background by handlingWM_ERASEBKGND.
一个带有消息循环的 基础类, 通常 是一个模板<ChildName>,参数是派生类的名字。
这样它可以进入 派生类的成员
...
 LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
...
 pT->GetClientRect ( &rcClient );
}
首先, 编译器检查 我们调用派生类的方法 GetClientRect是否存在, 然后OnEraseBkgnd被执行。

class CMyWindow : public CWindowImpl<CMyWindow, CWindow, CFrameWinTraits>,
public CPaintBkgnd<CMyWindow, RGB(0,0,255)>
大把大把继承

typedef CPaintBkgnd<CMyWindow, RGB(0,0,255)> CPaintBkgndBase;

CHAIN_MSG_MAP(CPaintBkgndBase)

 

Any messages that reach the CHAIN_MSG_MAP line without being handled are passed on to the map in CPaintBkgnd. Note that WM_CLOSE,WM_DESTROY, and IDC_ABOUT will not be chained, because once those are handled, the message map search ends.

任何消息 到达 CHAIN_MSG_MAP时,都会抛向 指定类去处理。除了WM_CLOSE,WM_DESTROY,IDC_ABOUT它们直接退出。

不像MFC, MFC总将没有处理的消息 传给基础类。

Structure of an ATL EXE

下面看下如何使用CWinApp全局对象, 在MFC里叫theApp, 

在ATL里,VC6和VC7叫法不同, 会分开讲解:

见程序

Dialogs in ATL

两个Dialog类, 这里有其中之一: CDialogImpl

有两点和framewindow不同:

1. CDialogImpl 代替 CWindowImpl

2. 需要定义公共变量 IDD 对应资源ID 


posted on 2011-02-23 22:54  oleeceo  阅读(706)  评论(0)    收藏  举报

导航