#include "wx/resource.h"
#endif
-// OLE is used for drag-and-drop, clipboard, OLE Automation...
-#ifndef wxUSE_NORLANDER_HEADERS
-#if defined(__GNUWIN32__) || defined(__SC__) || defined(__SALFORDC__)
+#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__)
#undef wxUSE_OLE
#define wxUSE_OLE 0
#endif // broken compilers
-#endif
#if wxUSE_OLE
#include <ole2.h>
#include <string.h>
#include <ctype.h>
-#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
+#if defined(__WIN95__) && !(defined(__GNUWIN32_OLD__) || defined(__TWIN32__))
#include <commctrl.h>
#endif
#include "wx/msw/msvcrt.h"
+// ----------------------------------------------------------------------------
+// conditional compilation
+// ----------------------------------------------------------------------------
+
+// The macro _WIN32_IE is defined by commctrl.h (unless it had already been
+// defined before) and shows us what common control features are available
+// during the compile time (it doesn't mean that they will be available during
+// the run-time, use GetComCtl32Version() to test for them!). The possible
+// values are:
+//
+// 0x0200 for comctl32.dll 4.00 shipped with Win95/NT 4.0
+// 0x0300 4.70 IE 3.x
+// 0x0400 4.71 IE 4.0
+// 0x0401 4.72 IE 4.01 and Win98
+// 0x0500 5.00 IE 5.x and NT 5.0 (Win2000)
+
+#ifndef _WIN32_IE
+ // minimal set of features by default
+ #define _WIN32_IE 0x0200
+#endif
+
+#if _WIN32_IE >= 0x0300
+ #include <shlwapi.h>
+#endif
+
// ---------------------------------------------------------------------------
// global variables
// ---------------------------------------------------------------------------
extern wxList *wxWinHandleList;
extern wxList WXDLLEXPORT wxPendingDelete;
extern void wxSetKeyboardHook(bool doIt);
-extern wxCursor *g_globalCursor;
-HINSTANCE wxhInstance = 0;
MSG s_currentMsg;
wxApp *wxTheApp = NULL;
-// FIXME why not const? and not static?
-
// NB: all "NoRedraw" classes must have the same names as the "normal" classes
// with NR suffix - wxWindow::MSWCreate() supposes this
-wxChar wxFrameClassName[] = wxT("wxFrameClass");
-wxChar wxFrameClassNameNoRedraw[] = wxT("wxFrameClassNR");
-wxChar wxMDIFrameClassName[] = wxT("wxMDIFrameClass");
-wxChar wxMDIFrameClassNameNoRedraw[] = wxT("wxMDIFrameClassNR");
-wxChar wxMDIChildFrameClassName[] = wxT("wxMDIChildFrameClass");
-wxChar wxMDIChildFrameClassNameNoRedraw[] = wxT("wxMDIChildFrameClassNR");
-wxChar wxPanelClassName[] = wxT("wxPanelClass");
-wxChar wxCanvasClassName[] = wxT("wxCanvasClass");
+const wxChar *wxFrameClassName = wxT("wxFrameClass");
+const wxChar *wxFrameClassNameNoRedraw = wxT("wxFrameClassNR");
+const wxChar *wxMDIFrameClassName = wxT("wxMDIFrameClass");
+const wxChar *wxMDIFrameClassNameNoRedraw = wxT("wxMDIFrameClassNR");
+const wxChar *wxMDIChildFrameClassName = wxT("wxMDIChildFrameClass");
+const wxChar *wxMDIChildFrameClassNameNoRedraw = wxT("wxMDIChildFrameClassNR");
+const wxChar *wxPanelClassName = wxT("wxPanelClass");
+const wxChar *wxPanelClassNameNR = wxT("wxPanelClassNR");
+const wxChar *wxCanvasClassName = wxT("wxCanvasClass");
+const wxChar *wxCanvasClassNameNR = wxT("wxCanvasClassNR");
HICON wxSTD_FRAME_ICON = (HICON) NULL;
HICON wxSTD_MDICHILDFRAME_ICON = (HICON) NULL;
HBRUSH wxDisableButtonBrush = (HBRUSH) 0;
-LRESULT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
-
-#if defined(__WIN95__) && !defined(__TWIN32__)
- #define wxUSE_RICHEDIT 1
-#else
- #define wxUSE_RICHEDIT 0
-#endif
-
-#if wxUSE_RICHEDIT
- static HINSTANCE gs_hRichEdit = (HINSTANCE) NULL;
-#endif
+LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM);
// ===========================================================================
// implementation
// wxApp
// ---------------------------------------------------------------------------
-#if !USE_SHARED_LIBRARY
IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
EVT_END_SESSION(wxApp::OnEndSession)
EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
END_EVENT_TABLE()
-#endif
//// Initialize
bool wxApp::Initialize()
#if defined(__WIN95__)
InitCommonControls();
-#if wxUSE_RICHEDIT
- gs_hRichEdit = LoadLibrary(wxT("RICHED32.DLL"));
-
- if (gs_hRichEdit == (HINSTANCE) NULL)
- {
- wxLogError(_("Could not initialise Rich Edit DLL"));
- }
-#endif // wxUSE_RICHEDIT
-
#endif // __WIN95__
#if wxUSE_OLE
Ctl3dAutoSubclass(wxhInstance);
#endif
- g_globalCursor = new wxCursor;
-
+ // VZ: these icons are not in wx.rc anyhow (but should they?)!
+#if 0
wxSTD_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_FRAME"));
wxSTD_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_MDIPARENTFRAME"));
wxSTD_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, wxT("wxSTD_MDICHILDFRAME"));
wxDEFAULT_FRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_FRAME"));
wxDEFAULT_MDIPARENTFRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_MDIPARENTFRAME"));
wxDEFAULT_MDICHILDFRAME_ICON = LoadIcon(wxhInstance, wxT("wxDEFAULT_MDICHILDFRAME"));
+#endif // 0
RegisterWindowClasses();
return FALSE;
}
+ // Register the no redraw panel window class.
+ wndclass.lpszClassName = wxPanelClassNameNR;
+ wndclass.style = styleNoRedraw;
+
+ if ( !RegisterClass(&wndclass) )
+ {
+ wxLogLastError("RegisterClass(no redraw panel)");
+
+ return FALSE;
+ }
+
// Register the canvas and textsubwindow class name
wndclass.hbrBackground = (HBRUSH)NULL;
wndclass.lpszClassName = wxCanvasClassName;
return FALSE;
}
+ wndclass.lpszClassName = wxCanvasClassNameNR;
+ wndclass.style = styleNoRedraw;
+ if ( !RegisterClass(&wndclass) )
+ {
+ wxLogLastError("RegisterClass(no redraw canvas)");
+
+ return FALSE;
+ }
+
return TRUE;
}
// wxDefaultResourceTable->ClearTable();
#endif
- // Indicate that the cursor can be freed, so that cursor won't be deleted
- // by deleting the bitmap list before g_globalCursor goes out of scope
- // (double deletion of the cursor).
- wxSetCursor(wxNullCursor);
- delete g_globalCursor;
- g_globalCursor = NULL;
-
wxDeleteStockObjects();
// Destroy all GDI lists, etc.
wxSetKeyboardHook(FALSE);
-#ifdef __WIN95__
-
-#if wxUSE_RICHEDIT
- if (gs_hRichEdit != (HINSTANCE) NULL)
- FreeLibrary(gs_hRichEdit);
-#endif
-
-#endif
-
#if wxUSE_PENWINDOWS
wxCleanUpPenWin();
#endif
if (wxWinHandleList)
delete wxWinHandleList;
- // GL: I'm annoyed ... I don't know where to put this and I don't want to
+ // 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;
#if wxUSE_THREADS
// wxDebugContext, too.
if (wxDebugContext::CountObjectsLeft(TRUE) > 0)
{
- wxLogDebug(wxT("There were memory leaks."));
+ wxLogMessage(wxT("There were memory leaks."));
wxDebugContext::Dump();
wxDebugContext::PrintStatistics();
}
#endif // wxUSE_LOG
}
+//----------------------------------------------------------------------
+// Entry point helpers, used by wxPython
+//----------------------------------------------------------------------
+
+int WXDLLEXPORT wxEntryStart( int WXUNUSED(argc), char** WXUNUSED(argv) )
+{
+ return wxApp::Initialize();
+}
+
+int WXDLLEXPORT wxEntryInitGui()
+{
+ wxTheApp->OnInitGui();
+ return 0;
+}
+
+void WXDLLEXPORT wxEntryCleanup()
+{
+ wxApp::CleanUp();
+}
+
+
#if !defined(_WINDLL) || (defined(_WINDLL) && defined(WXMAKINGDLL))
// temporarily disable this warning which would be generated in release builds
#pragma warning(disable: 4715) // not all control paths return a value
#endif // Visual C++
-//// Main wxWindows entry point
+//----------------------------------------------------------------------
+// Main wxWindows entry point
+//----------------------------------------------------------------------
int wxEntry(WXHINSTANCE hInstance,
WXHINSTANCE WXUNUSED(hPrevInstance),
char *lpCmdLine,
// (another useful flag is _CRTDBG_DELAY_FREE_MEM_DF which doesn't free
// deallocated memory which may be used to simulate low-memory condition)
wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
-
+#ifdef __MWERKS__
+#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
+ // This seems to be necessary since there are 'rogue'
+ // objects present at this point (perhaps global objects?)
+ // Setting a checkpoint will ignore them as far as the
+ // memory checking facility is concerned.
+ // Of course you may argue that memory allocated in globals should be
+ // checked, but this is a reasonable compromise.
+ wxDebugContext::SetCheckpoint();
+#endif
+#endif
// take everything into a try-except block in release build
// FIXME other compilers must support Win32 SEH (structured exception
// handling) too, just find the appropriate keyword in their docs!
#else
#undef CATCH_PROGRAM_EXCEPTIONS
#endif
-
wxhInstance = (HINSTANCE) hInstance;
- if (!wxApp::Initialize())
+ if (!wxEntryStart(0,0))
return 0;
// create the application object or ensure that one already exists
// GUI-specific initialisation. In fact on Windows we don't have any,
// but this call is provided for compatibility across platforms.
- wxTheApp->OnInitGui();
+ wxEntryInitGui();
+
+ // We really don't want timestamps by default, because it means
+ // we can't simply double-click on the error message and get to that
+ // line in the source. So VC++ at least, let's have a sensible default.
+#ifdef __VISUALC__
+ wxLog::SetTimestamp(NULL);
+#endif
int retValue = 0;
wxTheApp->OnExit();
- wxApp::CleanUp();
+ wxEntryCleanup();
return retValue;
#else /* _WINDLL */
-//// Entry point for DLLs
+//----------------------------------------------------------------------
+// Entry point for wxWindows + the App in a DLL
+//----------------------------------------------------------------------
int wxEntry(WXHINSTANCE hInstance)
{
wxhInstance = (HINSTANCE) hInstance;
- wxApp::Initialize();
+ wxEntryStart(0, 0);
// The app may have declared a global application object, but we recommend
// the IMPLEMENT_APP macro is used instead, which sets an initializer function
wxTheApp->argc = 0;
wxTheApp->argv = NULL;
- wxTheApp->OnInitGui();
+ wxEntryInitGui();
wxTheApp->OnInit();
wxMutexGuiLeaveOrEnter();
#endif // wxUSE_THREADS
- while ( !::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) &&
- ProcessIdle() )
- {
- }
-
+ while ( !Pending() && ProcessIdle() )
+ ;
+ // a message came or no more idle processing to do
DoMessage();
}
void wxApp::ExitMainLoop()
{
+ // VZ: why not ::PostQuitMessage()?
m_keepGoing = FALSE;
}
bool wxApp::Pending()
{
- return (::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) != 0);
+ return ::PeekMessage(&s_currentMsg, 0, 0, 0, PM_NOREMOVE) != 0;
}
void wxApp::Dispatch()
{
MSG *msg = (MSG *)wxmsg;
HWND hWnd = msg->hwnd;
- wxWindow *wndThis = wxFindWinFromHandle((WXHWND)hWnd), *wnd;
+ wxWindow *wndThis = wxGetWindowFromHWND((WXHWND)hWnd);
- // for some composite controls (like a combobox), wndThis might be NULL
- // because the subcontrol is not a wxWindow, but only the control itself
- // is - try to catch this case
- while ( hWnd && !wndThis )
+#if wxUSE_TOOLTIPS
+ // we must relay WM_MOUSEMOVE events to the tooltip ctrl if we want it to
+ // popup the tooltip bubbles
+ if ( wndThis && (msg->message == WM_MOUSEMOVE) )
{
- hWnd = ::GetParent(hWnd);
- wndThis = wxFindWinFromHandle((WXHWND)hWnd);
+ wxToolTip *tt = wndThis->GetToolTip();
+ if ( tt )
+ {
+ tt->RelayEvent(wxmsg);
+ }
}
+#endif // wxUSE_TOOLTIPS
// Try translations first; find the youngest window with
// a translation table.
+ wxWindow *wnd;
for ( wnd = wndThis; wnd; wnd = wnd->GetParent() )
{
if ( wnd->MSWTranslateMessage(wxmsg) )
s_inOnIdle = TRUE;
+ // If there are pending events, we must process them: pending events
+ // are either events to the threads other than main or events posted
+ // with wxPostEvent() functions
+ // GRG: I have moved this here so that all pending events are processed
+ // before starting to delete any objects. This behaves better (in
+ // particular, wrt wxPostEvent) and is coherent with wxGTK's current
+ // behaviour. Changed Feb/2000 before 2.1.14
+ ProcessPendingEvents();
+
// 'Garbage' collection of windows deleted with Close().
DeletePendingObjects();
#if wxUSE_LOG
// flush the logged messages if any
- wxLog *pLog = wxLog::GetActiveTarget();
- if ( pLog != NULL && pLog->HasPendingMessages() )
- pLog->Flush();
+ wxLog::FlushActive();
#endif // wxUSE_LOG
// Send OnIdle events to all windows
event.RequestMore(TRUE);
}
- // If they are pending events, we must process them: pending events are
- // either events to the threads other than main or events posted with
- // wxPostEvent() functions
- ProcessPendingEvents();
-
s_inOnIdle = FALSE;
}
}
}
-int wxApp::GetComCtl32Version() const
+/* static */
+int wxApp::GetComCtl32Version()
{
- // have we loaded COMCTL32 yet?
- HMODULE theModule = ::GetModuleHandle(wxT("COMCTL32"));
- int version = 0;
+ // cache the result
+ static int s_verComCtl32 = -1;
+
+ wxCRIT_SECT_DECLARE(csComCtl32);
+ wxCRIT_SECT_LOCKER(lock, csComCtl32);
- // if so, then we can check for the version
- if (theModule)
+ if ( s_verComCtl32 == -1 )
{
- // InitCommonControlsEx is unique to 4.7 and later
- FARPROC theProc = ::GetProcAddress(theModule, "InitCommonControlsEx");
+ // initally assume no comctl32.dll at all
+ s_verComCtl32 = 0;
- if (! theProc)
- { // not found, must be 4.00
- version = 400;
- }
- else
+ // do we have it?
+ HMODULE hModuleComCtl32 = ::GetModuleHandle(wxT("COMCTL32"));
+
+ // if so, then we can check for the version
+ if ( hModuleComCtl32 )
{
- // The following symbol are unique to 4.71
- // DllInstall
- // FlatSB_EnableScrollBar FlatSB_GetScrollInfo FlatSB_GetScrollPos
- // FlatSB_GetScrollProp FlatSB_GetScrollRange FlatSB_SetScrollInfo
- // FlatSB_SetScrollPos FlatSB_SetScrollProp FlatSB_SetScrollRange
- // FlatSB_ShowScrollBar
- // _DrawIndirectImageList _DuplicateImageList
- // InitializeFlatSB
- // UninitializeFlatSB
- // we could check for any of these - I chose DllInstall
- FARPROC theProc = ::GetProcAddress(theModule, "DllInstall");
- if (! theProc)
- {
- // not found, must be 4.70
- version = 470;
- }
- else
- { // found, must be 4.71
- version = 471;
- }
+ // try to use DllGetVersion() if available in _headers_
+ #ifdef DLLVER_PLATFORM_WINDOWS // defined in shlwapi.h
+ DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)
+ ::GetProcAddress(hModuleComCtl32, _T("DllGetVersion"));
+ if ( pfnDllGetVersion )
+ {
+ DLLVERSIONINFO dvi;
+ dvi.cbSize = sizeof(dvi);
+
+ HRESULT hr = (*pfnDllGetVersion)(&dvi);
+ if ( FAILED(hr) )
+ {
+ wxLogApiError(_T("DllGetVersion"), hr);
+ }
+ else
+ {
+ // this is incompatible with _WIN32_IE values, but
+ // compatible with the other values returned by
+ // GetComCtl32Version()
+ s_verComCtl32 = 100*dvi.dwMajorVersion +
+ dvi.dwMinorVersion;
+ }
+ }
+ #endif
+ // DllGetVersion() unavailable either during compile or
+ // run-time, try to guess the version otherwise
+ if ( !s_verComCtl32 )
+ {
+ // InitCommonControlsEx is unique to 4.70 and later
+ FARPROC theProc = ::GetProcAddress
+ (
+ hModuleComCtl32,
+#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x520)
+ "InitCommonControlsEx"
+#else
+ _T("InitCommonControlsEx")
+#endif
+ );
+
+ if ( !theProc )
+ {
+ // not found, must be 4.00
+ s_verComCtl32 = 400;
+ }
+ else
+ {
+ // many symbols appeared in comctl32 4.71, could use
+ // any of them except may be DllInstall
+ theProc = ::GetProcAddress
+ (
+ hModuleComCtl32,
+#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x520)
+ "InitializeFlatSB"
+#else
+ _T("InitializeFlatSB")
+#endif
+ );
+ if ( !theProc )
+ {
+ // not found, must be 4.70
+ s_verComCtl32 = 470;
+ }
+ else
+ {
+ // found, must be 4.71
+ s_verComCtl32 = 471;
+ }
+ }
+ }
}
}
- return version;
+
+ return s_verComCtl32;
}
void wxExit()
wxLogError(_("Fatal error: exiting"));
wxApp::CleanUp();
+ exit(0);
}
// Yield to incoming messages
bool wxYield()
{
+ // disable log flushing from here because a call to wxYield() shouldn't
+ // normally result in message boxes popping up &c
+ wxLog::Suspend();
+
// we don't want to process WM_QUIT from here - it should be processed in
// the main event loop in order to stop it
-
MSG msg;
while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
msg.message != WM_QUIT )
{
+#if wxUSE_THREADS
+ wxMutexGuiLeaveOrEnter();
+#endif // wxUSE_THREADS
+
if ( !wxTheApp->DoMessage() )
break;
}
// If they are pending events, we must process them.
- wxTheApp->ProcessPendingEvents();
+ if (wxTheApp)
+ wxTheApp->ProcessPendingEvents();
+
+ // let the logs be flashed again
+ wxLog::Resume();
return TRUE;
}
+//-----------------------------------------------------------------------------
+// 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("PostMessage(WM_NULL)");
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+
wxIcon
wxApp::GetStdIcon(int which) const
{
}
}
-
-HINSTANCE wxGetInstance()
-{
- return wxhInstance;
-}
-
-void wxSetInstance(HINSTANCE hInst)
-{
- wxhInstance = hInst;
-}
-
// 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(__TWIN32__))
+#if (defined(__VISUALC__) && !defined(__WIN32__)) || (defined(__GNUWIN32__) && !defined(__TWIN32__) && !defined(WXMAKINGDLL))
#include "main.cpp"
#endif