]> git.saurik.com Git - wxWidgets.git/blame - src/msw/main.cpp
do use the font in DoGetTextExtent()
[wxWidgets.git] / src / msw / main.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
d5da0ce7 2// Name: src/msw/main.cpp
e2478fde 3// Purpose: WinMain/DllMain
2bda0e17
KB
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
b568d04f
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
b568d04f 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
d5da0ce7
WS
27#ifndef WX_PRECOMP
28 #include "wx/event.h"
670f9935 29 #include "wx/app.h"
c43507b0 30 #include "wx/utils.h"
d5da0ce7
WS
31#endif //WX_PRECOMP
32
94826170 33#include "wx/cmdline.h"
48733d47 34#include "wx/scopeguard.h"
b568d04f
VZ
35
36#include "wx/msw/private.h"
39ea2103 37#include "wx/msw/seh.h"
b568d04f 38
8c125d13
VZ
39#if wxUSE_ON_FATAL_EXCEPTION
40 #include "wx/datetime.h"
41 #include "wx/msw/crashrpt.h"
8c125d13
VZ
42#endif // wxUSE_ON_FATAL_EXCEPTION
43
44#ifdef __WXWINCE__
45 // there is no ExitProcess() under CE but exiting the main thread has the
46 // same effect
226c11c0
VZ
47 #ifndef ExitProcess
48 #define ExitProcess ExitThread
49 #endif
50#endif // __WXWINCE__
8c125d13 51
e2478fde
VZ
52#ifdef __BORLANDC__
53 // BC++ has to be special: its run-time expects the DLL entry point to be
54 // named DllEntryPoint instead of the (more) standard DllMain
55 #define DllMain DllEntryPoint
226c11c0 56#endif // __BORLANDC__
e2478fde
VZ
57
58#if defined(__WXMICROWIN__)
59 #define HINSTANCE HANDLE
60#endif
beed393c 61
1ac4716d
VZ
62// defined in common/init.cpp
63extern int wxEntryReal(int& argc, wxChar **argv);
64
b568d04f 65// ============================================================================
e2478fde 66// implementation: various entry points
b568d04f
VZ
67// ============================================================================
68
226c11c0
VZ
69#if wxUSE_BASE
70
84bdb0d8 71#if wxUSE_ON_FATAL_EXCEPTION && defined(__VISUALC__) && !defined(__WXWINCE__)
226c11c0
VZ
72 // VC++ (at least from 4.0 up to version 7.1) is incredibly broken in that
73 // a "catch ( ... )" will *always* catch SEH exceptions in it even though
74 // it should have never been the case... to prevent such catches from
75 // stealing the exceptions from our wxGlobalSEHandler which is only called
76 // if the exception is not handled elsewhere, we have to also call it from
77 // a special SEH translator function which is called by VC CRT when a Win32
78 // exception occurs
79
80 // this warns that /EHa (async exceptions) should be used when using
81 // _set_se_translator but, in fact, this doesn't seem to change anything
23c06cde
VZ
82 // with VC++ up to 8.0
83 #if _MSC_VER <= 1400
226c11c0
VZ
84 #pragma warning(disable:4535)
85 #endif
86
87 // note that the SE translator must be called wxSETranslator!
88 #define DisableAutomaticSETranslator() _set_se_translator(wxSETranslator)
89#else // !__VISUALC__
90 #define DisableAutomaticSETranslator()
91#endif // __VISUALC__/!__VISUALC__
92
8c125d13 93// ----------------------------------------------------------------------------
3103e8a9 94// wrapper wxEntry catching all Win32 exceptions occurring in a wx program
8c125d13
VZ
95// ----------------------------------------------------------------------------
96
97// wrap real wxEntry in a try-except block to be able to call
98// OnFatalException() if necessary
226c11c0
VZ
99#if wxUSE_ON_FATAL_EXCEPTION
100
8c125d13
VZ
101// global pointer to exception information, only valid inside OnFatalException,
102// used by wxStackWalker and wxCrashReport
103extern EXCEPTION_POINTERS *wxGlobalSEInformation = NULL;
104
105// flag telling us whether the application wants to handle exceptions at all
106static bool gs_handleExceptions = false;
107
226c11c0
VZ
108static void wxFatalExit()
109{
110 // use the same exit code as abort()
111 ::ExitProcess(3);
112}
113
8c125d13
VZ
114unsigned long wxGlobalSEHandler(EXCEPTION_POINTERS *pExcPtrs)
115{
116 if ( gs_handleExceptions && wxTheApp )
117 {
118 // store the pointer to exception info
119 wxGlobalSEInformation = pExcPtrs;
120
121 // give the user a chance to do something special about this
39ea2103 122 wxSEH_TRY
8c125d13
VZ
123 {
124 wxTheApp->OnFatalException();
125 }
39ea2103 126 wxSEH_IGNORE // ignore any exceptions inside the exception handler
8c125d13
VZ
127
128 wxGlobalSEInformation = NULL;
129
130 // this will execute our handler and terminate the process
131 return EXCEPTION_EXECUTE_HANDLER;
132 }
133
134 return EXCEPTION_CONTINUE_SEARCH;
135}
136
137#ifdef __VISUALC__
138
39ea2103 139void wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS *ep)
8c125d13 140{
226c11c0
VZ
141 switch ( wxGlobalSEHandler(ep) )
142 {
143 default:
144 wxFAIL_MSG( _T("unexpected wxGlobalSEHandler() return value") );
145 // fall through
146
147 case EXCEPTION_EXECUTE_HANDLER:
148 // if wxApp::OnFatalException() had been called we should exit the
149 // application -- but we shouldn't kill our host when we're a DLL
150#ifndef WXMAKINGDLL
151 wxFatalExit();
152#endif // not a DLL
153 break;
154
155 case EXCEPTION_CONTINUE_SEARCH:
156 // we're called for each "catch ( ... )" and if we (re)throw from
157 // here, the catch handler body is not executed, so the effect is
158 // as if had inhibited translation of SE to C++ ones because the
159 // handler will never see any structured exceptions
160 throw;
161 }
8c125d13
VZ
162}
163
164#endif // __VISUALC__
165
166bool wxHandleFatalExceptions(bool doit)
167{
168 // assume this can only be called from the main thread
169 gs_handleExceptions = doit;
170
8c125d13
VZ
171#if wxUSE_CRASHREPORT
172 if ( doit )
173 {
174 // try to find a place where we can put out report file later
175 wxChar fullname[MAX_PATH];
176 if ( !::GetTempPath(WXSIZEOF(fullname), fullname) )
177 {
178 wxLogLastError(_T("GetTempPath"));
179
180 // when all else fails...
181 wxStrcpy(fullname, _T("c:\\"));
182 }
183
184 // use PID and date to make the report file name more unique
185 wxString name = wxString::Format
186 (
187 _T("%s_%s_%lu.dmp"),
c9f78968 188 wxTheApp ? (const wxChar*)wxTheApp->GetAppName().c_str()
8c125d13
VZ
189 : _T("wxwindows"),
190 wxDateTime::Now().Format(_T("%Y%m%dT%H%M%S")).c_str(),
191 ::GetCurrentProcessId()
192 );
193
194 wxStrncat(fullname, name, WXSIZEOF(fullname) - wxStrlen(fullname) - 1);
195
196 wxCrashReport::SetFileName(fullname);
197 }
198#endif // wxUSE_CRASHREPORT
199
200 return true;
201}
202
203int wxEntry(int& argc, wxChar **argv)
204{
226c11c0
VZ
205 DisableAutomaticSETranslator();
206
39ea2103 207 wxSEH_TRY
8c125d13 208 {
8c125d13
VZ
209 return wxEntryReal(argc, argv);
210 }
39ea2103 211 wxSEH_HANDLE(-1)
8c125d13
VZ
212}
213
226c11c0
VZ
214#else // !wxUSE_ON_FATAL_EXCEPTION
215
b734b2ca 216#if defined(__VISUALC__) && !defined(__WXWINCE__)
1ac4716d 217
226c11c0
VZ
218static void
219wxSETranslator(unsigned int WXUNUSED(code), EXCEPTION_POINTERS * WXUNUSED(ep))
220{
221 // see wxSETranslator() version for wxUSE_ON_FATAL_EXCEPTION above
222 throw;
223}
224
1ac4716d
VZ
225#endif // __VISUALC__
226
226c11c0
VZ
227int wxEntry(int& argc, wxChar **argv)
228{
229 DisableAutomaticSETranslator();
230
231 return wxEntryReal(argc, argv);
232}
233
234#endif // wxUSE_ON_FATAL_EXCEPTION/!wxUSE_ON_FATAL_EXCEPTION
235
236#endif // wxUSE_BASE
8c125d13 237
532d575b 238#if wxUSE_GUI && defined(__WXMSW__)
8c125d13 239
6f2df739
VZ
240#if wxUSE_UNICODE && !defined(__WXWINCE__)
241 #define NEED_UNICODE_CHECK
242#endif
94826170 243
6f2df739
VZ
244#ifdef NEED_UNICODE_CHECK
245
246// check whether Unicode is available
247static bool wxIsUnicodeAvailable()
94826170 248{
6f2df739
VZ
249 static const wchar_t *ERROR_STRING = L"wxWidgets Fatal Error";
250
406d283a 251 if ( wxGetOsVersion() != wxOS_WINDOWS_NT )
bd866271 252 {
69c54afe 253 // we need to be built with MSLU support
d5da0ce7 254#if !wxUSE_UNICODE_MSLU
bd866271
VZ
255 // note that we can use MessageBoxW() as it's implemented even under
256 // Win9x - OTOH, we can't use wxGetTranslation() because the file APIs
257 // used by wxLocale are not
258 ::MessageBox
259 (
260 NULL,
6f2df739
VZ
261 L"This program uses Unicode and requires Windows NT/2000/XP.\n"
262 L"\n"
263 L"Program aborted.",
264 ERROR_STRING,
bd866271
VZ
265 MB_ICONERROR | MB_OK
266 );
267
6f2df739 268 return false;
774960ce 269#else // wxUSE_UNICODE_MSLU
69c54afe
VZ
270 // and the MSLU DLL must also be available
271 HMODULE hmod = ::LoadLibraryA("unicows.dll");
272 if ( !hmod )
273 {
274 ::MessageBox
275 (
276 NULL,
6f2df739
VZ
277 L"This program uses Unicode and requires unicows.dll to work "
278 L"under current operating system.\n"
279 L"\n"
280 L"Please install unicows.dll and relaunch the program.",
281 ERROR_STRING,
69c54afe
VZ
282 MB_ICONERROR | MB_OK
283 );
6f2df739 284 return false;
69c54afe
VZ
285 }
286
287 // this is not really necessary but be tidy
288 ::FreeLibrary(hmod);
6f2df739
VZ
289
290 // finally do the last check: has unicows.lib initialized correctly?
291 hmod = ::LoadLibraryW(L"unicows.dll");
292 if ( !hmod )
293 {
294 ::MessageBox
295 (
296 NULL,
297 L"This program uses Unicode but is not using unicows.dll\n"
298 L"correctly and so cannot work under current operating system.\n"
299 L"Please contact the program author for an updated version.\n"
300 L"\n"
301 L"Program aborted.",
302 ERROR_STRING,
303 MB_ICONERROR | MB_OK
304 );
305
306 return false;
307 }
308
309 ::FreeLibrary(hmod);
774960ce 310#endif // !wxUSE_UNICODE_MSLU
bd866271 311 }
6f2df739
VZ
312
313 return true;
314}
315
316#endif // NEED_UNICODE_CHECK
317
318// ----------------------------------------------------------------------------
319// Windows-specific wxEntry
320// ----------------------------------------------------------------------------
321
48733d47
VZ
322// helper function used to clean up in wxEntry() just below
323//
324// notice that argv elements are supposed to be allocated using malloc() while
325// argv array itself is allocated with new
326static void wxFreeArgs(int argc, wxChar **argv)
327{
328 for ( int i = 0; i < argc; i++ )
329 {
330 free(argv[i]);
331 }
332
333 delete [] argv;
334}
335
6f2df739
VZ
336WXDLLEXPORT int wxEntry(HINSTANCE hInstance,
337 HINSTANCE WXUNUSED(hPrevInstance),
338 wxCmdLineArgType WXUNUSED(pCmdLine),
339 int nCmdShow)
340{
341 // the first thing to do is to check if we're trying to run an Unicode
342 // program under Win9x w/o MSLU emulation layer - if so, abort right now
343 // as it has no chance to work and has all chances to crash
344#ifdef NEED_UNICODE_CHECK
345 if ( !wxIsUnicodeAvailable() )
346 return -1;
347#endif // NEED_UNICODE_CHECK
bd866271
VZ
348
349
94826170 350 // remember the parameters Windows gave us
13bdd545 351 wxSetInstance(hInstance);
94826170
VZ
352 wxApp::m_nCmdShow = nCmdShow;
353
b2b1371c
VZ
354 // parse the command line: we can't use pCmdLine in Unicode build so it is
355 // simpler to never use it at all (this also results in a more correct
356 // argv[0])
357
358 // break the command line in words
359 wxArrayString args;
13a5a49f 360
b2b1371c
VZ
361 const wxChar *cmdLine = ::GetCommandLine();
362 if ( cmdLine )
363 {
364 args = wxCmdLineParser::ConvertStringToArgs(cmdLine);
365 }
366
13a5a49f 367#ifdef __WXWINCE__
77d8d6cd
VZ
368 // WinCE doesn't insert the program itself, so do it ourselves.
369 args.Insert(wxGetFullModuleName(), 0);
13a5a49f
JS
370#endif
371
b2b1371c
VZ
372 int argc = args.GetCount();
373
374 // +1 here for the terminating NULL
375 wxChar **argv = new wxChar *[argc + 1];
376 for ( int i = 0; i < argc; i++ )
377 {
378 argv[i] = wxStrdup(args[i]);
379 }
380
381 // argv[] must be NULL-terminated
382 argv[argc] = NULL;
94826170 383
48733d47
VZ
384 wxON_BLOCK_EXIT2(wxFreeArgs, argc, argv);
385
94826170
VZ
386 return wxEntry(argc, argv);
387}
388
532d575b 389#endif // wxUSE_GUI && __WXMSW__
94826170 390
b568d04f 391// ----------------------------------------------------------------------------
e2478fde 392// global HINSTANCE
b568d04f
VZ
393// ----------------------------------------------------------------------------
394
ec67cff1 395#if wxUSE_BASE
e2478fde
VZ
396
397HINSTANCE wxhInstance = 0;
398
028e7716 399extern "C" HINSTANCE wxGetInstance()
b568d04f
VZ
400{
401 return wxhInstance;
402}
403
404void wxSetInstance(HINSTANCE hInst)
405{
406 wxhInstance = hInst;
407}
2bda0e17 408
ec67cff1 409#endif // wxUSE_BASE