]> git.saurik.com Git - wxWidgets.git/commitdiff
refactored code to create hidden window in one place only; use it from wxTimer; unreg...
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 23 Sep 2003 23:57:32 +0000 (23:57 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 23 Sep 2003 23:57:32 +0000 (23:57 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23868 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/msw/timer.h
src/msw/gsockmsw.c
src/msw/timer.cpp
src/msw/utils.cpp
src/msw/utilsexc.cpp

index f44fd0cefb8eef57fb2bc97757e8a985648bcf20..2051e5d57ce7f2b1cc0d25caeac5ea7bcad86839 100644 (file)
@@ -63,6 +63,7 @@ wxMSW:
 - wxRadioButtons are now checked when they get focus (standard behaviour)
 - several fixes to owner drawn menu items (Christian Sturmlechner)
 - wxGauge now supports full 32 bit range (Miroslav Rajcic)
+- use proper window with wxTimer (Jaakko Salli)
 
 wxGTK:
 
index 116e02e303f3a18692fc17e2bfefc51bb0f9c472..7cca85b1fa667629c98c6e4a7e9df929789680e3 100644 (file)
@@ -35,6 +35,7 @@ protected:
     void Init();
 
     long m_id;
+    WXHWND m_hwnd;
 
 private:
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxTimer)
index 7bc845bed020ced2ace1c191aa6a0db6faf47808..96b237f1043e5e8b6bf33413c3cc50615225ee52 100644 (file)
@@ -84,7 +84,10 @@ HINSTANCE wxGetInstance(void);
 #endif
 
 #define CLASSNAME  TEXT("_GSocket_Internal_Window_Class")
-#define WINDOWNAME TEXT("_GSocket_Internal_Window_Name")
+
+/* implemented in utils.cpp */
+extern HWND
+wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
 
 /* Maximum number of different GSocket objects at a given time.
  * This value can be modified at will, but it CANNOT be greater
@@ -109,28 +112,13 @@ static int firstAvailable;
 
 int _GSocket_GUI_Init(void)
 {
-  WNDCLASS winClass;
+  LPCTSTR pclassname;
   int i;
 
   /* Create internal window for event notifications */
-  winClass.style         = 0;
-  winClass.lpfnWndProc   = _GSocket_Internal_WinProc;
-  winClass.cbClsExtra    = 0;
-  winClass.cbWndExtra    = 0;
-  winClass.hInstance     = INSTANCE;
-  winClass.hIcon         = (HICON) NULL;
-  winClass.hCursor       = (HCURSOR) NULL;
-  winClass.hbrBackground = (HBRUSH) NULL;
-  winClass.lpszMenuName  = (LPCTSTR) NULL;
-  winClass.lpszClassName = CLASSNAME;
-
-  RegisterClass(&winClass);
-  hWin = CreateWindow(CLASSNAME,
-                      WINDOWNAME,
-                      0, 0, 0, 0, 0,
-                      (HWND) NULL, (HMENU) NULL, INSTANCE, (LPVOID) NULL);
-
-  if (!hWin) return FALSE;
+  hWin = wxCreateHiddenWindow(&pclassname, CLASSNAME, _GSocket_Internal_WinProc);
+  if (!hWin)
+      return FALSE;
 
   /* Initialize socket list */
   InitializeCriticalSection(&critical);
@@ -141,7 +129,7 @@ int _GSocket_GUI_Init(void)
   }
   firstAvailable = 0;
 
-  return 1;
+  return TRUE;
 }
 
 void _GSocket_GUI_Cleanup(void)
index cccb8ed09fc7634b5468a4eb6706ca60e85ef3f5..09f830cd951728a0142a4b346399c2f787358e9c 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        timer.cpp
+// Name:        msw/timer.cpp
 // Purpose:     wxTimer implementation
 // Author:      Julian Smart
 // Modified by:
 #endif
 
 #include "wx/hashmap.h"
+#include "wx/module.h"
 
 #include "wx/timer.h"
 
 #include "wx/msw/private.h"
 
+// from utils.cpp
+extern "C" HWND
+wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
+
 // ----------------------------------------------------------------------------
 // private functions
 // ----------------------------------------------------------------------------
