added and documented wxApp::OnAssert

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@10971 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2001-07-11 15:19:32 +00:00
parent 1e4d446b99
commit a5f1fd3e33
9 changed files with 303 additions and 166 deletions

View File

@@ -189,16 +189,64 @@ to provide your own (environment-dependent) main loop.
Returns 0 under X, and the wParam of the WM\_QUIT message under Windows. Returns 0 under X, and the wParam of the WM\_QUIT message under Windows.
\membersection{wxApp::OnActivate}\label{wxapponactivate} %% VZ: OnXXX() functions should *not* be documented
%%
%%\membersection{wxApp::OnActivate}\label{wxapponactivate}
%%
%%\func{void}{OnActivate}{\param{wxActivateEvent\& }{event}}
%%
%%Provide this member function to know whether the application is being
%%activated or deactivated (Windows only).
%%
%%\wxheading{See also}
%%
%%\helpref{wxWindow::OnActivate}{wxwindowonactivate}, \helpref{wxActivateEvent}{wxactivateevent}
%%
%%\membersection{wxApp::OnCharHook}\label{wxapponcharhook}
%%
%%\func{void}{OnCharHook}{\param{wxKeyEvent\&}{ event}}
%%
%%This event handler function is called (under Windows only) to allow the window to intercept keyboard events
%%before they are processed by child windows.
%%
%%\wxheading{Parameters}
%%
%%\docparam{event}{The keypress event.}
%%
%%\wxheading{Remarks}
%%
%%Use the wxEVT\_CHAR\_HOOK macro in your event table.
%%
%%If you use this member, you can selectively consume keypress events by calling\rtfsp
%%\helpref{wxEvent::Skip}{wxeventskip} for characters the application is not interested in.
%%
%%\wxheading{See also}
%%
%%\helpref{wxKeyEvent}{wxkeyevent}, \helpref{wxWindow::OnChar}{wxwindowonchar},\rtfsp
%%\helpref{wxWindow::OnCharHook}{wxwindowoncharhook}, \helpref{wxDialog::OnCharHook}{wxdialogoncharhook}
\func{void}{OnActivate}{\param{wxActivateEvent\& }{event}} \membersection{wxApp::OnAssert}\label{wxapponassert}
Provide this member function to know whether the application is being \func{void}{OnAssert}{\param{const wxChar }{*file}, \param{int }{line}, \param{const wxChar }{*msg}}
activated or deactivated (Windows only).
\wxheading{See also} This function is called when an assert failure occurs, i.e. the condition
specified in \helpref{wxASSERT}{wxassert} macro evaluated to {\tt FALSE}.
It is only called in debug mode (when {\tt \_\_WXDEBUG\_\_| is defined) as
asserts are not left in the release code at all.
\helpref{wxWindow::OnActivate}{wxwindowonactivate}, \helpref{wxActivateEvent}{wxactivateevent} The base class version show the default assert failure dialog box proposing to
the user to stop the program, continue or ignore all subsequent asserts.
\wxheading{Parameters}
\docparam{file}{the name of the source file where the assert occured}
\docparam{line}{the line number in this file where the assert occured}
\docparam{msg}{the message specified as argument to
\helpref{wxASSERT\_MSG}{wxassertmsg} or \helpref{wxFAIL\_MSG}{wxfailmsg}, will
be {\tt NULL} if just \helpref{wxASSERT}{wxassert} or \helpref{wxFAIL}{wxfail}
was used}
\membersection{wxApp::OnExit}\label{wxapponexit} \membersection{wxApp::OnExit}\label{wxapponexit}
@@ -207,29 +255,6 @@ activated or deactivated (Windows only).
Provide this member function for any processing which needs to be done as Provide this member function for any processing which needs to be done as
the application is about to exit. the application is about to exit.
\membersection{wxApp::OnCharHook}\label{wxapponcharhook}
\func{void}{OnCharHook}{\param{wxKeyEvent\&}{ event}}
This event handler function is called (under Windows only) to allow the window to intercept keyboard events
before they are processed by child windows.
\wxheading{Parameters}
\docparam{event}{The keypress event.}
\wxheading{Remarks}
Use the wxEVT\_CHAR\_HOOK macro in your event table.
If you use this member, you can selectively consume keypress events by calling\rtfsp
\helpref{wxEvent::Skip}{wxeventskip} for characters the application is not interested in.
\wxheading{See also}
\helpref{wxKeyEvent}{wxkeyevent}, \helpref{wxWindow::OnChar}{wxwindowonchar},\rtfsp
\helpref{wxWindow::OnCharHook}{wxwindowoncharhook}, \helpref{wxDialog::OnCharHook}{wxdialogoncharhook}
\membersection{wxApp::OnCmdLineError}\label{wxapponcmdlineerror} \membersection{wxApp::OnCmdLineError}\label{wxapponcmdlineerror}
\func{bool}{OnCmdLineError}{\param{wxCmdLineParser\& }{parser}} \func{bool}{OnCmdLineError}{\param{wxCmdLineParser\& }{parser}}

View File

@@ -263,6 +263,16 @@ public:
virtual void SetActive(bool isActive, wxWindow *lastFocus); virtual void SetActive(bool isActive, wxWindow *lastFocus);
#endif // wxUSE_GUI #endif // wxUSE_GUI
// debugging support
// -----------------
// this function is called when an assert failure occurs, the base class
// version does the normal processing (i.e. shows the usual assert failure
// dialog box)
#ifdef __WXDEBUG__
virtual void OnAssert(const wxChar *file, int line, const wxChar *msg);
#endif // __WXDEBUG__
// implementation only from now on // implementation only from now on
// ------------------------------- // -------------------------------

View File

@@ -41,6 +41,8 @@ WXDLLEXPORT_DATA(extern const bool) wxTrue;
WXDLLEXPORT_DATA(extern const bool) wxFalse; WXDLLEXPORT_DATA(extern const bool) wxFalse;
// Macros which are completely disabled in 'release' mode // Macros which are completely disabled in 'release' mode
//
// NB: these functions are implemented in src/common/appcmn.cpp
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
/* /*
this function may be redefined to do something non trivial and is called this function may be redefined to do something non trivial and is called

View File

@@ -61,9 +61,11 @@ public:
bool ProcessIdle(); bool ProcessIdle();
void DeletePendingObjects(); void DeletePendingObjects();
// This can be used to suppress the generation of Idle events. #ifdef __WXDEBUG__
void SuppressIdleEvents(bool arg = TRUE) { m_suppressIdleEvents = arg; } virtual void OnAssert(const wxChar *file, int line, const wxChar *msg);
bool GetSuppressIdleEvents() const { return m_suppressIdleEvents; }
bool IsInAssert() const { return m_isInAssert; }
#endif // __WXDEBUG__
bool m_initialized; bool m_initialized;
@@ -74,10 +76,11 @@ public:
unsigned char *m_colorCube; unsigned char *m_colorCube;
private: private:
// Set to TRUE while we are in wxYield(). // true if we're inside an assert modal dialog
bool m_suppressIdleEvents; #ifdef __WXDEBUG__
bool m_isInAssert;
#endif // __WXDEBUG__
private:
DECLARE_DYNAMIC_CLASS(wxApp) DECLARE_DYNAMIC_CLASS(wxApp)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };

View File

@@ -61,9 +61,11 @@ public:
bool ProcessIdle(); bool ProcessIdle();
void DeletePendingObjects(); void DeletePendingObjects();
// This can be used to suppress the generation of Idle events. #ifdef __WXDEBUG__
void SuppressIdleEvents(bool arg = TRUE) { m_suppressIdleEvents = arg; } virtual void OnAssert(const wxChar *file, int line, const wxChar *msg);
bool GetSuppressIdleEvents() const { return m_suppressIdleEvents; }
bool IsInAssert() const { return m_isInAssert; }
#endif // __WXDEBUG__
bool m_initialized; bool m_initialized;
@@ -74,10 +76,11 @@ public:
unsigned char *m_colorCube; unsigned char *m_colorCube;
private: private:
// Set to TRUE while we are in wxYield(). // true if we're inside an assert modal dialog
bool m_suppressIdleEvents; #ifdef __WXDEBUG__
bool m_isInAssert;
#endif // __WXDEBUG__
private:
DECLARE_DYNAMIC_CLASS(wxApp) DECLARE_DYNAMIC_CLASS(wxApp)
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };

View File

@@ -32,12 +32,23 @@
#include "wx/app.h" #include "wx/app.h"
#include "wx/intl.h" #include "wx/intl.h"
#include "wx/list.h" #include "wx/list.h"
#if wxUSE_GUI
#include "wx/msgdlg.h"
#endif // wxUSE_GUI
#endif #endif
#include "wx/cmdline.h" #include "wx/cmdline.h"
#include "wx/thread.h" #include "wx/thread.h"
#include "wx/confbase.h" #include "wx/confbase.h"
#if !defined(__WXMSW__) || defined(__WXMICROWIN__)
#include <signal.h> // for SIGTRAP used by wxTrap()
#endif //Win/Unix
#if defined(__WXMSW__)
#include "wx/msw/private.h" // includes windows.h for MessageBox()
#endif
// =========================================================================== // ===========================================================================
// implementation // implementation
// =========================================================================== // ===========================================================================
@@ -258,3 +269,149 @@ bool wxAppBase::OnCmdLineError(wxCmdLineParser& parser)
#endif // wxUSE_CMDLINE_PARSER #endif // wxUSE_CMDLINE_PARSER
// ----------------------------------------------------------------------------
// debugging support
// ----------------------------------------------------------------------------
#ifdef __WXDEBUG__
// wxASSERT() helper
bool wxAssertIsEqual(int x, int y)
{
return x == y;
}
// break into the debugger
void wxTrap()
{
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
DebugBreak();
#elif defined(__WXMAC__)
#if __powerc
Debugger();
#else
SysBreak();
#endif
#elif defined(__UNIX__)
raise(SIGTRAP);
#else
// TODO
#endif // Win/Unix
}
// show the assert modal dialog
static
void ShowAssertDialog(const wxChar *szFile, int nLine, const wxChar *szMsg)
{
// this variable can be set to true to suppress "assert failure" messages
static bool s_bNoAsserts = FALSE;
static bool s_bInAssert = FALSE; // FIXME MT-unsafe
if ( s_bInAssert )
{
// He-e-e-e-elp!! we're trapped in endless loop
wxTrap();
s_bInAssert = FALSE;
return;
}
s_bInAssert = TRUE;
wxChar szBuf[4096];
// make life easier for people using VC++ IDE: clicking on the message
// will take us immediately to the place of the failed assert
wxSnprintf(szBuf, WXSIZEOF(szBuf),
#ifdef __VISUALC__
wxT("%s(%d): assert failed"),
#else // !VC++
// make the error message more clear for all the others
wxT("Assert failed in file %s at line %d"),
#endif // VC/!VC
szFile, nLine);
if ( szMsg != NULL )
{
wxStrcat(szBuf, wxT(": "));
wxStrcat(szBuf, szMsg);
}
else // no message given
{
wxStrcat(szBuf, wxT("."));
}
if ( !s_bNoAsserts )
{
// send it to the normal log destination
wxLogDebug(szBuf);
#if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__)
// this message is intentionally not translated - it is for
// developpers only
wxStrcat(szBuf, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings."));
// use the native message box if available: this is more robust than
// using our own
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
switch ( ::MessageBox(NULL, szBuf, _T("Debug"),
MB_YESNOCANCEL | MB_ICONSTOP ) )
{
case IDYES:
wxTrap();
break;
case IDCANCEL:
s_bNoAsserts = TRUE;
break;
//case IDNO: nothing to do
}
#else // !MSW
switch ( wxMessageBox(szBuf, wxT("Debug"),
wxYES_NO | wxCANCEL | wxICON_STOP ) )
{
case wxYES:
wxTrap();
break;
case wxCANCEL:
s_bNoAsserts = TRUE;
break;
//case wxNO: nothing to do
}
#endif // GUI or MSW
#else // !GUI
wxTrap();
#endif // GUI/!GUI
}
s_bInAssert = FALSE;
}
// this function is called when an assert fails
void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg)
{
if ( !wxTheApp )
{
// by default, show the assert dialog box - we can't customize this
// behaviour
ShowAssertDialog(szFile, nLine, szMsg);
}
else
{
// let the app process it as it wants
wxTheApp->OnAssert(szFile, nLine, szMsg);
}
}
void wxAppBase::OnAssert(const wxChar *file, int line, const wxChar *msg)
{
ShowAssertDialog(file, line, msg);
}
#endif //WXDEBUG

View File

@@ -39,7 +39,6 @@
#ifdef __WXMSW__ #ifdef __WXMSW__
#include "wx/msw/private.h" #include "wx/msw/private.h"
#endif #endif
#include "wx/msgdlg.h"
#endif #endif
#endif //WX_PRECOMP #endif //WX_PRECOMP
@@ -61,10 +60,6 @@
#include "wx/msw/private.h" // includes windows.h for OutputDebugString #include "wx/msw/private.h" // includes windows.h for OutputDebugString
#endif #endif
#if !defined(__WXMSW__) || defined(__WXMICROWIN__)
#include <signal.h>
#endif //Win/Unix
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// non member functions // non member functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -748,122 +743,4 @@ const wxChar *wxSysErrorMsg(unsigned long nErrCode)
#endif // Win/Unix #endif // Win/Unix
} }
// ----------------------------------------------------------------------------
// debug helper
// ----------------------------------------------------------------------------
#ifdef __WXDEBUG__
// wxASSERT() helper
bool wxAssertIsEqual(int x, int y)
{
return x == y;
}
// break into the debugger
void wxTrap()
{
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
DebugBreak();
#elif defined(__WXMAC__)
#if __powerc
Debugger();
#else
SysBreak();
#endif
#elif defined(__UNIX__)
raise(SIGTRAP);
#else
// TODO
#endif // Win/Unix
}
// this function is called when an assert fails
void wxOnAssert(const wxChar *szFile, int nLine, const wxChar *szMsg)
{
// this variable can be set to true to suppress "assert failure" messages
static bool s_bNoAsserts = FALSE;
static bool s_bInAssert = FALSE; // FIXME MT-unsafe
if ( s_bInAssert ) {
// He-e-e-e-elp!! we're trapped in endless loop
wxTrap();
s_bInAssert = FALSE;
return;
}
s_bInAssert = TRUE;
wxChar szBuf[LOG_BUFFER_SIZE];
// make life easier for people using VC++ IDE: clicking on the message
// will take us immediately to the place of the failed assert
wxSnprintf(szBuf, WXSIZEOF(szBuf),
#ifdef __VISUALC__
wxT("%s(%d): assert failed"),
#else // !VC++
// make the error message more clear for all the others
wxT("Assert failed in file %s at line %d"),
#endif // VC/!VC
szFile, nLine);
if ( szMsg != NULL ) {
wxStrcat(szBuf, wxT(": "));
wxStrcat(szBuf, szMsg);
}
else {
wxStrcat(szBuf, wxT("."));
}
if ( !s_bNoAsserts ) {
// send it to the normal log destination
wxLogDebug(szBuf);
#if (wxUSE_GUI && wxUSE_MSGDLG) || defined(__WXMSW__)
// this message is intentionally not translated - it is for
// developpers only
wxStrcat(szBuf, wxT("\nDo you want to stop the program?\nYou can also choose [Cancel] to suppress further warnings."));
// use the native message box if available: this is more robust than
// using our own
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
switch ( ::MessageBox(NULL, szBuf, _T("Debug"),
MB_YESNOCANCEL | MB_ICONSTOP ) ) {
case IDYES:
wxTrap();
break;
case IDCANCEL:
s_bNoAsserts = TRUE;
break;
//case IDNO: nothing to do
}
#else // !MSW
switch ( wxMessageBox(szBuf, wxT("Debug"),
wxYES_NO | wxCANCEL | wxICON_STOP ) ) {
case wxYES:
wxTrap();
break;
case wxCANCEL:
s_bNoAsserts = TRUE;
break;
//case wxNO: nothing to do
}
#endif // GUI or MSW
#else // !GUI
wxTrap();
#endif // GUI/!GUI
}
s_bInAssert = FALSE;
}
#endif //WXDEBUG
#endif //wxUSE_LOG #endif //wxUSE_LOG

View File

@@ -194,7 +194,18 @@ gint wxapp_pending_callback( gpointer WXUNUSED(data) )
gint wxapp_idle_callback( gpointer WXUNUSED(data) ) gint wxapp_idle_callback( gpointer WXUNUSED(data) )
{ {
if (!wxTheApp) return TRUE; if (!wxTheApp)
return TRUE;
#ifdef __WXDEBUG__
if ( wxTheApp->IsInAssert() )
{
// don't generate the idle events while the assert modal dialog is
// shown, this completely confuses the apps which don't expect to be
// reentered from some safely-looking functions
return FALSE;
}
#endif // __WXDEBUG__
// when getting called from GDK's time-out handler // when getting called from GDK's time-out handler
// we are no longer within GDK's grab on the GUI // we are no longer within GDK's grab on the GUI
@@ -309,6 +320,11 @@ END_EVENT_TABLE()
wxApp::wxApp() wxApp::wxApp()
{ {
m_initialized = FALSE;
#ifdef __WXDEBUG__
m_isInAssert = FALSE;
#endif // __WXDEBUG__
m_idleTag = 0; m_idleTag = 0;
wxapp_install_idle_handler(); wxapp_install_idle_handler();
@@ -850,3 +866,17 @@ wxApp::GetStdIcon(int which) const
return wxIcon(error_xpm); return wxIcon(error_xpm);
} }
} }
#ifdef __WXDEBUG__
void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)
{
m_isInAssert = TRUE;
wxAppBase::OnAssert(file, line, msg);
m_isInAssert = FALSE;
}
#endif // __WXDEBUG__

View File

@@ -194,7 +194,18 @@ gint wxapp_pending_callback( gpointer WXUNUSED(data) )
gint wxapp_idle_callback( gpointer WXUNUSED(data) ) gint wxapp_idle_callback( gpointer WXUNUSED(data) )
{ {
if (!wxTheApp) return TRUE; if (!wxTheApp)
return TRUE;
#ifdef __WXDEBUG__
if ( wxTheApp->IsInAssert() )
{
// don't generate the idle events while the assert modal dialog is
// shown, this completely confuses the apps which don't expect to be
// reentered from some safely-looking functions
return FALSE;
}
#endif // __WXDEBUG__
// when getting called from GDK's time-out handler // when getting called from GDK's time-out handler
// we are no longer within GDK's grab on the GUI // we are no longer within GDK's grab on the GUI
@@ -309,6 +320,11 @@ END_EVENT_TABLE()
wxApp::wxApp() wxApp::wxApp()
{ {
m_initialized = FALSE;
#ifdef __WXDEBUG__
m_isInAssert = FALSE;
#endif // __WXDEBUG__
m_idleTag = 0; m_idleTag = 0;
wxapp_install_idle_handler(); wxapp_install_idle_handler();
@@ -850,3 +866,17 @@ wxApp::GetStdIcon(int which) const
return wxIcon(error_xpm); return wxIcon(error_xpm);
} }
} }
#ifdef __WXDEBUG__
void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)
{
m_isInAssert = TRUE;
wxAppBase::OnAssert(file, line, msg);
m_isInAssert = FALSE;
}
#endif // __WXDEBUG__