]> git.saurik.com Git - wxWidgets.git/commitdiff
cleanup the Win32 window classes registration code: remove global variables and regis...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 29 Nov 2008 22:19:55 +0000 (22:19 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 29 Nov 2008 22:19:55 +0000 (22:19 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57030 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/app.h
include/wx/msw/window.h
src/msw/app.cpp
src/msw/glcanvas.cpp
src/msw/mdi.cpp
src/msw/toplevel.cpp
src/msw/window.cpp

index e45caf78a30034dbed236739bad446ff6c8accf6..62c6668f1aa408bb11967638407e11b2bb8b79f4 100644 (file)
@@ -25,8 +25,6 @@ class WXDLLIMPEXP_FWD_BASE wxLog;
 // a new App object to start application
 class WXDLLIMPEXP_CORE wxApp : public wxAppBase
 {
-    DECLARE_DYNAMIC_CLASS(wxApp)
-
 public:
     wxApp();
     virtual ~wxApp();
@@ -50,13 +48,40 @@ public:
     virtual bool OnExceptionInMainLoop();
 #endif // wxUSE_EXCEPTIONS
 
+    // MSW-specific from now on
+    // ------------------------
+
+    // this suffix should be appended to all our Win32 class names to obtain a
+    // variant registered without CS_[HV]REDRAW styles
+    static const wxChar *GetNoRedrawClassSuffix() { return _T("NR"); }
+
+    // get the name of the registered Win32 class with the given (unique) base
+    // name: this function constructs the unique class name using this name as
+    // prefix, checks if the class is already registered and registers it if it
+    // isn't and returns the name it was registered under (or NULL if it failed)
+    //
+    // the registered class will always have CS_[HV]REDRAW and CS_DBLCLKS
+    // styles as well as any additional styles specified as arguments here; and
+    // there will be also a companion registered class identical to this one
+    // but without CS_[HV]REDRAW whose name will be the same one but with
+    // GetNoRedrawClassSuffix()
+    //
+    // the background brush argument must be either a COLOR_XXX standard value
+    // or (default) -1 meaning that the class paints its background itself
+    static const wxChar *GetRegisteredClassName(const wxChar *name,
+                                                int bgBrushCol = -1,
+                                                int extraStyles = 0);
+
+    // return true if this name corresponds to one of the classes we registered
+    // in the previous GetRegisteredClassName() calls
+    static bool IsRegisteredClassName(const wxString& name);
+
 protected:
     int    m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT
 
 public:
-    // Implementation
-    static bool RegisterWindowClasses();
-    static bool UnregisterWindowClasses();
+    // unregister any window classes registered by GetRegisteredClassName()
+    static void UnregisterWindowClasses();
 
 #if wxUSE_RICHEDIT
     // initialize the richedit DLL of (at least) given version, return true if
@@ -79,6 +104,7 @@ public:
 protected:
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxApp)
+    DECLARE_DYNAMIC_CLASS(wxApp)
 };
 
 #ifdef __WXWINCE__
index 3f068dddd6911fc6da30df84fcd9a338031b75de..ededcaeca732243b14135e9f6d7ea58365c81821 100644 (file)
@@ -245,6 +245,9 @@ public:
     // get the HWND to be used as parent of this window with CreateWindow()
     virtual WXHWND MSWGetParent() const;
 
+    // get the Win32 window class name used by all wxWindow objects by default
+    static const wxChar *MSWGetRegisteredClassName();
+
     // creates the window of specified Windows class with given style, extended
     // style, title and geometry (default values
     //
index 2a65e8139e0d5e3382d11a44f709807e3bd5a46d..00f768bf6b4bf5b66bced1c76581ef6fb0f626ea 100644 (file)
@@ -51,6 +51,7 @@
 #include "wx/evtloop.h"
 #include "wx/thread.h"
 #include "wx/scopeguard.h"
+#include "wx/vector.h"
 
 #include "wx/msw/private.h"
 #include "wx/msw/dc.h"
 extern void wxSetKeyboardHook(bool doIt);
 #endif
 
-WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName = NULL;
-WXDLLIMPEXP_CORE const wxChar *wxCanvasClassNameNR = NULL;
-WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassName = NULL;
-WXDLLIMPEXP_CORE const wxChar *wxMDIFrameClassNameNoRedraw = NULL;
-WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassName = NULL;
-WXDLLIMPEXP_CORE const wxChar *wxMDIChildFrameClassNameNoRedraw = NULL;
+namespace
+{
+
+struct ClassRegInfo
+{
+    // the base name of the class: this is used to construct the unique name in
+    // RegisterClassWithUniqueNames()
+    wxString basename;
+
+    // the name of the registered class with and without CS_[HV]REDRAW styles
+    wxString regname,
+             regnameNR;
+};
+
+wxVector<ClassRegInfo> gs_regClassesInfo;
+
+} // anonymous namespace
 
 // ----------------------------------------------------------------------------
 // private functions
@@ -620,8 +632,6 @@ bool wxApp::Initialize(int& argc, wxChar **argv)
 
     wxOleInitialize();
 
-    RegisterWindowClasses();
-
 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
     wxSetKeyboardHook(true);
 #endif
@@ -632,143 +642,106 @@ bool wxApp::Initialize(int& argc, wxChar **argv)
 }
 
 // ---------------------------------------------------------------------------
