@@ -79,7 +79,9 @@ int giMajorVersion = 0;
7979int giMinorVersion = 0 ;
8080int giBuildNumber = 0 ;
8181#endif
82-
82+ #if defined( WANT_SINGLE_INSTANCE )
83+ wxSingleInstanceChecker *gp_checker;
84+ #endif
8385// ------------------------------------------------------------------
8486#include < wx/listimpl.cpp>
8587WX_DEFINE_LIST ( MyAccountList );
@@ -101,7 +103,10 @@ wxBEGIN_EVENT_TABLE(MyApp, wxApp)
101103 EVT_DIALUP_CONNECTED (MyApp::OnConnected)
102104 EVT_DIALUP_DISCONNECTED(MyApp::OnConnected)
103105#endif
104- // EVT_CLOSE( MyFrame::OnClose )
106+ #if defined( WANT_NEW_STOP )
107+ EVT_QUERY_END_SESSION ( MyApp::OnAppQueryEndSession )
108+ EVT_END_SESSION(MyApp::OnAppEndSession)
109+ #endif
105110wxEND_EVENT_TABLE ()
106111
107112// ------------------------------------------------------------------
@@ -111,13 +116,15 @@ MyApp::MyApp()
111116 m_frame = NULL ;
112117 m_pConfig = NULL ;
113118#if defined( WANT_SINGLE_INSTANCE )
114- m_checker = NULL ;
119+ gp_checker = NULL ;
115120#endif
116121#if defined( WANT_LOG_CHAIN )
117122 m_pLogChain = NULL ;
118123 m_pAppLog = NULL ;
119124#endif
125+ #if defined( WANT_NEW_STOP )
120126 m_bShuttingDown = false ;
127+ #endif
121128 m_pFilterConfig = NULL ;
122129 m_pLogWindow = NULL ;
123130 m_bSilentMode = false ;
@@ -144,11 +151,16 @@ MyApp::MyApp()
144151// -------------------------------------------------------------------
145152// Public methods
146153// -------------------------------------------------------------------
147- #if defined( WANT_SINGLE_INSTANCE )
148- wxSingleInstanceChecker *m_checker;
154+
149155MyApp::~MyApp ()
150156{
151- delete m_checker;
157+ #if defined( WANT_SINGLE_INSTANCE )
158+ if ( gp_checker )
159+ {
160+ delete gp_checker;
161+ gp_checker = NULL ;
162+ }
163+ #endif
152164#if defined( WANT_TASKBAR )
153165 delete m_pTaskBarIcon;
154166#endif
@@ -158,13 +170,20 @@ MyApp::~MyApp()
158170#endif
159171 return ;
160172}
161- #else
162- MyApp::~MyApp (){;}
163- #endif
164173
165174// ------------------------------------------------------------------
166175/* *
167- * Only get here from red 'x' on main frame.
176+ * Only get here from red 'x' on main frame or
177+ * when the system shuts down and sends the message to OnAppEndSession().
178+ * Therefore any saving of critical data MUST be done here !!!!!!!!!!!!!!!!!!!!!!
179+ * Stopping the threads needs/ought to be done in the main frame dtor
180+ */
181+ /* * More info from an old discussion ( 2008 & msw 2.8.7
182+ * from: http://wxwidgets.10942.n7.nabble.com/msw-2-8-7-Problem-saving-application-settings-when-system-is-shut-down-td24744.html
183+ * If this code makes it into the library, maybe it should be mentioned
184+ * in the docs that the wxApp dtor will not get called if the
185+ * WM_ENDSESSION is received, so if anyone has important cleanup code in
186+ * his dtor, he can move the code to wxApp::OnExit().
168187 */
169188int MyApp::OnExit ()
170189{
@@ -174,7 +193,45 @@ int MyApp::OnExit()
174193 SaveFilterConfig ();
175194 return 0 ;
176195}
196+ #if defined( WANT_NEW_STOP )
177197
198+ // ------------------------------------------------------------------
199+ /* *
200+ * Called when the OS is trying to kill the application and it is called
201+ * before OnAppEndSession()
202+ * In either case we have 5 seconds to clean up, before the shut down is forced
203+ * see: https://docs.microsoft.com/en-us/windows/desktop/Shutdown/shutdown-changes-for-windows-vista
204+ */
205+ void MyApp::OnAppQueryEndSession (wxCloseEvent& event)
206+ {
207+ // called when the system is shutting down
208+ // can be tested using
209+ // C:\Program Files (x86)\Windows Kits\10\App Certification Kit\rmlogotest.exe"
210+ // which needs the process ID
211+ // see also comments in wxCloseEvent handler
212+ // it seems we can also use
213+ // GetLoggingOff () const
214+ // Returns true if the user is just logging off or false if the system is shutting down.
215+ // This method can only be called for end session and query end session events, it doesn't
216+ // make sense for close window event.
217+ // if multi-threading, here we can check and stop all threads if any are running.
218+ // see the thread example in MSVC 2015/examples
219+ //
220+ #if defined( WANT_NEW_STOP )
221+ m_bShuttingDown = true ;
222+ #endif
223+
224+ // all shutdown related work is best done in main frame dtor
225+ event.Skip ();
226+
227+ }
228+
229+ // ------------------------------------------------------------------
230+ void MyApp::OnAppEndSession (wxCloseEvent& event)
231+ {
232+ event.Skip ();
233+ }
234+ #endif
178235// ------------------------------------------------------------------
179236int MyApp::OnRun ()
180237{
@@ -187,7 +244,9 @@ bool MyApp::OnInit()
187244{
188245 theApp = this ;
189246 m_dial = NULL ;
190-
247+ #if defined( WANT_LOG_CHAIN )
248+ m_pLogChain = NULL ;
249+ #endif
191250 // stops the warning dialog from libpng "iCCP: known incorrect sRGB profile
192251 wxLogNull logNo;
193252 ::wxInitAllImageHandlers (); // IMPORTANT for wxCrafter
@@ -281,12 +340,19 @@ bool MyApp::OnInit()
281340#endif
282341#if defined( WANT_SINGLE_INSTANCE )
283342 const wxString name = wxString::Format (_T (" %s-%s" ), m_wsAppName, wxGetUserId () );
284- m_checker = new wxSingleInstanceChecker (name);
285- if ( m_checker ->IsAnotherRunning () )
343+ gp_checker = new wxSingleInstanceChecker (name);
344+ if ( gp_checker ->IsAnotherRunning () )
286345 {
287- wxLogError (_ (" Another program instance is already running, aborting." ));
288- delete m_checker; // OnExit() won't be called if we return false
289- m_checker = NULL ;
346+ wxLogError ( _ (" Another program instance is already running, aborting." ) );
347+ // does not show either, because the debugger termiates as well in this case
348+ wxLogDebug ( _ (" Another program instance is already running, aborting." ) );
349+ wxBell ();
350+ wxString wsMsg;
351+ wsMsg.Printf ( _ (" Another program instance of %s-%s is already running, aborting." ),
352+ m_wsAppName, wxGetUserId () );
353+ wxMessageBox ( wsMsg, _ (" Error" ), wxOK );
354+ delete gp_checker; // OnExit() won't be called if we return false
355+ gp_checker = NULL ;
290356 return false ;
291357 }
292358#endif
@@ -369,11 +435,48 @@ bool MyApp::OnInit()
369435 RestoreConfig ();
370436 if ( g_iniPrefs.data [IE_OPT_LAST_CONF_FILE].dataCurrent .wsVal .IsEmpty () )
371437 g_iniPrefs.data [IE_OPT_LAST_CONF_FILE].dataCurrent .wsVal = m_wsConfigDir;
438+ #if defined( WANT_SCALING )
439+ // shrink app frame at startup is new reso;ution is smaller than old
440+ int x, y;
441+ wxDisplaySize ( &x, &y );
442+ if ( x < g_iniPrefs.data [IE_RESOLUTION_X].dataCurrent .lVal )
443+ {
444+ g_iniPrefs.data [IE_FRAME_W].dataCurrent .lVal *=
445+ (x / g_iniPrefs.data [IE_RESOLUTION_X].dataCurrent .lVal );
446+ }
447+ if ( y < g_iniPrefs.data [IE_RESOLUTION_Y].dataCurrent .lVal )
448+ {
449+ g_iniPrefs.data [IE_FRAME_W].dataCurrent .lVal *=
450+ (y / g_iniPrefs.data [IE_RESOLUTION_Y].dataCurrent .lVal );
451+ }
452+ #endif
453+ #if defined( WANT_MONITOR_CHECK )
454+ const size_t count = wxDisplay::GetCount ();
455+ int iWin = wxDisplay::GetFromWindow ( m_frame );
456+ // sets both size & position
457+ m_frame->SetSize ( g_iniPrefs.data [IE_FRAME_X].dataCurrent .lVal ,
458+ g_iniPrefs.data [IE_FRAME_Y].dataCurrent .lVal ,
459+ g_iniPrefs.data [IE_FRAME_W].dataCurrent .lVal ,
460+ g_iniPrefs.data [IE_FRAME_H].dataCurrent .lVal );
461+ iWin = wxDisplay::GetFromWindow ( m_frame );
462+ if ( iWin == wxNOT_FOUND ) // the coordinates are on a different screen
463+ {
464+ // repositon it to the primary screen, whichever that ends up as.
465+ // in this way, I expect that the user can then carry on, resizing
466+ // and repositioning as needed
467+ m_frame->SetSize ( 10 , 10 ,
468+ g_iniPrefs.data [IE_FRAME_W].dataCurrent .lVal ,
469+ g_iniPrefs.data [IE_FRAME_H].dataCurrent .lVal );
470+ }
471+ #else
372472 m_frame->SetSize ( g_iniPrefs.data [IE_FRAME_X].dataCurrent .lVal ,
373473 g_iniPrefs.data [IE_FRAME_Y].dataCurrent .lVal ,
374474 g_iniPrefs.data [IE_FRAME_W].dataCurrent .lVal ,
375475 g_iniPrefs.data [IE_FRAME_H].dataCurrent .lVal );
476+ #endif
376477 RestoreAccounts ();
478+ // see if any accounts are active/enabled
479+ m_frame->m_bAnyAccountsActive = m_frame->GetAccountInfo ();
377480 m_frame->RestoreColWidths ();
378481 m_frame->RestoreColLabels ();
379482 m_frame->InitializeMailGrid ();
@@ -399,17 +502,18 @@ bool MyApp::OnInit()
399502 m_wsCurLogFileName = g_iniPrefs.data [IE_LOG_DIR_PATH].dataCurrent .wsVal + _T (" /" ) + WS_LOG_FILE_NAME;
400503 if ( g_iniPrefs.data [IE_LOG_FILE_WANTED].dataCurrent .bVal )
401504 {
505+ // log size limit & rotation is handled by called routine
402506 CreateNewLog ();
403507 }
404508#endif // WANT_LOG_CHAIN
405509 // Show the frame as it's created initially hidden.
406510 m_frame->Show (true );
407511 m_frame->GetGaugeProgress ()->SetValue ( 0 );
408- // start the mail check timer if user wants it so
409- if ( g_iniPrefs. data [IE_SCHEDULE_MAIL_CHECK]. dataCurrent . bVal )
410- {
411- m_frame->GetMailTimerPtr ()-> Start ( 60 * 1000 );
412- }
512+
513+ // ::wxYield(); // causes crash
514+ // adding this delay here does not show tool bar icons
515+ m_frame->Refresh ( );
516+ ::wxMilliSleep ( 500 ); // give GUI a chance to settle before we check mail
413517#if defined( WANT_MSVC_INTERNET_TEST )
414518 // Init dial up manager
415519 m_dial = wxDialUpManager::Create ();
@@ -419,7 +523,6 @@ bool MyApp::OnInit()
419523#if wxUSE_LOG
420524 wxLog::GetActiveTarget ()->Flush ();
421525#endif // wxUSE_LOG
422-
423526 // do it here, OnExit() won't be called
424527 delete m_dial;
425528 m_dial = NULL ;
@@ -430,7 +533,7 @@ bool MyApp::OnInit()
430533 if ( m_frame->CheckConnectivity ())
431534 {
432535 if ( g_iniPrefs.data [IE_OPT_AUTO_UPDATE_CHECK].dataCurrent .bVal )
433- m_frame->Check4Update ();
536+ m_frame->Check4Update ( false );
434537 // check & download mail at start up?
435538 if ( g_iniPrefs.data [IE_CHECK_MAIL_STARTUP].dataCurrent .bVal )
436539 {
@@ -440,14 +543,19 @@ bool MyApp::OnInit()
440543 }
441544#endif
442545#if defined( _MSC_VER )
546+ #if !defined( WANT_STARTUP_IN_IDLE )
547+ // if this is used the tool bar will NOT show until after the mail check returns.
443548 if ( IsInternetAvailable () )
444549 {
445550 if ( g_iniPrefs.data [IE_OPT_AUTO_UPDATE_CHECK].dataCurrent .bVal )
446- m_frame->Check4Update ();
551+ m_frame->Check4Update ( false );
447552 // check & download mail at start up?
448553 if ( g_iniPrefs.data [IE_CHECK_MAIL_STARTUP].dataCurrent .bVal )
449554 {
450555 // check default account as left by user last time
556+ // ::wxYield();
557+ // m_frame->Refresh();
558+ // ::wxSleep( 10 );
451559 m_frame->Check4NewMail ();
452560 }
453561 }
@@ -458,6 +566,12 @@ bool MyApp::OnInit()
458566 // wxLogMessage( wsT ); // does not show
459567 }
460568#endif
569+ #endif
570+ // start the mail check timer if user wants it so
571+ if ( g_iniPrefs.data [IE_SCHEDULE_MAIL_CHECK].dataCurrent .bVal )
572+ {
573+ m_frame->GetMailTimerPtr ()->Start ( 60 * 1000 );
574+ }
461575 // Return true to tell program to continue (false would terminate).
462576 return true ;
463577}
0 commit comments