@@ -55,13 +60,45 @@ void WINAPI wxTimerProc(HWND hwnd, WORD, int idTimer, DWORD);
 // macros
 // ----------------------------------------------------------------------------
 
-// should probably be in wx/msw/missing.h
-#ifdef __WXMICROWIN__
-    #define MakeProcInstance(proc, hinst) proc
-#endif
-
 IMPLEMENT_ABSTRACT_CLASS(wxTimer, wxObject)
 
+// ----------------------------------------------------------------------------
+// globals
+// ----------------------------------------------------------------------------
+
+// these variables are for timer shared hwnd management
+static const wxChar *wxMSWTIMER_WNDCLASSNAME = wxT("_wxTimer_Internal_Class");
+static LPCTSTR s_classnameTimerWnd = NULL;
+static HWND s_hwndTimer = NULL;
+
+// ----------------------------------------------------------------------------
+// private classes
+// ----------------------------------------------------------------------------
+
+class wxTimerModule : public wxModule
+{
+public:
+    virtual bool OnInit() { return true; }
+    virtual void OnExit()
+    {
+        if ( s_hwndTimer )
+        {
+            ::DestroyWindow(s_hwndTimer);
+            s_hwndTimer = NULL;
+
+            if ( !::UnregisterClass(wxMSWTIMER_WNDCLASSNAME, wxGetInstance()) )
+            {
+                wxLogLastError(_T("UnregisterClass(wxTimerClass)"));
+            }
+
+            s_classnameTimerWnd = NULL;
+        }
+    }
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxTimerModule)
+};
+
 // ============================================================================
 // implementation
 // ============================================================================
@@ -73,10 +110,12 @@ IMPLEMENT_ABSTRACT_CLASS(wxTimer, wxObject)
 void wxTimer::Init()
 {
     m_id = 0;
+    m_hwnd = NULL;
 }
 
 wxTimer::~wxTimer()
 {
+    // save id as Stop() changes it
     long id = m_id;
 
     wxTimer::Stop();
@@ -86,40 +125,74 @@ wxTimer::~wxTimer()
 
 bool wxTimer::Start(int milliseconds, bool oneShot)
 {
-    (void)wxTimerBase::Start(milliseconds, oneShot);
-
     wxCHECK_MSG( m_milli > 0, false, wxT("invalid value for timer timeour") );
 
-#ifdef __WXWINCE__
-    m_id = ::SetTimer(NULL, (UINT)(m_id ? m_id : 1),
-                      (UINT)m_milli, (TIMERPROC) wxTimerProc);
-#else
-    TIMERPROC wxTimerProcInst = (TIMERPROC)
-        MakeProcInstance((FARPROC)wxTimerProc, wxGetInstance());
+    (void)wxTimerBase::Start(milliseconds, oneShot);
 
-    m_id = ::SetTimer(NULL, (UINT)(m_id ? m_id : 1),
-                      (UINT)m_milli, wxTimerProcInst);
-#endif
+    // find a window for SetTimer(): it should be a valid HWND owned by this
+    // thread (even if we had a non NULL m_hwnd before, reset it in case the
+    // owner has changed)
+    m_hwnd = NULL;
 
-    if ( m_id > 0 )
+    // first try the owner window
+    if ( m_owner )
     {
-        wxTimerList[m_id] = this;
+        wxWindow *win = wxDynamicCast(m_owner, wxWindow);
+        if ( win )
+        {
+            m_hwnd = win->GetHWND();
+        }
+    }
+
+    // if not, use a shared hidden window
+    if ( !m_hwnd )
+    {
+        if ( !s_hwndTimer )
+        {
+            s_hwndTimer = wxCreateHiddenWindow
+                          (
+                            &s_classnameTimerWnd,
+                            wxMSWTIMER_WNDCLASSNAME,
+                            ::DefWindowProc
+                          );
+
+            if ( !s_hwndTimer )
+            {
+                wxASSERT_MSG( s_hwndTimer, wxT("can't create a HWND for wxTimer") );
+                return false;
+            }
+        }
+
+        m_hwnd = (WXHWND)s_hwndTimer;
 
-        return true;
     }
-    else
+
+    m_id = ::SetTimer
+             (
+                (HWND)m_hwnd,
+                (UINT)(m_id ? m_id : 1),
+                (UINT)m_milli,
+                (TIMERPROC)wxTimerProc
+             );
+
+    if ( !m_id )
     {
         wxLogSysError(_("Couldn't create a timer"));
 
         return false;
     }
+
+    wxTimerList[m_id] = this;
+
+    return true;
 }
 
 void wxTimer::Stop()
 {
     if ( m_id )
     {
-        ::KillTimer(NULL, (UINT)m_id);
+        ::KillTimer((HWND)m_hwnd, (UINT)m_id);
+        m_hwnd = NULL;
 
         wxTimerList.erase(m_id);
     }
@@ -145,7 +218,6 @@ void wxProcessTimer(wxTimer& timer)
 
 void WINAPI wxTimerProc(HWND WXUNUSED(hwnd), WORD, int idTimer, DWORD)
 {
-    
     wxTimerMap::iterator node = wxTimerList.find((long)idTimer);
 
     wxASSERT_MSG( node != wxTimerList.end(), wxT("bogus timer id in wxTimerProc") );
index 97f1369e3c026afef954567ce680cb7866748bb9..8e5fab3265946128366d2883f4c772c9b9732d0c 100644 (file)
@@ -1052,12 +1052,12 @@ wxToolkitInfo& wxAppTraits::GetToolkitInfo()
                 case VER_PLATFORM_WIN32_CE:
                     s_ver = wxWINDOWS_CE;
                     break;
-#endif                    
+#endif
             }
         }
     }
 
