WTL Madness
I'm in the middle of a little downtime right now. I'm waiting for feedback on
the map editor and Cari's getting the GalCiv2 codebase integrated with our demo
stuff. Scott is well on his way with Political Machine so I'm stuck here with
nothing to do Well not really, but nothing that's immediately pressing right
now. I've decided to use this time to learn as much as I can about WTL.
Ian introduced me to WTL a couple of weeks ago. For those who don't know what
it is already, WTL is a stand in replacement for MFC. It's based on ATL so it's
template heavy. Cool stuff if you like it. I learned to like templates at my
last job. There are ports of you more common MFC utility classes (CPoint,
CString, etc..).
There are numerous resources for the WTL. Right now it's unsupported by M$ so
the community has come together to support it.
Yahoo! Groups - wtl
The Code Project - Free Source Code
and Tutorials
IDevResource.com - WTL (Windows
Template Library)
WTL Programming (CodeGuru)
The best tutorials I've found are on CodeProject. I'm not going to bore you
with a tutorial. You can find that somewhere else.
I did find a couple of snippets really interesting though. I haven't gone
through them yet to make them useful, but here's what I'm talking about.
Self Referencing Templates:
This is a trick I learned about at my last job. It's are really cool trick
to know. You can reference your type in a template definition.
template <class T>
class A
{
};
class B : public A<B>
{
};
There are a lot of uses for this trick. WTL uses it exstensively. It's really
neat.
Message Maps:
You can derive classes that are just message maps and manually chain them
together. This is one part I'm really interested in. I'm not sure if this will
work, but check out this situation:
Here's
the logic for a left click in the map editor. Currently, there's one function
that handles all this.
void LeftClick()
{
if(addingStars)
{
// Add Stars
}
else if(addingPlanets)
{
// Add Planets
}
else if(addingShps)
{
// Add Ships
}
}
That function can get pretty big and ugly pretty fast. With the WTL, I think
we can make this more modular using mixin message maps.
class AddStarMessageMap
{
BEGIN_MSG_MAP(AddStarMessageMap)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
END_MSG_MAP()
};
class AddPlanetMessageMap
{
BEGIN_MSG_MAP(AddPlanetMessageMap)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
END_MSG_MAP()
};
class AddShipMessageMap
{
BEGIN_MSG_MAP(AddShipMessageMap)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
END_MSG_MAP()
};
class EditorView
{
BEGIN_MSG_MAP(EditorView)
CHAIN_MSG_MAP(AddStarMessageMap)
CHAIN_MSG_MAP(AddPlanetMessageMap)
CHAIN_MSG_MAP(AddShipMessageMap)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
END_MSG_MAP()
};
Message Cracks:
atlcrack.h provides you with pre-defined MFC style message maps. Standard
WTL messages are handeld through a message handler like:
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
LRESULT OnLButtonDown(UINT, WPARAM, LPARAM, BOOL&);
atlcrack gives you shortcuts:
MSG_WM_LBUTTONDOWN(OnLButtonDown)
LRESULT OnLButtonDown(UINT, CPoint);
Anyways, that's my hope. I'd better get crackin' on it. I'll let you know how
it goes.
There are a few gotchas that I noticed.
- You can't use the cracked messages (atlcrack.h) on CMessageMap derived
classes. The macro only works for CWindowImpl classes. Bummer. I have to crack
them myself.
- I had to tie the message maps to the window implementation to share data.
That means that I couldn't easily re-use them with another class. I'm sure I
could come up with a different way that makes the message maps more modular,
but I'd have to think about it more. Using the self referencing templates was
cool even if it did make me feel dirty writing "pThis->". Ugh.
LRESULT OnLButtonDown(UINT, WPARAM, LPARAM,
BOOL&)
{
T* pThis = static_cast<T*>(this);
bHandled = pThis->GetMode() == ID_MODE_STAR;
if(bHandled)
{
// Do star stuff
}
return 0;
}
- You can't chain the WM_PAINT message. The first CPaintDC created does the
painting. Anything after that doesn't paint anymore. To get around it, I
manually call the OnPaint functions for each of the derived message maps. Not
a biggy.
It works. I managed to create a little app with 3 separate message maps. I'm
not sure if it was useful other than as an excersize. I'll have to use it more
to get more familiar with WTL. I only scratched the surface. There's way more
you can do and I probably will do in the future.