except.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: samples/except/except.cpp
  3. // Purpose: shows how C++ exceptions can be used in wxWidgets
  4. // Author: Vadim Zeitlin
  5. // Modified by:
  6. // Created: 2003-09-17
  7. // Copyright: (c) 2003-2005 Vadim Zeitlin
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. // ============================================================================
  11. // declarations
  12. // ============================================================================
  13. // ----------------------------------------------------------------------------
  14. // headers
  15. // ----------------------------------------------------------------------------
  16. // For compilers that support precompilation, includes "wx/wx.h".
  17. #include "wx/wxprec.h"
  18. #ifdef __BORLANDC__
  19. #pragma hdrstop
  20. #endif
  21. #if !wxUSE_EXCEPTIONS
  22. #error "This sample only works with wxUSE_EXCEPTIONS == 1"
  23. #endif // !wxUSE_EXCEPTIONS
  24. // for all others, include the necessary headers (this file is usually all you
  25. // need because it includes almost all "standard" wxWidgets headers)
  26. #ifndef WX_PRECOMP
  27. #include "wx/log.h"
  28. #include "wx/app.h"
  29. #include "wx/frame.h"
  30. #include "wx/dialog.h"
  31. #include "wx/menu.h"
  32. #include "wx/button.h"
  33. #include "wx/sizer.h"
  34. #include "wx/utils.h"
  35. #include "wx/msgdlg.h"
  36. #include "wx/icon.h"
  37. #include "wx/thread.h"
  38. #endif
  39. // ----------------------------------------------------------------------------
  40. // resources
  41. // ----------------------------------------------------------------------------
  42. // the application icon (under Windows and OS/2 it is in resources)
  43. #ifndef wxHAS_IMAGES_IN_RESOURCES
  44. #include "../sample.xpm"
  45. #endif
  46. // ----------------------------------------------------------------------------
  47. // private functions
  48. // ----------------------------------------------------------------------------
  49. static void DoCrash()
  50. {
  51. char *p = 0;
  52. strcpy(p, "Let's crash");
  53. }
  54. // ----------------------------------------------------------------------------
  55. // private classes
  56. // ----------------------------------------------------------------------------
  57. // Define a new application type, each program should derive a class from wxApp
  58. class MyApp : public wxApp
  59. {
  60. public:
  61. // override base class virtuals
  62. // ----------------------------
  63. // program startup
  64. virtual bool OnInit();
  65. // 2nd-level exception handling: we get all the exceptions occurring in any
  66. // event handler here
  67. virtual bool OnExceptionInMainLoop();
  68. // 3rd, and final, level exception handling: whenever an unhandled
  69. // exception is caught, this function is called
  70. virtual void OnUnhandledException();
  71. // and now for something different: this function is called in case of a
  72. // crash (e.g. dereferencing null pointer, division by 0, ...)
  73. virtual void OnFatalException();
  74. // you can override this function to do something different (e.g. log the
  75. // assert to file) whenever an assertion fails
  76. virtual void OnAssertFailure(const wxChar *file,
  77. int line,
  78. const wxChar *func,
  79. const wxChar *cond,
  80. const wxChar *msg);
  81. };
  82. // Define a new frame type: this is going to be our main frame
  83. class MyFrame : public wxFrame
  84. {
  85. public:
  86. // ctor(s)
  87. MyFrame();
  88. // event handlers (these functions should _not_ be virtual)
  89. void OnQuit(wxCommandEvent& event);
  90. void OnAbout(wxCommandEvent& event);
  91. void OnDialog(wxCommandEvent& event);
  92. void OnThrowInt(wxCommandEvent& event);
  93. void OnThrowString(wxCommandEvent& event);
  94. void OnThrowObject(wxCommandEvent& event);
  95. void OnThrowUnhandled(wxCommandEvent& event);
  96. void OnCrash(wxCommandEvent& event);
  97. void OnTrap(wxCommandEvent& event);
  98. #if wxUSE_ON_FATAL_EXCEPTION
  99. void OnHandleCrash(wxCommandEvent& event);
  100. #endif
  101. protected:
  102. // 1st-level exception handling: we overload ProcessEvent() to be able to
  103. // catch exceptions which occur in MyFrame methods here
  104. virtual bool ProcessEvent(wxEvent& event);
  105. // provoke assert in main or worker thread
  106. //
  107. // this is used to show how an assert failure message box looks like
  108. void OnShowAssert(wxCommandEvent& event);
  109. #if wxUSE_THREADS
  110. void OnShowAssertInThread(wxCommandEvent& event);
  111. #endif // wxUSE_THREADS
  112. private:
  113. // any class wishing to process wxWidgets events must use this macro
  114. wxDECLARE_EVENT_TABLE();
  115. };
  116. // A simple dialog which has only some buttons to throw exceptions
  117. class MyDialog : public wxDialog
  118. {
  119. public:
  120. MyDialog(wxFrame *parent);
  121. // event handlers
  122. void OnThrowInt(wxCommandEvent& event);
  123. void OnThrowObject(wxCommandEvent& event);
  124. void OnCrash(wxCommandEvent& event);
  125. private:
  126. wxDECLARE_EVENT_TABLE();
  127. };
  128. // A trivial exception class
  129. class MyException
  130. {
  131. public:
  132. MyException(const wxString& msg) : m_msg(msg) { }
  133. const wxChar *what() const { return m_msg.c_str(); }
  134. private:
  135. wxString m_msg;
  136. };
  137. // Another exception class which just has to be different from anything else
  138. class UnhandledException
  139. {
  140. };
  141. // ----------------------------------------------------------------------------
  142. // constants
  143. // ----------------------------------------------------------------------------
  144. // IDs for the controls and the menu commands
  145. enum
  146. {
  147. // control ids and menu items
  148. Except_ThrowInt = wxID_HIGHEST,
  149. Except_ThrowString,
  150. Except_ThrowObject,
  151. Except_ThrowUnhandled,
  152. Except_Crash,
  153. Except_Trap,
  154. #if wxUSE_ON_FATAL_EXCEPTION
  155. Except_HandleCrash,
  156. #endif // wxUSE_ON_FATAL_EXCEPTION
  157. Except_ShowAssert,
  158. #if wxUSE_THREADS
  159. Except_ShowAssertInThread,
  160. #endif // wxUSE_THREADS
  161. Except_Dialog,
  162. Except_Quit = wxID_EXIT,
  163. Except_About = wxID_ABOUT
  164. };
  165. // ----------------------------------------------------------------------------
  166. // event tables and other macros for wxWidgets
  167. // ----------------------------------------------------------------------------
  168. // the event tables connect the wxWidgets events with the functions (event
  169. // handlers) which process them. It can be also done at run-time, but for the
  170. // simple menu events like this the static method is much simpler.
  171. wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
  172. EVT_MENU(Except_Quit, MyFrame::OnQuit)
  173. EVT_MENU(Except_About, MyFrame::OnAbout)
  174. EVT_MENU(Except_Dialog, MyFrame::OnDialog)
  175. EVT_MENU(Except_ThrowInt, MyFrame::OnThrowInt)
  176. EVT_MENU(Except_ThrowString, MyFrame::OnThrowString)
  177. EVT_MENU(Except_ThrowObject, MyFrame::OnThrowObject)
  178. EVT_MENU(Except_ThrowUnhandled, MyFrame::OnThrowUnhandled)
  179. EVT_MENU(Except_Crash, MyFrame::OnCrash)
  180. EVT_MENU(Except_Trap, MyFrame::OnTrap)
  181. #if wxUSE_ON_FATAL_EXCEPTION
  182. EVT_MENU(Except_HandleCrash, MyFrame::OnHandleCrash)
  183. #endif // wxUSE_ON_FATAL_EXCEPTION
  184. EVT_MENU(Except_ShowAssert, MyFrame::OnShowAssert)
  185. #if wxUSE_THREADS
  186. EVT_MENU(Except_ShowAssertInThread, MyFrame::OnShowAssertInThread)
  187. #endif // wxUSE_THREADS
  188. wxEND_EVENT_TABLE()
  189. wxBEGIN_EVENT_TABLE(MyDialog, wxDialog)
  190. EVT_BUTTON(Except_ThrowInt, MyDialog::OnThrowInt)
  191. EVT_BUTTON(Except_ThrowObject, MyDialog::OnThrowObject)
  192. EVT_BUTTON(Except_Crash, MyDialog::OnCrash)
  193. wxEND_EVENT_TABLE()
  194. // Create a new application object: this macro will allow wxWidgets to create
  195. // the application object during program execution (it's better than using a
  196. // static object for many reasons) and also implements the accessor function
  197. // wxGetApp() which will return the reference of the right type (i.e. MyApp and
  198. // not wxApp)
  199. IMPLEMENT_APP(MyApp)
  200. // ============================================================================
  201. // MyApp implementation
  202. // ============================================================================
  203. // 'Main program' equivalent: the program execution "starts" here
  204. bool MyApp::OnInit()
  205. {
  206. if ( !wxApp::OnInit() )
  207. return false;
  208. // create the main application window
  209. MyFrame *frame = new MyFrame();
  210. // and show it (the frames, unlike simple controls, are not shown when
  211. // created initially)
  212. frame->Show(true);
  213. // success: wxApp::OnRun() will be called which will enter the main message
  214. // loop and the application will run. If we returned false here, the
  215. // application would exit immediately.
  216. return true;
  217. }
  218. bool MyApp::OnExceptionInMainLoop()
  219. {
  220. try
  221. {
  222. throw;
  223. }
  224. catch ( int i )
  225. {
  226. wxLogWarning(wxT("Caught an int %d in MyApp."), i);
  227. }
  228. catch ( MyException& e )
  229. {
  230. wxLogWarning(wxT("Caught MyException(%s) in MyApp."), e.what());
  231. }
  232. catch ( ... )
  233. {
  234. throw;
  235. }
  236. return true;
  237. }
  238. void MyApp::OnUnhandledException()
  239. {
  240. // this shows how we may let some exception propagate uncaught
  241. try
  242. {
  243. throw;
  244. }
  245. catch ( UnhandledException& )
  246. {
  247. throw;
  248. }
  249. catch ( ... )
  250. {
  251. wxMessageBox(wxT("Unhandled exception caught, program will terminate."),
  252. wxT("wxExcept Sample"), wxOK | wxICON_ERROR);
  253. }
  254. }
  255. void MyApp::OnFatalException()
  256. {
  257. wxMessageBox(wxT("Program has crashed and will terminate."),
  258. wxT("wxExcept Sample"), wxOK | wxICON_ERROR);
  259. }
  260. void MyApp::OnAssertFailure(const wxChar *file,
  261. int line,
  262. const wxChar *func,
  263. const wxChar *cond,
  264. const wxChar *msg)
  265. {
  266. // take care to not show the message box from a worker thread, this doesn't
  267. // work as it doesn't have any event loop
  268. if ( !wxIsMainThread() ||
  269. wxMessageBox
  270. (
  271. wxString::Format("An assert failed in %s().", func) +
  272. "\n"
  273. "Do you want to call the default assert handler?",
  274. "wxExcept Sample",
  275. wxYES_NO | wxICON_QUESTION
  276. ) == wxYES )
  277. {
  278. wxApp::OnAssertFailure(file, line, func, cond, msg);
  279. }
  280. }
  281. // ============================================================================
  282. // MyFrame implementation
  283. // ============================================================================
  284. // frame constructor
  285. MyFrame::MyFrame()
  286. : wxFrame(NULL, wxID_ANY, wxT("Except wxWidgets App"),
  287. wxPoint(50, 50), wxSize(450, 340))
  288. {
  289. // set the frame icon
  290. SetIcon(wxICON(sample));
  291. #if wxUSE_MENUS
  292. // create a menu bar
  293. wxMenu *menuFile = new wxMenu;
  294. menuFile->Append(Except_Dialog, wxT("Show &dialog\tCtrl-D"));
  295. menuFile->AppendSeparator();
  296. menuFile->Append(Except_ThrowInt, wxT("Throw an &int\tCtrl-I"));
  297. menuFile->Append(Except_ThrowString, wxT("Throw a &string\tCtrl-S"));
  298. menuFile->Append(Except_ThrowObject, wxT("Throw an &object\tCtrl-O"));
  299. menuFile->Append(Except_ThrowUnhandled,
  300. wxT("Throw &unhandled exception\tCtrl-U"));
  301. menuFile->Append(Except_Crash, wxT("&Crash\tCtrl-C"));
  302. menuFile->Append(Except_Trap, "&Trap\tCtrl-T",
  303. "Break into the debugger (if one is running)");
  304. menuFile->AppendSeparator();
  305. #if wxUSE_ON_FATAL_EXCEPTION
  306. menuFile->AppendCheckItem(Except_HandleCrash, wxT("&Handle crashes\tCtrl-H"));
  307. menuFile->AppendSeparator();
  308. #endif // wxUSE_ON_FATAL_EXCEPTION
  309. menuFile->Append(Except_ShowAssert, wxT("Provoke &assert failure\tCtrl-A"));
  310. #if wxUSE_THREADS
  311. menuFile->Append(Except_ShowAssertInThread,
  312. wxT("Assert failure in &thread\tShift-Ctrl-A"));
  313. #endif // wxUSE_THREADS
  314. menuFile->AppendSeparator();
  315. menuFile->Append(Except_Quit, wxT("E&xit\tCtrl-Q"), wxT("Quit this program"));
  316. wxMenu *helpMenu = new wxMenu;
  317. helpMenu->Append(Except_About, wxT("&About\tF1"), wxT("Show about dialog"));
  318. // now append the freshly created menu to the menu bar...
  319. wxMenuBar *menuBar = new wxMenuBar();
  320. menuBar->Append(menuFile, wxT("&File"));
  321. menuBar->Append(helpMenu, wxT("&Help"));
  322. // ... and attach this menu bar to the frame
  323. SetMenuBar(menuBar);
  324. #endif // wxUSE_MENUS
  325. #if wxUSE_STATUSBAR && !defined(__WXWINCE__)
  326. // create a status bar just for fun (by default with 1 pane only)
  327. CreateStatusBar(2);
  328. SetStatusText(wxT("Welcome to wxWidgets!"));
  329. #endif // wxUSE_STATUSBAR
  330. }
  331. bool MyFrame::ProcessEvent(wxEvent& event)
  332. {
  333. try
  334. {
  335. return wxFrame::ProcessEvent(event);
  336. }
  337. catch ( const wxChar *msg )
  338. {
  339. wxLogMessage(wxT("Caught a string \"%s\" in MyFrame"), msg);
  340. return true;
  341. }
  342. }
  343. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  344. {
  345. // true is to force the frame to close
  346. Close(true);
  347. }
  348. void MyFrame::OnDialog(wxCommandEvent& WXUNUSED(event))
  349. {
  350. try
  351. {
  352. MyDialog dlg(this);
  353. dlg.ShowModal();
  354. }
  355. catch ( ... )
  356. {
  357. wxLogWarning(wxT("An exception in MyDialog"));
  358. Destroy();
  359. throw;
  360. }
  361. }
  362. void MyFrame::OnThrowInt(wxCommandEvent& WXUNUSED(event))
  363. {
  364. throw -17;
  365. }
  366. void MyFrame::OnThrowString(wxCommandEvent& WXUNUSED(event))
  367. {
  368. throw wxT("string thrown from MyFrame");
  369. }
  370. void MyFrame::OnThrowObject(wxCommandEvent& WXUNUSED(event))
  371. {
  372. throw MyException(wxT("Exception thrown from MyFrame"));
  373. }
  374. void MyFrame::OnThrowUnhandled(wxCommandEvent& WXUNUSED(event))
  375. {
  376. throw UnhandledException();
  377. }
  378. void MyFrame::OnCrash(wxCommandEvent& WXUNUSED(event))
  379. {
  380. DoCrash();
  381. }
  382. void MyFrame::OnTrap(wxCommandEvent& WXUNUSED(event))
  383. {
  384. wxTrap();
  385. }
  386. #if wxUSE_ON_FATAL_EXCEPTION
  387. void MyFrame::OnHandleCrash(wxCommandEvent& event)
  388. {
  389. wxHandleFatalExceptions(event.IsChecked());
  390. }
  391. #endif // wxUSE_ON_FATAL_EXCEPTION
  392. void MyFrame::OnShowAssert(wxCommandEvent& WXUNUSED(event))
  393. {
  394. // provoke an assert from wxArrayString
  395. wxArrayString arr;
  396. arr[0];
  397. }
  398. #if wxUSE_THREADS
  399. void MyFrame::OnShowAssertInThread(wxCommandEvent& WXUNUSED(event))
  400. {
  401. class AssertThread : public wxThread
  402. {
  403. public:
  404. AssertThread()
  405. : wxThread(wxTHREAD_JOINABLE)
  406. {
  407. }
  408. protected:
  409. virtual void *Entry()
  410. {
  411. wxFAIL_MSG("Test assert in another thread.");
  412. return 0;
  413. }
  414. };
  415. AssertThread thread;
  416. thread.Create();
  417. thread.Run();
  418. thread.Wait();
  419. }
  420. #endif // wxUSE_THREADS
  421. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  422. {
  423. wxString msg;
  424. msg.Printf( wxT("This is the About dialog of the except sample.\n")
  425. wxT("Welcome to %s"), wxVERSION_STRING);
  426. wxMessageBox(msg, wxT("About Except"), wxOK | wxICON_INFORMATION, this);
  427. }
  428. // ============================================================================
  429. // MyDialog implementation
  430. // ============================================================================
  431. MyDialog::MyDialog(wxFrame *parent)
  432. : wxDialog(parent, wxID_ANY, wxString(wxT("Throw exception dialog")))
  433. {
  434. wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
  435. sizerTop->Add(new wxButton(this, Except_ThrowInt, wxT("Throw &int")),
  436. 0, wxCENTRE | wxALL, 5);
  437. sizerTop->Add(new wxButton(this, Except_ThrowObject, wxT("Throw &object")),
  438. 0, wxCENTRE | wxALL, 5);
  439. sizerTop->Add(new wxButton(this, Except_Crash, wxT("&Crash")),
  440. 0, wxCENTRE | wxALL, 5);
  441. sizerTop->Add(new wxButton(this, wxID_CANCEL, wxT("&Cancel")),
  442. 0, wxCENTRE | wxALL, 5);
  443. SetSizerAndFit(sizerTop);
  444. }
  445. void MyDialog::OnThrowInt(wxCommandEvent& WXUNUSED(event))
  446. {
  447. throw 17;
  448. }
  449. void MyDialog::OnThrowObject(wxCommandEvent& WXUNUSED(event))
  450. {
  451. throw MyException(wxT("Exception thrown from MyDialog"));
  452. }
  453. void MyDialog::OnCrash(wxCommandEvent& WXUNUSED(event))
  454. {
  455. DoCrash();
  456. }