-// RegisterWindowClasses
+// Win32 window class registration
 // ---------------------------------------------------------------------------
 
-// This function registers the given class name and stores a pointer to a
-// heap-allocated copy of it at the specified location, it must be deleted
-// later.
-static void RegisterAndStoreClassName(const wxString& uniqueClassName,
-                                      const wxChar **className,
-                                      WNDCLASS *lpWndClass)
+/* static */
+const wxChar *wxApp::GetRegisteredClassName(const wxChar *name,
+                                            int bgBrushCol,
+                                            int extraStyles)
 {
-    const size_t length = uniqueClassName.length() + 1; // for trailing NUL
-    wxChar * const newChars = new wxChar[length];
-    wxStrlcpy(newChars, uniqueClassName, length);
-    *className = newChars;
-    lpWndClass->lpszClassName = *className;
-
-    if ( !::RegisterClass(lpWndClass) )
+    const size_t count = gs_regClassesInfo.size();
+    for ( size_t n = 0; n < count; n++ )
     {
-        wxLogLastError(wxString::Format(wxT("RegisterClass(%s)"), newChars));
+        if ( gs_regClassesInfo[n].basename == name )
+            return gs_regClassesInfo[n].regname;
     }
-}
 
-// This function registers the class defined by the provided WNDCLASS struct
-// contents using a unique name constructed from the specified base name and
-// and a suffix unique to this library instance. It also stores the generated
-// unique names for normal and "no redraw" versions of the class in the
-// provided variables, caller must delete their contents later.
-static void RegisterClassWithUniqueNames(const wxString& baseName,
-                                         const wxChar **className,
-                                         const wxChar **classNameNR,
-                                         WNDCLASS *lpWndClass)
-{
-    // for each class we register one with CS_(V|H)REDRAW style and one
-    // without for windows created with wxNO_FULL_REDRAW_ON_REPAINT flag
-    static const long styleNormal = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
-    static const long styleNoRedraw = CS_DBLCLKS;
-
-    const wxString uniqueSuffix(wxString::Format(wxT("@%p"), className));
-
-    wxString uniqueClassName(baseName + uniqueSuffix);
-    lpWndClass->style = styleNormal;
-    RegisterAndStoreClassName(uniqueClassName, className, lpWndClass);
-
-    // NB: remember that code elsewhere supposes that no redraw class names
-    //     use the same names as normal classes with "NR" suffix so we must put
-    //     "NR" at the end instead of using more natural baseName+"NR"+suffix
-    wxString uniqueClassNameNR(uniqueClassName + wxT("NR"));
-    lpWndClass->style = styleNoRedraw;
-    RegisterAndStoreClassName(uniqueClassNameNR, classNameNR, lpWndClass);
-}
-
-// TODO we should only register classes really used by the app. For this it
-//      would be enough to just delay the class registration until an attempt
-//      to create a window of this class is made.
-bool wxApp::RegisterWindowClasses()
-{
+    // we need to register this class
     WNDCLASS wndclass;
     wxZeroMemory(wndclass);
 
-    // the fields which are common to all classes
     wndclass.lpfnWndProc   = (WNDPROC)wxWndProc;
     wndclass.hInstance     = wxhInstance;
-    wndclass.hCursor       = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
-
-    // register the class for all normal windows and "no redraw" frames
-    wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
-    RegisterClassWithUniqueNames(wxT("wxWindowClass"),
-                                 &wxCanvasClassName,
-                                 &wxCanvasClassNameNR,
-                                 &wndclass);
-
-    // Register the MDI frame window class and "no redraw" MDI frame
-    wndclass.hbrBackground = (HBRUSH)NULL; // paint MDI frame ourselves
-    RegisterClassWithUniqueNames(wxT("wxMDIFrameClass"),
-                                 &wxMDIFrameClassName,
-                                 &wxMDIFrameClassNameNoRedraw,
-                                 &wndclass);
-
-    // Register the MDI child frame window class and "no redraw" MDI child frame
-    wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
-    RegisterClassWithUniqueNames(wxT("wxMDIChildFrameClass"),
-                                 &wxMDIChildFrameClassName,
-                                 &wxMDIChildFrameClassNameNoRedraw,
-                                 &wndclass);
-
-    return true;
-}
-
-// ---------------------------------------------------------------------------
-// UnregisterWindowClasses
-// ---------------------------------------------------------------------------
-
-// This function unregisters the class with the given name and frees memory
-// allocated for it by RegisterAndStoreClassName().
-static bool UnregisterAndFreeClassName(const wxChar **ppClassName)
-{
-    bool retval = true;
-
-    if ( !::UnregisterClass(*ppClassName, wxhInstance) )
+    wndclass.hCursor       = ::LoadCursor(NULL, IDC_ARROW);
+    wndclass.hbrBackground = (HBRUSH)wxUIntToPtr(bgBrushCol + 1);
+    wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | extraStyles;
+
+
+    ClassRegInfo regClass;
+    regClass.basename = name;
+
+    // constuct a unique suffix to allow registering the class with the same
+    // base name in a main application using wxWidgets and a DLL using
+    // wxWidgets loaded into its address space: as gs_regClassesInfo variable
+    // is different in them, we're going to obtain a unique prefix by using its
+    // address here
+    regClass.regname = regClass.basename +
+                            wxString::Format(wxT("@%p"), &gs_regClassesInfo);
+    wndclass.lpszClassName = regClass.regname.wx_str();
+    if ( !::RegisterClass(&wndclass) )
     {
-        wxLogLastError(
-                wxString::Format(wxT("UnregisterClass(%s)"), *ppClassName));
+        wxLogLastError(wxString::Format(wxT("RegisterClass(%s)"),
+                       regClass.regname));
+        return NULL;
+    }
 
-        retval = false;
+    // NB: remember that code elsewhere supposes that no redraw class names
+    //     use the same names as normal classes with "NR" suffix so we must put
+    //     "NR" at the end instead of using more natural basename+"NR"+suffix
+    regClass.regnameNR = regClass.regname + GetNoRedrawClassSuffix();
+    wndclass.style &= ~(CS_HREDRAW | CS_VREDRAW);
+    wndclass.lpszClassName = regClass.regnameNR.wx_str();
+    if ( !::RegisterClass(&wndclass) )
+    {
+        wxLogLastError(wxString::Format(wxT("RegisterClass(%s)"),
+                       regClass.regname));
+        ::UnregisterClass(regClass.regname, wxhInstance);
+        return NULL;
     }
 
-    delete [] (wxChar*) *ppClassName;
-    *ppClassName = NULL;
+    gs_regClassesInfo.push_back(regClass);
 
-    return retval;
+    // take care to return the pointer which will remain valid after the
+    // function returns (it could be invalidated later if new elements are
+    // added to the vector and it's reallocated but this shouldn't matter as
+    // this pointer should be used right now, not stored)
+    return gs_regClassesInfo.back().regname.wx_str();
 }
 