-    static wxToolkitInfo info;    
+    static wxToolkitInfo info;
     info.versionMajor = s_major;
     info.versionMinor = s_minor;
     info.os = s_ver;
@@ -1232,3 +1232,62 @@ extern long wxCharsetToCodepage(const wxChar *name)
 
 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
 
+/*
+  Creates a hidden window with supplied window proc registering the class for
+  it if necesssary (i.e. the first time only). Caller is responsible for
+  destroying the window and unregistering the class (note that this must be
+  done because wxWindows may be used as a DLL and so may be loaded/unloaded
+  multiple times into/from the same process so we cna't rely on automatic
+  Windows class unregistration).
+
+  pclassname is a pointer to a caller stored classname, which must initially be
+  NULL. classname is the desired wndclass classname. If function succesfully
+  registers the class, pclassname will be set to classname.
+ */
+extern "C" HWND
+wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc)
+{
+    wxCHECK_MSG( classname && pclassname && wndproc, NULL,
+                    _T("NULL parameter in wxCreateHiddenWindow") );
+
+    // register the class fi we need to first
+    if ( *pclassname == NULL )
+    {
+        WNDCLASS wndclass;
+        wxZeroMemory(wndclass);
+
+        wndclass.lpfnWndProc   = wndproc;
+        wndclass.hInstance     = wxGetInstance();
+        wndclass.lpszClassName = classname;
+
+        if ( !::RegisterClass(&wndclass) )
+        {
+            wxLogLastError(wxT("RegisterClass() in wxCreateHiddenWindow"));
+
+            return NULL;
+        }
+
+        *pclassname = classname;
+    }
+
+    // next create the window
+    HWND hwnd = ::CreateWindow
+                  (
+                    *pclassname,
+                    NULL,
+                    0, 0, 0, 0,
+                    0,
+                    (HWND) NULL,
+                    (HMENU)NULL,
+                    wxGetInstance(),
+                    (LPVOID) NULL
+                  );
+
+    if ( !hwnd )
+    {
+        wxLogLastError(wxT("CreateWindow() in wxCreateHiddenWindow"));
+    }
+
+    return hwnd;
+}
+
index 7046329ee5a42f54e3b9692c9548d589d7d99d08..b2fbf1d0606f0f6ef07e0780fab207fbe622a2ce 100644 (file)
     #include "wx/log.h"
 #endif
 
-#ifdef __WIN32__
-    #include "wx/stream.h"
-    #include "wx/process.h"
-#endif
+#include "wx/stream.h"
+#include "wx/process.h"
 
 #include "wx/apptrait.h"
 
