// a new App object to start application
class WXDLLIMPEXP_CORE wxApp : public wxAppBase
{
- DECLARE_DYNAMIC_CLASS(wxApp)
-
public:
wxApp();
virtual ~wxApp();
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
protected:
DECLARE_EVENT_TABLE()
DECLARE_NO_COPY_CLASS(wxApp)
+ DECLARE_DYNAMIC_CLASS(wxApp)
};
#ifdef __WXWINCE__
// 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
//
#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
wxOleInitialize();
- RegisterWindowClasses();
-
#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
wxSetKeyboardHook(true);
#endif
}
// ---------------------------------------------------------------------------
-// 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()
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/app.h"
- #include "wx/module.h"
#endif
#include "wx/msw/private.h"
# 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
// ----------------------------------------------------------------------------
{
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;
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());
extern wxMenu *wxCurrentPopupMenu;
-extern const wxChar *wxMDIFrameClassName; // from app.cpp
-extern const wxChar *wxMDIChildFrameClassName;
-extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
extern void wxRemoveHandleAssociation(wxWindow *win);
// ---------------------------------------------------------------------------
msflags &= ~WS_VSCROLL;
msflags &= ~WS_HSCROLL;
- if ( !wxWindow::MSWCreate(wxMDIFrameClassName,
+ if ( !wxWindow::MSWCreate(wxApp::GetRegisteredClassName(_T("wxMDIFrame")),
title.wx_str(),
pos, size,
msflags,
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)
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)
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,
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;
}
+/* 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,
msflags |= WS_VISIBLE;
}
- if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+ if ( !MSWCreate(MSWGetRegisteredClassName(),
+ NULL, pos, size, msflags, exstyle) )
return false;
InheritAttributes();
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");
}
// ----------------------------------------------------------------------------
// 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);
wxString className(wclass);
if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
{
- className += wxT("NR");
+ className += wxApp::GetNoRedrawClassSuffix();
}
// do create the window