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
114 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:

Window Traits

In the previous article we specified window styles by passing the style and extended style information to CWindowImpl's Create() function.

[listing 2.3]

mainwnd.Create(NULL,CWindow::rcDefault,_T("Main Window"),
               WS_OVERLAPPEDWINDOW);

The Windows Template Library provides another method of specifying these styles: window traits. Window traits work by taking style information and storing it in an instance of a template class. This is done though a template class called CWinTraits. The template takes two DWORD parameters, the style and extended style, and provides methods for accessing them. The definition of CWinTraits is listed below.

[listing 2.4]

template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
class CWinTraits
{
public:
  static DWORD GetWndStyle(DWORD dwStyle)
  {
    return dwStyle == 0 ? t_dwStyle : dwStyle;
  }
  static DWORD GetWndExStyle(DWORD dwExStyle)
  {
    return dwExStyle == 0 ? t_dwExStyle : dwExStyle;
  }
};

The purpose of the GetWndStyle() and GetWndExStyle() functions is rather obvious but their implementation is a bit cryptic. If the value passed to GetWndStyle() and GetWndExStyle() is zero they return the stored style information. If the value passed is not zero, they return the passed value. Admittedly, this seems a little silly. Why not simply return the stored values, drop the parameter, and be done with it? The answer lies in the way the class is used in the WTL libraries. Below is CWindowImpl's Create method.

[listing 2.5]

HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
            DWORD dwStyle = 0, DWORD dwExStyle = 0,
            UINT nID = 0, LPVOID lpCreateParam = NULL)
{
  if (T::GetWndClassInfo().m_lpszOrigName == NULL)
  T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
  ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);

  dwStyle = T::GetWndStyle(dwStyle);
  dwExStyle = T::GetWndExStyle(dwExStyle);

  return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rcPos,
      szWindowName, dwStyle, dwExStyle, nID, atom, lpCreateParam);
}

Notice that the dwStyle and dwExStyle parameters have a default value: zero. Also notice that dwStyle and dwExStyle are passed to GetWndStyle() and GetWndExStyle(), set to the value returned by GetWndStyle() and GetWndExStyle(), and then passed on to CWindowImplBaseT's Create() method. With this set up, if no styles are specified in the call to CWindowImpl::Create() the styles stored in the trait class are used. If styles are passed to CWindowImpl::Create() they override the traits. This useful feature allows us to attach a set of default window styles to our newly implemented window, while users of this new window retain the ability easily override these styles if they happen to not suit the particular instance he or she is creating.

There are times, however, when you don't necessarily want users to replace the trait styles. You may wish to use the trait styles as a set of base styles and only give users of your window class the ability to add a style or two to this minimum set. The CWinTraitsOR class provides this functionality. Simply use it in place of CWinTraits.

To sum up, CWindowImpl derived classes that use a CWinTraits instance for the TWinTraits template parameter will override the stored styles if styles are passed to Create(). CWindowImpl derived classes that use a CWinTraitsOR instance for the TWinTraits template parameter will add any styles passed via Create() to the stored styles and this combined set of styles will be used to create the window.

The WTL library also provides a handful of predefined trait classes. You'll find them used by various window implementation classes provided by the library. For the sake of completeness I've listed their definition below.

[listing 2.6]

typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |
                   WS_CLIPSIBLINGS, 0> CControlWinTraits;
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
                   WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits;
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE |
                   WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
typedef CWinTraits<0, 0> CNullTraits;

Now that we have a thorough understanding of window traits, let's create a trait class for CDxWindowImpl. Make the following changes to CDxWindowImpl.h:

[listing 2.7]

#ifndef __ATLWIN_H__
    #error CDxWindowImpl.h requires atlwin.h to be included first
#endif

typedef CWinTraits<WS_OVERLAPPEDWINDOW,0> CDxAppWinTraits;

template <class T, class TBase = CWindow, class TWinTraits = CDxAppWinTraits >
class CDxWindowImpl : public CWindowImpl<T,TBase, TWinTraits >
{
public:
  BEGIN_MSG_MAP(CDxWindowImpl)
    MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
  END_MSG_MAP()

  LRESULT OnDestroy( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled )
  {
    PostQuitMessage(0);
    bHandled = FALSE;
    return 0;
  }

};

With these changes in place the call to Create() in Main.cpp no longer needs window styles passed to it. At this point rebuilding the project should produce an executable that creates and displays a window.





Window Class Registration


Contents
  Introduction
  Window Traits
  Window Class Registration
  Full Screen and Back

  Source code
  Printable version
  Discuss this article

The Series
  Getting Started
  Windowing