@@ -79,7 +79,9 @@ int giMajorVersion = 0;
79
79
int giMinorVersion = 0 ;
80
80
int giBuildNumber = 0 ;
81
81
#endif
82
-
82
+ #if defined( WANT_SINGLE_INSTANCE )
83
+ wxSingleInstanceChecker *gp_checker;
84
+ #endif
83
85
// ------------------------------------------------------------------
84
86
#include < wx/listimpl.cpp>
85
87
WX_DEFINE_LIST ( MyAccountList );
@@ -101,7 +103,10 @@ wxBEGIN_EVENT_TABLE(MyApp, wxApp)
101
103
EVT_DIALUP_CONNECTED (MyApp::OnConnected)
102
104
EVT_DIALUP_DISCONNECTED(MyApp::OnConnected)
103
105
#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
105
110
wxEND_EVENT_TABLE ()
106
111
107
112
// ------------------------------------------------------------------
@@ -111,13 +116,15 @@ MyApp::MyApp()
111
116
m_frame = NULL ;
112
117
m_pConfig = NULL ;
113
118
#if defined( WANT_SINGLE_INSTANCE )
114
- m_checker = NULL ;
119
+ gp_checker = NULL ;
115
120
#endif
116
121
#if defined( WANT_LOG_CHAIN )
117
122
m_pLogChain = NULL ;
118
123
m_pAppLog = NULL ;
119
124
#endif
125
+ #if defined( WANT_NEW_STOP )
120
126
m_bShuttingDown = false ;
127
+ #endif
121
128
m_pFilterConfig = NULL ;
122
129
m_pLogWindow = NULL ;
123
130
m_bSilentMode = false ;
@@ -144,11 +151,16 @@ MyApp::MyApp()
144
151
// -------------------------------------------------------------------
145
152
// Public methods
146
153
// -------------------------------------------------------------------
147
- #if defined( WANT_SINGLE_INSTANCE )
148
- wxSingleInstanceChecker *m_checker;
154
+
149
155
MyApp::~MyApp ()
150
156
{
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
152
164
#if defined( WANT_TASKBAR )
153
165
delete m_pTaskBarIcon;
154
166
#endif
@@ -158,13 +170,20 @@ MyApp::~MyApp()
158
170
#endif
159
171
return ;
160
172
}
161
- #else
162
- MyApp::~MyApp (){;}
163
- #endif
164
173
165
174
// ------------------------------------------------------------------
166
175
/* *
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().
168
187
*/
169
188
int MyApp::OnExit ()
170
189
{
@@ -174,7 +193,45 @@ int MyApp::OnExit()
174
193
SaveFilterConfig ();
175
194
return 0 ;
176
195
}
196
+ #if defined( WANT_NEW_STOP )
177
197
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
178
235
// ------------------------------------------------------------------
179
236
int MyApp::OnRun ()
180
237
{
@@ -187,7 +244,9 @@ bool MyApp::OnInit()
187
244
{
188
245
theApp = this ;
189
246
m_dial = NULL ;
190
-
247
+ #if defined( WANT_LOG_CHAIN )
248
+ m_pLogChain = NULL ;
249
+ #endif
191
250
// stops the warning dialog from libpng "iCCP: known incorrect sRGB profile
192
251
wxLogNull logNo;
193
252
::wxInitAllImageHandlers (); // IMPORTANT for wxCrafter
@@ -281,12 +340,19 @@ bool MyApp::OnInit()
281
340
#endif
282
341
#if defined( WANT_SINGLE_INSTANCE )
283
342
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 () )
286
345
{
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 ;
290
356
return false ;
291
357
}
292
358
#endif
@@ -369,11 +435,48 @@ bool MyApp::OnInit()
369
435
RestoreConfig ();
370
436
if ( g_iniPrefs.data [IE_OPT_LAST_CONF_FILE].dataCurrent .wsVal .IsEmpty () )
371
437
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
372
472
m_frame->SetSize ( g_iniPrefs.data [IE_FRAME_X].dataCurrent .lVal ,
373
473
g_iniPrefs.data [IE_FRAME_Y].dataCurrent .lVal ,
374
474
g_iniPrefs.data [IE_FRAME_W].dataCurrent .lVal ,
375
475
g_iniPrefs.data [IE_FRAME_H].dataCurrent .lVal );
476
+ #endif
376
477
RestoreAccounts ();
478
+ // see if any accounts are active/enabled
479
+ m_frame->m_bAnyAccountsActive = m_frame->GetAccountInfo ();
377
480
m_frame->RestoreColWidths ();
378
481
m_frame->RestoreColLabels ();
379
482
m_frame->InitializeMailGrid ();
@@ -399,17 +502,18 @@ bool MyApp::OnInit()
399
502
m_wsCurLogFileName = g_iniPrefs.data [IE_LOG_DIR_PATH].dataCurrent .wsVal + _T (" /" ) + WS_LOG_FILE_NAME;
400
503
if ( g_iniPrefs.data [IE_LOG_FILE_WANTED].dataCurrent .bVal )
401
504
{
505
+ // log size limit & rotation is handled by called routine
402
506
CreateNewLog ();
403
507
}
404
508
#endif // WANT_LOG_CHAIN
405
509
// Show the frame as it's created initially hidden.
406
510
m_frame->Show (true );
407
511
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
413
517
#if defined( WANT_MSVC_INTERNET_TEST )
414
518
// Init dial up manager
415
519
m_dial = wxDialUpManager::Create ();
@@ -419,7 +523,6 @@ bool MyApp::OnInit()
419
523
#if wxUSE_LOG
420
524
wxLog::GetActiveTarget ()->Flush ();
421
525
#endif // wxUSE_LOG
422
-
423
526
// do it here, OnExit() won't be called
424
527
delete m_dial;
425
528
m_dial = NULL ;
@@ -430,7 +533,7 @@ bool MyApp::OnInit()
430
533
if ( m_frame->CheckConnectivity ())
431
534
{
432
535
if ( g_iniPrefs.data [IE_OPT_AUTO_UPDATE_CHECK].dataCurrent .bVal )
433
- m_frame->Check4Update ();
536
+ m_frame->Check4Update ( false );
434
537
// check & download mail at start up?
435
538
if ( g_iniPrefs.data [IE_CHECK_MAIL_STARTUP].dataCurrent .bVal )
436
539
{
@@ -440,14 +543,19 @@ bool MyApp::OnInit()
440
543
}
441
544
#endif
442
545
#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.
443
548
if ( IsInternetAvailable () )
444
549
{
445
550
if ( g_iniPrefs.data [IE_OPT_AUTO_UPDATE_CHECK].dataCurrent .bVal )
446
- m_frame->Check4Update ();
551
+ m_frame->Check4Update ( false );
447
552
// check & download mail at start up?
448
553
if ( g_iniPrefs.data [IE_CHECK_MAIL_STARTUP].dataCurrent .bVal )
449
554
{
450
555
// check default account as left by user last time
556
+ // ::wxYield();
557
+ // m_frame->Refresh();
558
+ // ::wxSleep( 10 );
451
559
m_frame->Check4NewMail ();
452
560
}
453
561
}
@@ -458,6 +566,12 @@ bool MyApp::OnInit()
458
566
// wxLogMessage( wsT ); // does not show
459
567
}
460
568
#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
+ }
461
575
// Return true to tell program to continue (false would terminate).
462
576
return true ;
463
577
}
0 commit comments