refactored code to create hidden window in one place only; use it from wxTimer; unregister class used by wxExecute (modified patch 782947)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23868 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2003-09-23 23:57:32 +00:00
parent 007bea23c3
commit eccd199223
6 changed files with 213 additions and 91 deletions

View 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:

View File

@ -35,6 +35,7 @@ protected:
void Init();
long m_id;
WXHWND m_hwnd;
private:
DECLARE_DYNAMIC_CLASS_NO_COPY(wxTimer)

View 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)

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////////
// Name: timer.cpp
// Name: msw/timer.cpp
// Purpose: wxTimer implementation
// Author: Julian Smart
// Modified by:
@ -32,11 +32,16 @@
#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;
return true;
wxWindow *win = wxDynamicCast(m_owner, wxWindow);
if ( win )
{
m_hwnd = win->GetHWND();
}
}
else
// 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;
}
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") );

View 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;
}

View File

@ -35,13 +35,13 @@
#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>
@ -58,14 +58,14 @@
#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>
@ -82,6 +82,10 @@
#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
// ----------------------------------------------------------------------------
@ -96,6 +100,7 @@
// 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