#include "wx/resource.h"
#endif
-// OLE is used for drag-and-drop, clipboard, OLE Automation...
-#ifndef wxUSE_NORLANDER_HEADERS
-#if defined(__GNUWIN32__) || defined(__SC__) || defined(__SALFORDC__)
+#if wxUSE_TOOLTIPS
+ #include "wx/tooltip.h"
+#endif // wxUSE_TOOLTIPS
+
+// OLE is used for drag-and-drop, clipboard, OLE Automation..., but some
+// compilers don't support it (missing headers, libs, ...)
+#if defined(__GNUWIN32_OLD__) || defined(__SC__) || defined(__SALFORDC__)
#undef wxUSE_OLE
#define wxUSE_OLE 0
#endif // broken compilers
-#endif
#if wxUSE_OLE
#include <ole2.h>
#include <string.h>
#include <ctype.h>
-#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
+#if defined(__WIN95__) && !(defined(__GNUWIN32_OLD__) || defined(__TWIN32__))
#include <commctrl.h>
#endif
// ---------------------------------------------------------------------------
extern wxChar *wxBuffer;
-extern wxChar *wxOsVersion;
extern wxList *wxWinHandleList;
extern wxList WXDLLEXPORT wxPendingDelete;
extern void wxSetKeyboardHook(bool doIt);
-extern wxCursor *g_globalCursor;
MSG s_currentMsg;
wxApp *wxTheApp = NULL;
const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
const wxChar *wxPanelClassName = wxT("wxPanelClass");
+const wxChar *wxPanelClassNameNR = wxT("wxPanelClassNR");
const wxChar *wxCanvasClassName = wxT("wxCanvasClass");
+const wxChar *wxCanvasClassNameNR = wxT("wxCanvasClassNR");
HICON wxSTD_FRAME_ICON = (HICON) NULL;
HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
+// FIXME wxUSE_ON_FATAL_EXCEPTION is only supported for VC++ now because it
+// needs compiler support for Win32 SEH. Others (especially Borland)
+// probably have it too, but I'm not sure about how it works
+// JACS: get 'Cannot use __try in functions that require unwinding
+// in Unicode mode, so disabling.
+#if !defined(__VISUALC__) || defined(__WIN16__) || defined(UNICODE)
+ #undef wxUSE_ON_FATAL_EXCEPTION
+ #define wxUSE_ON_FATAL_EXCEPTION 0
+#endif // VC++
+
+#if wxUSE_ON_FATAL_EXCEPTION
+ static bool gs_handleExceptions = FALSE;
+#endif
+
// ===========================================================================
// implementation
// ===========================================================================
// wxApp
// ---------------------------------------------------------------------------
- IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
+IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
- BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
- EVT_IDLE(wxApp::OnIdle)
- EVT_END_SESSION(wxApp::OnEndSession)
- EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
- END_EVENT_TABLE()
+BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
+ EVT_IDLE(wxApp::OnIdle)
+ EVT_END_SESSION(wxApp::OnEndSession)
+ EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
+END_EVENT_TABLE()
//// Initialize
bool wxApp::Initialize()
{
+ // the first thing to do is to check if we're trying to run an Unicode
+ // program under Win9x - if so, abort right now as it has no chance to
+ // work
+#if wxUSE_UNICODE
+ if ( wxGetOsVersion() != wxWINDOWS_NT )
+ {
+ // note that we can use MessageBoxW() as it's implemented even under
+ // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
+ // used by wxLocale are not
+ ::MessageBox
+ (
+ NULL,
+ _T("This program uses Unicode and requires Windows NT/2000.\nProgram aborted."),
+ _T("wxWindows Fatal Error"),
+ MB_ICONERROR | MB_OK
+ );
+
+ return FALSE;
+ }
+#endif // wxUSE_UNICODE
+
// Some people may wish to use this, but
// probably it shouldn't be here by default.
#ifdef __WXDEBUG__
wxClassInfo::InitializeClasses();
-#if wxUSE_RESOURCES
- wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
-#endif
-
#if wxUSE_THREADS
wxPendingEventsLocker = new wxCriticalSection;
#endif
Ctl3dAutoSubclass(wxhInstance);
#endif
- g_globalCursor = new wxCursor;
-
// VZ: these icons are not in wx.rc anyhow (but should they?)!
#if 0
wxSTD_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_FRAME"));
// This is to foil optimizations in Visual C++ that throw out dummy.obj.
// PLEASE DO NOT ALTER THIS.
-#if defined(__VISUALC__) && !defined(WXMAKINGDLL)
+#if defined(__VISUALC__) && defined(__WIN16__) && !defined(WXMAKINGDLL)
extern char wxDummyChar;
if (wxDummyChar) wxDummyChar++;
#endif
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(frame)");
+ wxLogLastError(wxT("RegisterClass(frame)"));
return FALSE;
}
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(no redraw frame)");
+ wxLogLastError(wxT("RegisterClass(no redraw frame)"));
return FALSE;
}
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(MDI parent)");
+ wxLogLastError(wxT("RegisterClass(MDI parent)"));
return FALSE;
}
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(no redraw MDI parent frame)");
+ wxLogLastError(wxT("RegisterClass(no redraw MDI parent frame)"));
return FALSE;
}
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(MDI child)");
+ wxLogLastError(wxT("RegisterClass(MDI child)"));
return FALSE;
}
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(no redraw MDI child)");
+ wxLogLastError(wxT("RegisterClass(no redraw MDI child)"));
return FALSE;
}
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(panel)");
+ wxLogLastError(wxT("RegisterClass(panel)"));
+
+ return FALSE;
+ }
+
+ // Register the no redraw panel window class.
+ wndclass.lpszClassName = wxPanelClassNameNR;
+ wndclass.style = styleNoRedraw;
+
+ if ( !RegisterClass(&wndclass) )
+ {
+ wxLogLastError(wxT("RegisterClass(no redraw panel)"));
return FALSE;
}
if ( !RegisterClass(&wndclass) )
{
- wxLogLastError("RegisterClass(canvas)");
+ wxLogLastError(wxT("RegisterClass(canvas)"));
+
+ return FALSE;
+ }
+
+ wndclass.lpszClassName = wxCanvasClassNameNR;
+ wndclass.style = styleNoRedraw;
+ if ( !RegisterClass(&wndclass) )
+ {
+ wxLogLastError(wxT("RegisterClass(no redraw canvas)"));
return FALSE;
}
// wxDefaultResourceTable->ClearTable();
#endif
- // Indicate that the cursor can be freed, so that cursor won't be deleted
- // by deleting the bitmap list before g_globalCursor goes out of scope
- // (double deletion of the cursor).
- wxSetCursor(wxNullCursor);
- delete g_globalCursor;
- g_globalCursor = NULL;
-
wxDeleteStockObjects();
// Destroy all GDI lists, etc.
// wxDebugContext, too.
if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
{
- wxLogDebug(wxT("There were memory leaks."));
+ wxLogMessage(wxT("There were memory leaks."));
wxDebugContext::Dump();
wxDebugContext::PrintStatistics();
}
#endif // wxUSE_LOG
}
+//----------------------------------------------------------------------
+// Entry point helpers, used by wxPython
+//----------------------------------------------------------------------
+
+int WXDLLEXPORT wxEntryStart( int WXUNUSED(argc), char** WXUNUSED(argv) )
+{
+ return wxApp::Initialize();
+}
+
+int WXDLLEXPORT wxEntryInitGui()
+{
+ wxTheApp->OnInitGui();
+ return 0;
+}
+
+void WXDLLEXPORT wxEntryCleanup()
+{
+ wxApp::CleanUp();
+}
+
+
#if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
// temporarily disable this warning which would be generated in release builds
#pragma warning(disable: 4715) // not all control paths return a value
#endif // Visual C++
-//// Main wxWindows entry point
+//----------------------------------------------------------------------
+// Main wxWindows entry point
+//----------------------------------------------------------------------
int wxEntry(WXHINSTANCE hInstance,
WXHINSTANCE WXUNUSED(hPrevInstance),
char *lpCmdLine,
wxDebugContext::SetCheckpoint();
#endif
#endif
- // take everything into a try-except block in release build
- // FIXME other compilers must support Win32 SEH (structured exception
- // handling) too, just find the appropriate keyword in their docs!
- // Please note that it's _not_ the same as C++ exceptions!
-#if !defined(__WXDEBUG__) && defined(__VISUALC__)
- #define CATCH_PROGRAM_EXCEPTIONS
+ // take everything into a try-except block to be able to call
+ // OnFatalException() if necessary
+#if wxUSE_ON_FATAL_EXCEPTION
__try {
-#else
- #undef CATCH_PROGRAM_EXCEPTIONS
#endif
wxhInstance = (HINSTANCE) hInstance;
- if (!wxApp::Initialize())
+ if (!wxEntryStart(0,0))
return 0;
// create the application object or ensure that one already exists
// GUI-specific initialisation. In fact on Windows we don't have any,
// but this call is provided for compatibility across platforms.
- wxTheApp->OnInitGui();
+ wxEntryInitGui();
// We really don't want timestamps by default, because it means
// we can't simply double-click on the error message and get to that
int retValue = 0;
- if ( wxTheApp->OnInit() )
+ // it is common to create a modal dialog in OnInit() (to ask/notify the
+ // user about something) but it wouldn't work if we don't change the
+ // "exit on delete last frame" flag here as when this dialog is
+ // deleted, the app would terminate (it was the last top level window
+ // as the main frame wasn't created yet!), so disable this behaviour
+ // temproarily
+ bool exitOnLastFrameDelete = wxTheApp->GetExitOnFrameDelete();
+ wxTheApp->SetExitOnFrameDelete(FALSE);
+
+ // init the app
+ retValue = wxTheApp->OnInit() ? 0 : -1;
+
+ // restore the old flag value
+ wxTheApp->SetExitOnFrameDelete(exitOnLastFrameDelete);
+
+ if ( retValue == 0 )
{
if ( enterLoop )
{
+ // run the main loop
retValue = wxTheApp->OnRun();
}
else
- // We want to initialize, but not run or exit immediately.
+ {
+ // we want to initialize, but not run or exit immediately.
return 1;
+ }
}
//else: app initialization failed, so we skipped OnRun()
wxTheApp->OnExit();
- wxApp::CleanUp();
+ wxEntryCleanup();
return retValue;
-#ifdef CATCH_PROGRAM_EXCEPTIONS
+#if wxUSE_ON_FATAL_EXCEPTION
}
- __except ( EXCEPTION_EXECUTE_HANDLER ) {
- /*
- if ( wxTheApp )
+ __except ( gs_handleExceptions ? EXCEPTION_EXECUTE_HANDLER
+ : EXCEPTION_CONTINUE_SEARCH ) {
+ if ( wxTheApp )
+ {
+ // give the user a chance to do something special about this
wxTheApp->OnFatalException();
- */
-
- // using wxLog would be unsafe here
- ::MessageBox(NULL,
- _("Unrecoverable program error detected: "
- " the application will terminate."),
- _("Fatal Error"),
- MB_APPLMODAL | MB_ICONSTOP | MB_OK);
+ }
::ExitProcess(3); // the same exit code as abort()
// NOTREACHED
}
-#endif // CATCH_PROGRAM_EXCEPTIONS
+#endif // wxUSE_ON_FATAL_EXCEPTION
}
// restore warning state
#else /* _WINDLL */
-//// Entry point for DLLs
+//----------------------------------------------------------------------
+// Entry point for wxWindows + the App in a DLL
+//----------------------------------------------------------------------
int wxEntry(WXHINSTANCE hInstance)
{
wxhInstance = (HINSTANCE) hInstance;
- wxApp::Initialize();
+ wxEntryStart(0, 0);
// The app may have declared a global application object, but we recommend
// the IMPLEMENT_APP macro is used instead, which sets an initializer function
wxTheApp->argc = 0;
wxTheApp->argv = NULL;
- wxTheApp->OnInitGui();
+ wxEntryInitGui();
wxTheApp->OnInit();
return TRUE;
else
return FALSE;
-#endif
-#ifdef _WINDLL // Assume initialized if DLL (no way of telling)
+#else // Assume initialized if DLL (no way of telling)
return TRUE;
#endif
}
else if ( rc == -1 )
{
// should never happen, but let's test for it nevertheless
- wxLogLastError("GetMessage");
+ wxLogLastError(wxT("GetMessage"));
}
else
{
wxMutexGuiLeaveOrEnter();
#endif // wxUSE_THREADS
- while ( !::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) &&
- ProcessIdle() )
- {
- }
-
+ while ( !Pending() && ProcessIdle() )
+ ;
+ // a message came or no more idle processing to do
DoMessage();
}
void wxApp::ExitMainLoop()
{
+ // VZ: why not ::PostQuitMessage()?
m_keepGoing = FALSE;
}
bool wxApp::Pending()
{
- return (::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) != 0);
+ return ::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) != 0;
}
void wxApp::Dispatch()
{
MSG *msg = (MSG *)wxmsg;
HWND hWnd = msg->hwnd;
- wxWindow *wndThis = wxFindWinFromHandle((WXHWND)hWnd), *wnd;
+ wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hWnd);
- // for some composite controls (like a combobox), wndThis might be NULL
- // because the subcontrol is not a wxWindow, but only the control itself
- // is - try to catch this case
- while ( hWnd && !wndThis )
+#if wxUSE_TOOLTIPS
+ // we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
+ // popup the tooltip bubbles
+ if ( wndThis && (msg->message == WM_MOUSEMOVE) )
{
- hWnd = ::GetParent(hWnd);
- wndThis = wxFindWinFromHandle((WXHWND)hWnd);
+ wxToolTip *tt = wndThis->GetToolTip();
+ if ( tt )
+ {
+ tt->RelayEvent(wxmsg);
+ }
}
+#endif // wxUSE_TOOLTIPS
// Try translations first; find the youngest window with
// a translation table.
+ wxWindow *wnd;
+
for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
{
if ( wnd->MSWTranslateMessage(wxmsg) )
s_inOnIdle = TRUE;
+ // If there are pending events, we must process them: pending events
+ // are either events to the threads other than main or events posted
+ // with wxPostEvent() functions
+ // GRG: I have moved this here so that all pending events are processed
+ // before starting to delete any objects. This behaves better (in
+ // particular, wrt wxPostEvent) and is coherent with wxGTK's current
+ // behaviour. Changed Feb/2000 before 2.1.14
+ ProcessPendingEvents();
+
// 'Garbage' collection of windows deleted with Close().
DeletePendingObjects();
#if wxUSE_LOG
// flush the logged messages if any
- wxLog *pLog = wxLog::GetActiveTarget();
- if ( pLog != NULL && pLog->HasPendingMessages() )
- pLog->Flush();
+ wxLog::FlushActive();
#endif // wxUSE_LOG
// Send OnIdle events to all windows
event.RequestMore(TRUE);
}
- // If they are pending events, we must process them: pending events are
- // either events to the threads other than main or events posted with
- // wxPostEvent() functions
- ProcessPendingEvents();
-
s_inOnIdle = FALSE;
}
// try to use DllGetVersion() if available in _headers_
#ifdef DLLVER_PLATFORM_WINDOWS // defined in shlwapi.h
DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)
- ::GetProcAddress(hModuleComCtl32, _T("DllGetVersion"));
+ ::GetProcAddress(hModuleComCtl32, "DllGetVersion");
if ( pfnDllGetVersion )
{
DLLVERSIONINFO dvi;
FARPROC theProc = ::GetProcAddress
(
hModuleComCtl32,
-#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x520)
"InitCommonControlsEx"
-#else
- _T("InitCommonControlsEx")
-#endif
);
if ( !theProc )
theProc = ::GetProcAddress
(
hModuleComCtl32,
-#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x520)
"InitializeFlatSB"
-#else
- _T("InitializeFlatSB")
-#endif
);
if ( !theProc )
{
wxLogError(_("Fatal error: exiting"));
wxApp::CleanUp();
+ exit(0);
}
// Yield to incoming messages
+
+static bool gs_inYield = FALSE;
+
bool wxYield()
{
+ // disable log flushing from here because a call to wxYield() shouldn't
+ // normally result in message boxes popping up &c
+ wxLog::Suspend();
+
+#ifdef __WXDEBUG__
+ if (gs_inYield)
+ wxFAIL_MSG( wxT("wxYield called recursively" ) );
+#endif
+
+ gs_inYield = TRUE;
+
// we don't want to process WM_QUIT from here - it should be processed in
// the main event loop in order to stop it
-
MSG msg;
while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
msg.message != WM_QUIT )
{
+#if wxUSE_THREADS
+ wxMutexGuiLeaveOrEnter();
+#endif // wxUSE_THREADS
+
if ( !wxTheApp->DoMessage() )
break;
}
// If they are pending events, we must process them.
- wxTheApp->ProcessPendingEvents();
+ if (wxTheApp)
+ wxTheApp->ProcessPendingEvents();
+
+ // let the logs be flashed again
+ wxLog::Resume();
+
+ gs_inYield = FALSE;
+
+ return TRUE;
+}
+
+// Yield to incoming messages; but fail silently if recursion is detected.
+bool wxYieldIfNeeded()
+{
+ if (gs_inYield)
+ return FALSE;
+
+ return wxYield();
+}
+
+bool wxHandleFatalExceptions(bool doit)
+{
+#if wxUSE_ON_FATAL_EXCEPTION
+ // assume this can only be called from the main thread
+ gs_handleExceptions = doit;
return TRUE;
+#else
+ wxFAIL_MSG(_T("set wxUSE_ON_FATAL_EXCEPTION to 1 to sue this function"));
+
+ return FALSE;
+#endif
}
//-----------------------------------------------------------------------------
if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
{
// should never happen
- wxLogLastError("PostMessage(WM_NULL)");
+ wxLogLastError(wxT("PostMessage(WM_NULL)"));
}
}
}