]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/app.cpp
added XRC contrib makefile
[wxWidgets.git] / src / msw / app.cpp
index 7e26d1504f424f726f03109db06b6977e5d91f01..1b2e4f96baa9477b9c66afc60201dbc190dd4414 100644 (file)
@@ -5,8 +5,8 @@
 // Modified by:
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:     wxWindows license
+// Copyright:   (c) Julian Smart
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ===========================================================================
@@ -48,6 +48,7 @@
     #include "wx/log.h"
 #endif
 
+#include "wx/apptrait.h"
 #include "wx/cmdline.h"
 #include "wx/filename.h"
 #include "wx/module.h"
     WX_DEFINE_OBJARRAY(wxMsgArray);
 #endif // wxUSE_THREADS
 
-#if wxUSE_WX_RESOURCES
-    #include "wx/resource.h"
-#endif
-
 #if wxUSE_TOOLTIPS
     #include "wx/tooltip.h"
 #endif // wxUSE_TOOLTIPS
 
 // OLE is used for drag-and-drop, clipboard, OLE Automation..., but some
 // compilers don't support it (missing headers, libs, ...)
-#if defined(__GNUWIN32_OLD__) || defined(__SC__) || defined(__SALFORDC__)
+#if defined(__GNUWIN32_OLD__) || defined(__SYMANTEC__) || defined(__SALFORDC__)
     #undef wxUSE_OLE
 
     #define  wxUSE_OLE 0
@@ -88,7 +85,7 @@
 #include <string.h>
 #include <ctype.h>
 
-#if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__) || defined(__WXMICROWIN__)) && !defined(__CYGWIN10__))
+#if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__WXMICROWIN__)) && !defined(__CYGWIN10__))
     #include <commctrl.h>
 #endif
 
@@ -134,7 +131,6 @@ extern void wxSetKeyboardHook(bool doIt);
 #endif
 
 MSG s_currentMsg;
-wxApp *wxTheApp = NULL;
 
 // NB: all "NoRedraw" classes must have the same names as the "normal" classes
 //     with NR suffix - wxWindow::MSWCreate() supposes this
@@ -172,11 +168,92 @@ LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
 #endif
 
 // ===========================================================================
-// implementation
+// wxGUIAppTraits implementation
+// ===========================================================================
+
+// private class which we use to pass parameters from BeforeChildWaitLoop() to
+// AfterChildWaitLoop()
+struct ChildWaitLoopData
+{
+    ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *winActive_)
+    {
+        wd = wd_;
+        winActive = winActive_;
+    }
+
+    wxWindowDisabler *wd;
+    wxWindow *winActive;
+};
+
+void *wxGUIAppTraits::BeforeChildWaitLoop()
+{
+    /*
+       We use a dirty hack here to disable all application windows (which we
+       must do because otherwise the calls to wxYield() could lead to some very
+       unexpected reentrancies in the users code) but to avoid losing
+       focus/activation entirely when the child process terminates which would
+       happen if we simply disabled everything using wxWindowDisabler. Indeed,
+       remember that Windows will never activate a disabled window and when the
+       last childs window is closed and Windows looks for a window to activate
+       all our windows are still disabled. There is no way to enable them in
+       time because we don't know when the childs windows are going to be
+       closed, so the solution we use here is to keep one special tiny frame
+       enabled all the time. Then when the child terminates it will get
+       activated and when we close it below -- after reenabling all the other
+       windows! -- the previously active window becomes activated again and
+       everything is ok.
+     */
+    wxBeginBusyCursor();
+
+    // first disable all existing windows
+    wxWindowDisabler *wd = new wxWindowDisabler;
+
+    // then create an "invisible" frame: it has minimal size, is positioned
+    // (hopefully) outside the screen and doesn't appear on the taskbar
+    wxWindow *winActive = new wxFrame
+                    (
+                        wxTheApp->GetTopWindow(),
+                        -1,
+                        _T(""),
+                        wxPoint(32600, 32600),
+                        wxSize(1, 1),
+                        wxDEFAULT_FRAME_STYLE | wxFRAME_NO_TASKBAR
+                    );
+    winActive->Show();
+
+    return new ChildWaitLoopData(wd, winActive);
+}
+
+void wxGUIAppTraits::AlwaysYield()
+{
+    wxYield();
+}
+
+void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig)
+{
+    wxEndBusyCursor();
+
+    const ChildWaitLoopData * const data = (ChildWaitLoopData *)dataOrig;
+
+    delete data->wd;
+
+    // finally delete the dummy frame and, as wd has been already destroyed and
+    // the other windows reenabled, the activation is going to return to the
+    // window which had had it before
+    data->winActive->Destroy();
+}
+
+bool wxGUIAppTraits::DoMessageFromThreadWait()
+{
+    return !wxTheApp || wxTheApp->DoMessage();
+}
+
+// ===========================================================================
+// wxApp implementation
 // ===========================================================================
 
 // ---------------------------------------------------------------------------
