Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
109 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

WTL vs. Win32?

How does the WTL compare to straight Win32 programming? Comparing the performance of this application with a similar one developed using just the Win32 API would be kind of pointless, as far as speed is concerned.  There just isn't enough functionality here to make much of a comparison.  Even with additional functionality the point is rather moot.  Most of the applications time is spent simply waiting for messages.  My release build of the WTL application weighs in at around 40kb, and the Dependency Walker utility reported that it only used the most basic system dll's.  A similar Win32 application weighed in at 36kb (about 4kb smaller) and had exactly the same dependencies as the WTL version.  This isn't surprising since the WTL application had the bare minimum to begin with.  What this 4kb in code size bought us is an object-oriented approach to creating and implementing windows.  Considering the increase in maintainability the WTL code has over the Win32 code, I consider this a bargain.  Below is the Win32 application I used in my comparison.

Win32app.cpp

#include <windows.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                      PSTR szCmdLine, int iCmdShow)
{

     TCHAR    szAppName[] = TEXT("Main Window");
     HWND     hwnd;
     MSG      msg;
     WNDCLASS wndclass;

     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
     wndclass.lpfnWndProc   = WndProc;
     wndclass.cbClsExtra    = 0;
     wndclass.cbWndExtra    = 0;
     wndclass.hInstance     = hInstance;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
     wndclass.lpszMenuName  = NULL;
     wndclass.lpszClassName = szAppName;

     if (!RegisterClass(&wndclass))
     {
          MessageBox(NULL, TEXT("RegisterClass() Failed"), 
                     szAppName, MB_ICONERROR);
          return 0;
     }
     
     hwnd = CreateWindow(szAppName,TEXT("Main Window"),
                         WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
                         CW_USEDEFAULT,CW_USEDEFAULT,
                         CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
     
     ShowWindow(hwnd,iCmdShow);
     UpdateWindow(hwnd);
     
     while (GetMessage(&msg,NULL,0,0))
     {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
     }
     return msg.wParam;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
                          WPARAM wParam, LPARAM lParam)
{     
     switch(message)
     {          
     case WM_DESTROY:
          PostQuitMessage (0);
          return 0;
     }
     return DefWindowProc(hwnd,message,wParam,lParam);
}

WTL vs. MFC?

So, how about MFC?  Again, performance is difficult to measure.  But we do see a big difference in code size and dependencies.  A similar MFC app actually weighed in less than its WTL counterpart, around 16kb.  This is somewhat misleading because a good portion of the code was contained in mfc42.dll.  With static linking the MFC app grew to 100kb, and the Dependency Walker still reported dependencies on comctl32.dll and the bloated shell32.dll.  Not too big a deal but it does demonstrate the kind of overhead an MFC application is subject to that the WTL application gets to avoid.  Below is the MFC application I used for this comparison.

MFCapp.h

class CMyApp : public CWinApp
{
public:
    virtual BOOL InitInstance ();
};

class CMainWindow : public CFrameWnd
{
public:
    CMainWindow ();

protected:
    DECLARE_MESSAGE_MAP ()
};


MFCapp.cpp

#include <afxwin.h>
#include "MFCapp.h"

CMyApp myApp;

BOOL CMyApp::InitInstance ()
{
    m_pMainWnd = new CMainWindow;
    m_pMainWnd->ShowWindow (m_nCmdShow);
    m_pMainWnd->UpdateWindow ();
    return TRUE;
}

BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
END_MESSAGE_MAP ()

CMainWindow::CMainWindow ()
{
    Create (NULL, _T ("Main Window"));
}

Conclusion

In the context of game development our baby application still wants for a few basic features.  For starters it'd be nice to replace the standard background window color with black.  A mechanism for performing idle processing is also needed.  The simple application developed in this article also bothers me in that is doesn't follow the grand tradition of displaying a "Hello World" message.  I decided to leave this last item as an exercise for the reader since the new functionality is relatively simple to add.  Just add a MESSAGE_HANDLER entry for the WM_PAINT message to the message map and use a function like TextOut() to display the text.  The reader is encourage to make any other changes he or she likes.  The files (and project) used in this article will not be needed in the articles to follow.

Those who downloaded the WTL 7.0 libraries will find a WTL AppWizard included with the download (I believe the WTL 3.1 download also includes it but can't quite remember).  The wizard-generated files make for great example code.  And some of the options it provides are just plain cool.  See the WTL's readme file for installation instructions.

In part 2 of this series we'll take an in depth look at the class definition macros, see what exactly it is they do for us, and how to gain greater control of the attributes our CWindowImpl object uses when registering a window class.  We'll also learn how to insert idle processing into our message loop and how to get our hands on messages before they've been translated.  In the meantime I can be reached by emailing rmack005@hotmail.com or by posting a comment in this articles discussion forum, which I'll check frequently.  Comments and suggestions are greatly appreciated.  Now go play.

The code accompanying this article will compile with the WTL 7.1 libraries which can be obtained at the MSDN Download Site.

Acknowledgements

First I'd like to thank Ben "Kylotan" Sizer for the feedback he provided on an early draft of this article.  His comments significantly improved its quality.  I'd like to thank Olga Perez for her efforts to correct my grammar.  You put up a valiant fight, though I'm not sure you won.  And of course, I'd like to thank the staff at Gamedev.net for providing both a home and an audience for this article.  Thanks again everyone.

References

[1]  Michael Park, "ATL 3.0 Window Classes: An Introduction", MSDN.

[2]  Brad King and George Shepherd,  "Inside ATL", Microsoft Press, 1999 (Chapter 14)

[3]  MSDN's CWindow Reference

[4]  MSDN's CWindowImpl Reference

[5]  MSDN's MESSAGE_HANDLER Reference

[The Code Project also hosted a semi-official documentation effort for the WTL. http://www.thecodeproject.com/ -Ed.]




Contents
  Introduction
  Windows Class
  Message Handling
  Conclusion

  Source code
  Printable version
  Discuss this article

The Series
  Getting Started
  Windowing