A nice user interface is an important part of a good application besides other criteria like performance, stability/reliability... Personally, I really like following libraries which were published on CodeProject long time ago.
These listed libraries are written in WTL. But it's really hard to mix both MFC & WTL together. Obviously, it's not reasonable to ask a developer or a team to giving up MFC and move to the WTL world just because there were some great controls or visual Frameworks written in WTL (there are many things that should be considered especially in a company with hundreds of developers like the company I work for). Unfortunately, there was no such good and free visual Framework in MFC until now. Whatever difficulties there are, I still desire to be able to use them and now my effort is here to be shared with you.
There are two possible approaches:
- Porting WTL source code to MFC completely: There are some problems with this approach. First, it will take me a lot of time (just to re-write what people did). Second, bug-fixing and enhancement from the original authors will not be up to date. Third, I have to port again if another good WTL-targeted library is published one day. With such reasons in mind, I decide not to follow this direction.
- Mixing MFC & WTL together. I know there are a lot of problems with this approach as shown in the forum of the article Mix up WTL with MFC. Since I don't have an ambition to have a generic way to integrate all WTL-targeted libraries (now and in the future) but just for these above ones, I believe it's possible.
How Does it Work?
Here is the core of the MFC wrapper:
template<class TMFCWnd, class TWTLCWindow>
class ATL_NO_VTABLE CWTL4MFCWndT : public TMFCWnd
typedef TWTLCWindow WTLClass;
virtual void PreSubclassWindow()
m_wndWTLPeer.m_hWnd = m_hWnd;
virtual LRESULT WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
LRESULT lResult = 0;
if(FALSE == m_wndWTLPeer.ProcessWindowMessage
(m_hWnd, nMsg, wParam, lParam, lResult))
lResult = TMFCWnd::WindowProc(nMsg, wParam, lParam);
virtual BOOL PreTranslateMessage(MSG* pMsg)
BOOL blRes1 = __super::PreTranslateMessage(pMsg);
BOOL blRes2 = m_wndWTLPeer.PreTranslateMessage(pMsg);
// if both WTL & MFC handle this message
// there maybe a problem, consider to override
// this method in derived class
ASSERT(FALSE == (blRes2 && blRes1));
return (blRes1 | blRes2);
Not much to say; for each window message (
WM_xxx), if the corresponding WTL peer doesn't handle it, the MFC wrapper will.
Problems occur when a window message (
WM_xxx) is handled by the WTL peer (return
ProcessWindowMessage) but the message is also important for the MFC framework. To resolve this problem, I choose a very simple approach: do testing and workaround case by case.
Applying this library into an existing MFC project is easy; let's take the demo project as your starting point. Here is the class diagram for quick reference.
- Basically, a bug or a request for more features may belong to this MFC wrapper (1) or the original WTL code (2) or both (3). I will try fixing bugs that belong to category (1) and (3) and forward others to the corresponding authors (I will try not to touch WTL code as much as possible unless it's really necessary and of course with consent from original authors)
- Since this library is just a wrapper, please remember to get updates from other authors and the WTL Library too
I'd like to thank Daniel Bowen, Sergey Klimov and Igor Katrayev for their excellent WTL-targeted libraries. Thanks also for their consent to allow me to redistribute their source code (with a little modification) in this article.
- Oct 12, 2007: Initial version