-// wxApp
+// wxWin macros
 // ---------------------------------------------------------------------------
 
 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
@@ -191,7 +268,7 @@ END_EVENT_TABLE()
 bool wxApp::Initialize()
 {
     // the first thing to do is to check if we're trying to run an Unicode
-    // program under Win9x w/o MSLU emulation layer - if so, abort right now 
+    // program under Win9x w/o MSLU emulation layer - if so, abort right now
     // as it has no chance to work
 #if wxUSE_UNICODE && !wxUSE_UNICODE_MSLU
     if ( wxGetOsVersion() != wxWINDOWS_NT )
@@ -225,10 +302,6 @@ bool wxApp::Initialize()
     wxInitializeStockLists();
     wxInitializeStockObjects();
 
-#if wxUSE_WX_RESOURCES
-    wxInitializeResourceSystem();
-#endif
-
     wxBitmap::InitStandardHandlers();
 
 #if defined(__WIN95__) && !defined(__WXMICROWIN__)
@@ -511,12 +584,6 @@ void wxApp::CleanUp()
 
     wxModule::CleanUpModules();
 
-#if wxUSE_WX_RESOURCES
-    wxCleanUpResourceSystem();
-
-    //  wxDefaultResourceTable->ClearTable();
-#endif
-
     wxDeleteStockObjects();
 
     // Destroy all GDI lists, etc.
@@ -574,13 +641,14 @@ void wxApp::CleanUp()
 #endif
 
     delete wxWinHandleHash;
+    wxWinHandleHash = NULL; // Set to null in case anything later tries to ref it.
 
-    // GL: I'm annoyed ... I don't know where to put this and I don't want to
-    // create a module for that as it's part of the core.
     delete wxPendingEvents;
+    wxPendingEvents = NULL; // Set to null because wxAppBase::wxEvtHandler is destroyed later.
 
 #if wxUSE_THREADS
     delete wxPendingEventsLocker;
+    wxPendingEventsLocker = NULL; // Set to null because wxAppBase::wxEvtHandler is destroyed later.
     // If we don't do the following, we get an apparent memory leak
 #if wxUSE_VALIDATORS
     ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
@@ -812,8 +880,6 @@ int wxEntry(WXHINSTANCE hInstance)
 
 //// Static member initialization
 
-wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
-
 wxApp::wxApp()
 {
     argc = 0;
@@ -1140,33 +1206,48 @@ bool wxApp::SendIdleEvents()
 // Send idle event to window and all subwindows
 bool wxApp::SendIdleEvents(wxWindow* win)
 {
-    bool needMore = FALSE;
-
     wxIdleEvent event;
     event.SetEventObject(win);
     win->GetEventHandler()->ProcessEvent(event);
 
-    if (event.MoreRequested())
-        needMore = TRUE;
+    bool needMore = event.MoreRequested();
 
-    wxNode* node = win->GetChildren().First();
-    while (node)
+    wxWindowList::Node *node = win->GetChildren().GetFirst();
+    while ( node )
     {
-        wxWindow* win = (wxWindow*) node->Data();
+        wxWindow *win = node->GetData();
         if (SendIdleEvents(win))
             needMore = TRUE;
 
-        node = node->Next();
+        node = node->GetNext();
     }
+
     return needMore;
 }
 
+void wxApp::WakeUpIdle()
+{
+    // Send the top window a dummy message so idle handler processing will
+    // start up again.  Doing it this way ensures that the idle handler
+    // wakes up in the right thread (see also wxWakeUpMainThread() which does
+    // the same for the main app thread only)
+    wxWindow *topWindow = wxTheApp->GetTopWindow();
+    if ( topWindow )
+    {
+        if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
+        {
+            // should never happen
+            wxLogLastError(wxT("PostMessage(WM_NULL)"));
+        }
+    }
+}
+
 void wxApp::DeletePendingObjects()
 {
-    wxNode *node = wxPendingDelete.First();
+    wxNode *node = wxPendingDelete.GetFirst();
     while (node)
     {
-        wxObject *obj = (wxObject *)node->Data();
+        wxObject *obj = node->GetData();
 
         delete obj;
 
@@ -1175,7 +1256,7 @@ void wxApp::DeletePendingObjects()
 
         // Deleting one object may have deleted other pending
         // objects, so start from beginning of list again.
-        node = wxPendingDelete.First();
+        node = wxPendingDelete.GetFirst();
     }
 }
 
@@ -1196,6 +1277,17 @@ void wxApp::OnQueryEndSession(wxCloseEvent& event)
     }
 }
 