+#include "wx/module.h"
+
 #include "wx/msw/private.h"
 
 #include <ctype.h>
     #include <sys/stat.h>
 #endif
 
-#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
-#ifndef __UNIX__
-    #include <io.h>
-#endif
+#if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
+    #ifndef __UNIX__
+        #include <io.h>
+    #endif
 
-#ifndef __GNUWIN32__
-#include <shellapi.h>
-#endif
+    #ifndef __GNUWIN32__
+        #include <shellapi.h>
+    #endif
 #endif
 
 #include <stdio.h>
     #include "wx/dde.h"         // for WX_DDE hack in wxExecute
 #endif // wxUSE_IPC
 
+// implemented in utils.cpp
+extern "C" HWND
+wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
+
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
 // we need to create a hidden window to receive the process termination
 // notifications and for this we need a (Win) class name for it which we will
 // register the first time it's needed
+static const wxChar *wxMSWEXEC_WNDCLASSNAME = wxT("_wxExecute_Internal_Class");
 static const wxChar *gs_classForHiddenWindow = NULL;
 
 // ----------------------------------------------------------------------------
@@ -124,7 +129,28 @@ public:
     bool       state;         // set to FALSE when the process finishes
 };
 
-#if defined(__WIN32__) && wxUSE_STREAMS && !defined(__WXWINCE__)
+class wxExecuteModule : public wxModule
+{
+public:
+    virtual bool OnInit() { return true; }
+    virtual void OnExit()
+    {
+        if ( *gs_classForHiddenWindow )
+        {
+            if ( !::UnregisterClass(wxMSWEXEC_WNDCLASSNAME, wxGetInstance()) )
+            {
+                wxLogLastError(_T("UnregisterClass(wxExecClass)"));
+            }
+
+            gs_classForHiddenWindow = NULL;
+        }
+    }
+
+private:
+    DECLARE_DYNAMIC_CLASS(wxExecuteModule)
+};
+
+#if wxUSE_STREAMS && !defined(__WXWINCE__)
 
 // ----------------------------------------------------------------------------
 // wxPipeStreams
@@ -258,8 +284,6 @@ private:
 // implementation
 // ============================================================================
 
-#ifdef __WIN32__
-
 // ----------------------------------------------------------------------------
 // process termination detecting support
 // ----------------------------------------------------------------------------
@@ -438,8 +462,6 @@ size_t wxPipeOutputStream::OnSysWrite(const void *buffer, size_t len)
 
 #endif // wxUSE_STREAMS
 
-#endif // Win32
-
 // ============================================================================
 // wxExecute functions family
 // ============================================================================
@@ -738,36 +760,15 @@ long wxExecute(const wxString& cmd, int flags, wxProcess *handler)
     }
 #endif // wxUSE_STREAMS
 
-    // register the class for the hidden window used for the notifications
-    if ( !gs_classForHiddenWindow )
-    {
-        gs_classForHiddenWindow = _T("wxHiddenWindow");
-
-        WNDCLASS wndclass;
-        wxZeroMemory(wndclass);
-        wndclass.lpfnWndProc   = (WNDPROC)wxExecuteWindowCbk;
-        wndclass.hInstance     = wxGetInstance();
-        wndclass.lpszClassName = gs_classForHiddenWindow;
-
-        if ( !::RegisterClass(&wndclass) )
-        {
-            wxLogLastError(wxT("RegisterClass(hidden window)"));
-        }
-    }
-
     // create a hidden window to receive notification about process
     // termination
-#ifdef __WXWINCE__
-    HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL,
-                               WS_OVERLAPPED,
-                               0, 0, 0, 0, NULL,
-                               (HMENU)NULL, wxGetInstance(), 0);
-#else
-    HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL,
-                               WS_OVERLAPPEDWINDOW,
-                               0, 0, 0, 0, NULL,
-                               (HMENU)NULL, wxGetInstance(), 0);
-#endif
+    HWND hwnd = wxCreateHiddenWindow
+                (
+                    &gs_classForHiddenWindow,
+                    wxMSWEXEC_WNDCLASSNAME,
+                    (WNDPROC)wxExecuteWindowCbk
+                );
+
     wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
 
     // Alloc data