-bool wxApp::UnregisterWindowClasses()
+bool wxApp::IsRegisteredClassName(const wxString& name)
 {
-    bool retval = true;
-
-#ifndef __WXMICROWIN__
-    if ( !UnregisterAndFreeClassName(&wxMDIFrameClassName) )
-        retval = false;
-
-    if ( !UnregisterAndFreeClassName(&wxMDIFrameClassNameNoRedraw) )
-        retval = false;
-
-    if ( !UnregisterAndFreeClassName(&wxMDIChildFrameClassName) )
-        retval = false;
+    const size_t count = gs_regClassesInfo.size();
+    for ( size_t n = 0; n < count; n++ )
+    {
+        if ( gs_regClassesInfo[n].regname == name ||
+                gs_regClassesInfo[n].regnameNR == name )
+            return true;
+    }
 
-    if ( !UnregisterAndFreeClassName(&wxMDIChildFrameClassNameNoRedraw) )
-        retval = false;
+    return false;
+}
 
-    if ( !UnregisterAndFreeClassName(&wxCanvasClassName) )
-        retval = false;
+void wxApp::UnregisterWindowClasses()
+{
+    const size_t count = gs_regClassesInfo.size();
+    for ( size_t n = 0; n < count; n++ )
+    {
+        const ClassRegInfo& regClass = gs_regClassesInfo[n];
+        if ( !::UnregisterClass(regClass.regname, wxhInstance) )
+        {
+            wxLogLastError(wxString::Format(wxT("UnregisterClass(%s)"),
+                           regClass.regname));
+        }
 
-    if ( !UnregisterAndFreeClassName(&wxCanvasClassNameNR) )
-        retval = false;
-#endif // __WXMICROWIN__
+        if ( !::UnregisterClass(regClass.regnameNR, wxhInstance) )
+        {
+            wxLogLastError(wxString::Format(wxT("UnregisterClass(%s)"),
+                           regClass.regnameNR));
+        }
+    }
 
-    return retval;
+    gs_regClassesInfo.clear();
 }
 
 void wxApp::CleanUp()