+typedef struct _WXADllVersionInfo
+{
+        DWORD cbSize;
+        DWORD dwMajorVersion;                   // Major version
+        DWORD dwMinorVersion;                   // Minor version
+        DWORD dwBuildNumber;                    // Build number
+        DWORD dwPlatformID;                     // DLLVER_PLATFORM_*
+} WXADLLVERSIONINFO;
+
+typedef HRESULT (CALLBACK* WXADLLGETVERSIONPROC)(WXADLLVERSIONINFO *);
+
 /* static */
 int wxApp::GetComCtl32Version()
 {
@@ -1215,17 +1307,25 @@ int wxApp::GetComCtl32Version()
 
         // do we have it?
         HMODULE hModuleComCtl32 = ::GetModuleHandle(wxT("COMCTL32"));
+        BOOL bFreeComCtl32 = FALSE ;
+        if(!hModuleComCtl32)
+        {
+            hModuleComCtl32 = ::LoadLibrary(wxT("COMCTL32.DLL")) ;
+            if(hModuleComCtl32)
+            {
+                bFreeComCtl32 = TRUE ;
+            }
+        }
 
         // if so, then we can check for the version
         if ( hModuleComCtl32 )
         {
             // try to use DllGetVersion() if available in _headers_
-            #ifdef DLLVER_PLATFORM_WINDOWS // defined in shlwapi.h
-                DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)
+                WXADLLGETVERSIONPROC pfnDllGetVersion = (WXADLLGETVERSIONPROC)
                     ::GetProcAddress(hModuleComCtl32, "DllGetVersion");
                 if ( pfnDllGetVersion )
                 {
-                    DLLVERSIONINFO dvi;
+                    WXADLLVERSIONINFO dvi;
                     dvi.cbSize = sizeof(dvi);
 
                     HRESULT hr = (*pfnDllGetVersion)(&dvi);
@@ -1242,7 +1342,6 @@ int wxApp::GetComCtl32Version()
                                             dvi.dwMinorVersion;
                     }
                 }
-            #endif
                 // DllGetVersion() unavailable either during compile or
                 // run-time, try to guess the version otherwise
                 if ( !s_verComCtl32 )
@@ -1281,20 +1380,17 @@ int wxApp::GetComCtl32Version()
                     }
                 }
         }
+
+        if(bFreeComCtl32)
+        {
+            ::FreeLibrary(hModuleComCtl32) ;
+        }
     }
 
     return s_verComCtl32;
 #endif
 }
 
-void wxExit()
-{
-    wxLogError(_("Fatal error: exiting"));
-
-    wxApp::CleanUp();
-    exit(0);
-}
-
 // Yield to incoming messages
 
 bool wxApp::Yield(bool onlyIfNeeded)
@@ -1362,31 +1458,10 @@ bool wxHandleFatalExceptions(bool doit)
 #endif
 }
 
-//-----------------------------------------------------------------------------
-// wxWakeUpIdle
-//-----------------------------------------------------------------------------
-
-void wxWakeUpIdle()
-{
-    // Send the top window a dummy message so idle handler processing will
-    // start up again.  Doing it this way ensures that the idle handler
-    // wakes up in the right thread (see also wxWakeUpMainThread() which does
-    // the same for the main app thread only)
-    wxWindow *topWindow = wxTheApp->GetTopWindow();
-    if ( topWindow )
-    {
-        if ( !::PostMessage(GetHwndOf(topWindow), WM_NULL, 0, 0) )
-        {
-            // should never happen
-            wxLogLastError(wxT("PostMessage(WM_NULL)"));
-        }
-    }
-}
-
 //-----------------------------------------------------------------------------
 
 // For some reason, with MSVC++ 1.5, WinMain isn't linked in properly
 // if in a separate file. So include it here to ensure it's linked.
-#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__WINE__) && !defined(__TWIN32__) && !defined(WXMAKINGDLL))
+#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__WINE__) && !defined(WXMAKINGDLL))
 #include "main.cpp"
 #endif