index 9ef0f75d0c43d4291d753157f9810ce5f5652366..c8a84f6cf6dfaeea38375aa471cfe14c946a7dc0 100644 (file)
@@ -29,7 +29,6 @@
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/app.h"
-    #include "wx/module.h"
 #endif
 
 #include "wx/msw/private.h"
@@ -104,110 +103,6 @@ LRESULT WXDLLEXPORT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message,
 #  pragma comment( lib, "glu32" )
 #endif
 
-// ----------------------------------------------------------------------------
-// constants
-// ----------------------------------------------------------------------------
-
-static const wxChar *wxGLCanvasClassName = wxT("wxGLCanvasClass");
-static const wxChar *wxGLCanvasClassNameNoRedraw = wxT("wxGLCanvasClassNR");
-
-// ============================================================================
-// implementation
-// ============================================================================
-
-// ----------------------------------------------------------------------------
-// wxGLModule is responsible for unregistering wxGLCanvasClass Windows class
-// ----------------------------------------------------------------------------
-
-class wxGLModule : public wxModule
-{
-public:
-    bool OnInit() { return true; }
-    void OnExit() { UnregisterClasses(); }
-
-    // register the GL classes if not done yet, return true if ok, false if
-    // registration failed
-    static bool RegisterClasses();
-
-    // unregister the classes, done automatically on program termination
-    static void UnregisterClasses();
-
-private:
-    // wxGLCanvas is only used from the main thread so this is MT-ok
-    static bool ms_registeredGLClasses;
-
-    DECLARE_DYNAMIC_CLASS(wxGLModule)
-};
-
-IMPLEMENT_DYNAMIC_CLASS(wxGLModule, wxModule)
-
-bool wxGLModule::ms_registeredGLClasses = false;
-
-/* static */
-bool wxGLModule::RegisterClasses()
-{
-    if ( ms_registeredGLClasses )
-        return true;
-
-    // We have to register a special window class because we need the CS_OWNDC
-    // style for GLCanvas: some OpenGL drivers are buggy and don't work with
-    // windows without this style
-    WNDCLASS wndclass;
-
-    // the fields which are common to all classes
-    wndclass.lpfnWndProc   = (WNDPROC)wxWndProc;
-    wndclass.cbClsExtra    = 0;
-    wndclass.cbWndExtra    = sizeof( DWORD ); // VZ: what is this DWORD used for?
-    wndclass.hInstance     = wxhInstance;
-    wndclass.hIcon         = (HICON) NULL;
-    wndclass.hCursor       = ::LoadCursor((HINSTANCE)NULL, IDC_ARROW);
-    wndclass.lpszMenuName  = NULL;
-
-    // Register the GLCanvas class name
-    wndclass.hbrBackground = (HBRUSH)NULL;
-    wndclass.lpszClassName = wxGLCanvasClassName;
-    wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
-
-    if ( !::RegisterClass(&wndclass) )
-    {
-        wxLogLastError(wxT("RegisterClass(wxGLCanvasClass)"));
-        return false;
-    }
-
-    // Register the GLCanvas class name for windows which don't do full repaint
-    // on resize
-    wndclass.lpszClassName = wxGLCanvasClassNameNoRedraw;
-    wndclass.style        &= ~(CS_HREDRAW | CS_VREDRAW);
-
-    if ( !::RegisterClass(&wndclass) )
-    {
-        wxLogLastError(wxT("RegisterClass(wxGLCanvasClassNameNoRedraw)"));
-
-        ::UnregisterClass(wxGLCanvasClassName, wxhInstance);
-
-        return false;
-    }
-
-    ms_registeredGLClasses = true;
-
-    return true;
-}
-
-/* static */
-void wxGLModule::UnregisterClasses()
-{
-    // we need to unregister the classes in case we're in a DLL which is
-    // unloaded and then loaded again because if we don't, the registration is
-    // going to fail in wxGLCanvas::Create() the next time we're loaded
-    if ( ms_registeredGLClasses )
-    {
-        ::UnregisterClass(wxGLCanvasClassName, wxhInstance);
-        ::UnregisterClass(wxGLCanvasClassNameNoRedraw, wxhInstance);
-
-        ms_registeredGLClasses = false;
-    }
-}
-
 // ----------------------------------------------------------------------------
 // wxGLContext
 // ----------------------------------------------------------------------------
@@ -297,13 +192,6 @@ bool wxGLCanvas::CreateWindow(wxWindow *parent,
 {
     wxCHECK_MSG( parent, false, wxT("can't create wxWindow without parent") );
 
-    if ( !wxGLModule::RegisterClasses() )
-    {
-        wxLogError(_("Failed to register OpenGL window class."));
-
-        return false;
-    }
-
     if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) )
         return false;
 
@@ -319,7 +207,8 @@ bool wxGLCanvas::CreateWindow(wxWindow *parent,
     DWORD msflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
     msflags |= MSWGetStyle(style, &exStyle);
 
-    if ( !MSWCreate(wxGLCanvasClassName, NULL, pos, size, msflags, exStyle) )
+    if ( !MSWCreate(wxApp::GetRegisteredClassName(_T("wxGLCanvas"), -1, CS_OWNDC),
+                    NULL, pos, size, msflags, exStyle) )
         return false;
 
     m_hDC = ::GetDC(GetHwnd());
index 0fd04ab62cfc51e31dd5867dcbb51c014517232c..6b9cdbcc9a139cfab1d987421525fc7426e237c4 100644 (file)
@@ -52,9 +52,6 @@
 
 extern wxMenu *wxCurrentPopupMenu;
 
-extern const wxChar *wxMDIFrameClassName;   // from app.cpp
-extern const wxChar *wxMDIChildFrameClassName;
-extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
 extern void wxRemoveHandleAssociation(wxWindow *win);
 
 // ---------------------------------------------------------------------------
@@ -188,7 +185,7 @@ bool wxMDIParentFrame::Create(wxWindow *parent,
   msflags &= ~WS_VSCROLL;
   msflags &= ~WS_HSCROLL;
 
-  if ( !wxWindow::MSWCreate(wxMDIFrameClassName,
+  if ( !wxWindow::MSWCreate(wxApp::GetRegisteredClassName(_T("wxMDIFrame")),
                             title.wx_str(),
                             pos, size,
                             msflags,
@@ -736,9 +733,12 @@ bool wxMDIChildFrame::Create(wxMDIParentFrame *parent,
 
   MDICREATESTRUCT mcs;
 
-  mcs.szClass = style & wxFULL_REPAINT_ON_RESIZE
-                    ? wxMDIChildFrameClassName
-                    : wxMDIChildFrameClassNameNoRedraw;
+  wxString className =
+      wxApp::GetRegisteredClassName(_T("wxMDIChildFrame"), COLOR_WINDOW);
+  if ( !(style & wxFULL_REPAINT_ON_RESIZE) )
+      className += wxApp::GetNoRedrawClassSuffix();
+
+  mcs.szClass = className.wx_str();
   mcs.szTitle = title.wx_str();
   mcs.hOwner = wxGetInstance();
   if (x != wxDefaultCoord)
index 20725c1ca47717db9b884b1717d85911828a7adb..0e53428192eaa3ec5f308cda688795c483704b7f 100644 (file)
@@ -78,13 +78,6 @@ static inline bool IsZoomed(HWND WXUNUSED(hwnd)) { return false; }
 LONG APIENTRY _EXPORT
 wxDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
 
-// ----------------------------------------------------------------------------
-// globals
-// ----------------------------------------------------------------------------
-
-// the name of the default wxWidgets class
-extern const wxChar *wxCanvasClassName;
-
 // ----------------------------------------------------------------------------
 // wxTLWHiddenParentModule: used to manage the hidden parent window (we need a
 // module to ensure that the window is always deleted)
@@ -490,7 +483,8 @@ bool wxTopLevelWindowMSW::CreateFrame(const wxString& title,
         exflags |= WS_EX_LAYOUTRTL;
 #endif
 
-    return MSWCreate(wxCanvasClassName, title.wx_str(), pos, sz, flags, exflags);
+    return MSWCreate(MSWGetRegisteredClassName(),
+                     title.wx_str(), pos, sz, flags, exflags);
 }
 
 bool wxTopLevelWindowMSW::Create(wxWindow *parent,
index 48f8daade2f6d71935771a00e7728ac86f47a033..22913dd508fff55dbd5db766390082f0d4116a9a 100644 (file)
 extern wxMenu *wxCurrentPopupMenu;
 #endif
 
-extern const wxChar *wxCanvasClassName;
-
 // true if we had already created the std colour map, used by
 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT)
 static bool gs_hasStdCmap = false;
@@ -585,6 +583,12 @@ wxWindowMSW::~wxWindowMSW()
 
 }
 
+/* static */
+const wxChar *wxWindowMSW::MSWGetRegisteredClassName()
+{
+    return wxApp::GetRegisteredClassName(_T("wxWindow"), COLOR_BTNFACE);
+}
+
 // real construction (Init() must have been called before!)
 bool wxWindowMSW::Create(wxWindow *parent,
                          wxWindowID id,
@@ -617,7 +621,8 @@ bool wxWindowMSW::Create(wxWindow *parent,
         msflags |= WS_VISIBLE;
     }
 
-    if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+    if ( !MSWCreate(MSWGetRegisteredClassName(),
+                    NULL, pos, size, msflags, exstyle) )
         return false;
 
     InheritAttributes();
@@ -1272,31 +1277,12 @@ void wxWindowMSW::DissociateHandle()
 bool wxCheckWindowWndProc(WXHWND hWnd,
                           WXFARPROC WXUNUSED(wndProc))
 {
-// TODO: This list of window class names should be factored out so they can be
-// managed in one place and then accessed from here and other places, such as
-// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
-
-    extern const wxChar *wxCanvasClassName;
-    extern const wxChar *wxCanvasClassNameNR;
-    extern const wxChar *wxMDIFrameClassName;
-    extern const wxChar *wxMDIFrameClassNameNoRedraw;
-    extern const wxChar *wxMDIChildFrameClassName;
-    extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
-    wxString str(wxGetWindowClass(hWnd));
-    if (str == wxCanvasClassName ||
-        str == wxCanvasClassNameNR ||
-#if wxUSE_GLCANVAS
-        str == _T("wxGLCanvasClass") ||
-        str == _T("wxGLCanvasClassNR") ||
-#endif // wxUSE_GLCANVAS
-        str == wxMDIFrameClassName ||
-        str == wxMDIFrameClassNameNoRedraw ||
-        str == wxMDIChildFrameClassName ||
-        str == wxMDIChildFrameClassNameNoRedraw ||
-        str == _T("wxTLWHiddenParent"))
-        return true; // Effectively means don't subclass
-    else
-        return false;
+    const wxString str(wxGetWindowClass(hWnd));
+
+    // TODO: get rid of wxTLWHiddenParent special case (currently it's not
+    //       registered by wxApp but using ad hoc code in msw/toplevel.cpp);
+    //       there is also a hidden window class used by sockets &c
+    return wxApp::IsRegisteredClassName(str) || str == _T("wxTLWHiddenParent");
 }
 
 // ----------------------------------------------------------------------------
@@ -3676,6 +3662,11 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     // especially for wxTLWs
     wxCHECK_MSG( !m_hWnd, true, "window can't be recreated" );
 
+    // this can happen if this function is called using the return value of
+    // wxApp::GetRegisteredClassName() which failed
+    wxCHECK_MSG( wclass, false, "failed to register window class?" );
+
+
     // choose the position/size for the new window
     int x, y, w, h;
     (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
@@ -3690,7 +3681,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     wxString className(wclass);
     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
     {
-        className += wxT("NR");
+        className += wxApp::GetNoRedrawClassSuffix();
     }
 
     // do create the window