]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/utilsgui.cpp
Ensure that validators work even in presence of pushed event handlers.
[wxWidgets.git] / src / msw / utilsgui.cpp
index 9b14ea38ac413831d2b49a05e37cb75594280e83..277535f0dc8d283754322da13ddc05cc0d975877 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     21.06.2003 (extracted from msw/utils.cpp)
 // RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart
-// License:     wxWindows license
+// Licence:     wxWindows licence
 ///////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
     #include "wx/utils.h"
 #endif //WX_PRECOMP
 
+#include "wx/dynlib.h"
+
 #include "wx/msw/private.h"     // includes <windows.h>
+#include "wx/msw/registry.h"
+#include <shellapi.h> // needed for SHELLEXECUTEINFO
+
 
 // ============================================================================
 // implementation
 // ============================================================================
 
-// ----------------------------------------------------------------------------
-// functions to work with .INI files
-// ----------------------------------------------------------------------------
-
-// Reading and writing resources (eg WIN.INI, .Xdefaults)
-#if wxUSE_RESOURCES
-bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file)
-{
-  if (file != wxEmptyString)
-// Don't know what the correct cast should be, but it doesn't
-// compile in BC++/16-bit without this cast.
-#if !defined(__WIN32__)
-    return (WritePrivateProfileString((const char*) section, (const char*) entry, (const char*) value, (const char*) file) != 0);
-#else
-    return (WritePrivateProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)value, (LPCTSTR)WXSTRINGCAST file) != 0);
-#endif
-  else
-    return (WriteProfileString((LPCTSTR)WXSTRINGCAST section, (LPCTSTR)WXSTRINGCAST entry, (LPCTSTR)WXSTRINGCAST value) != 0);
-}
-
-bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file)
-{
-    wxString buf;
-    buf.Printf(wxT("%.4f"), value);
-
-    return wxWriteResource(section, entry, buf, file);
-}
-
-bool wxWriteResource(const wxString& section, const wxString& entry, long value, const wxString& file)
-{
-    wxString buf;
-    buf.Printf(wxT("%ld"), value);
-
-    return wxWriteResource(section, entry, buf, file);
-}
-
-bool wxWriteResource(const wxString& section, const wxString& entry, int value, const wxString& file)
-{
-    wxString buf;
-    buf.Printf(wxT("%d"), value);
-
-    return wxWriteResource(section, entry, buf, file);
-}
-
-bool wxGetResource(const wxString& section, const wxString& entry, wxChar **value, const wxString& file)
-{
-    static const wxChar defunkt[] = wxT("$$default");
-
-    wxChar buf[1024];
-    if (file != wxEmptyString)
-    {
-        int n = GetPrivateProfileString(section, entry, defunkt,
-                                        buf, WXSIZEOF(buf), file);
-        if (n == 0 || wxStrcmp(buf, defunkt) == 0)
-            return FALSE;
-    }
-    else
-    {
-        int n = GetProfileString(section, entry, defunkt, buf, WXSIZEOF(buf));
-        if (n == 0 || wxStrcmp(buf, defunkt) == 0)
-            return FALSE;
-    }
-    if (*value) delete[] (*value);
-    *value = copystring(buf);
-    return TRUE;
-}
-
-bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file)
-{
-    wxChar *s = NULL;
-    bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
-    if (succ)
-    {
-        *value = (float)wxStrtod(s, NULL);
-        delete[] s;
-        return TRUE;
-    }
-    else return FALSE;
-}
-
-bool wxGetResource(const wxString& section, const wxString& entry, long *value, const wxString& file)
-{
-    wxChar *s = NULL;
-    bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
-    if (succ)
-    {
-        *value = wxStrtol(s, NULL, 10);
-        delete[] s;
-        return TRUE;
-    }
-    else return FALSE;
-}
-
-bool wxGetResource(const wxString& section, const wxString& entry, int *value, const wxString& file)
-{
-    wxChar *s = NULL;
-    bool succ = wxGetResource(section, entry, (wxChar **)&s, file);
-    if (succ)
-    {
-        *value = (int)wxStrtol(s, NULL, 10);
-        delete[] s;
-        return TRUE;
-    }
-    else return FALSE;
-}
-#endif // wxUSE_RESOURCES
-
 // ---------------------------------------------------------------------------
 // helper functions for showing a "busy" cursor
 // ---------------------------------------------------------------------------
@@ -157,7 +55,7 @@ extern HCURSOR wxGetCurrentBusyCursor()
 }
 
 // Set the cursor to the busy cursor for all windows
-void wxBeginBusyCursor(wxCursor *cursor)
+void wxBeginBusyCursor(const wxCursor *cursor)
 {
     if ( gs_wxBusyCursorCount++ == 0 )
     {
@@ -184,7 +82,7 @@ void wxEndBusyCursor()
     }
 }
 
-// TRUE if we're between the above two calls
+// true if we're between the above two calls
 bool wxIsBusy()
 {
   return gs_wxBusyCursorCount > 0;
@@ -194,7 +92,7 @@ bool wxIsBusy()
 // in long calculations.
 bool wxCheckForInterrupt(wxWindow *wnd)
 {
-    wxCHECK( wnd, FALSE );
+    wxCHECK( wnd, false );
 
     MSG msg;
     while ( ::PeekMessage(&msg, GetHwndOf(wnd), 0, 0, PM_REMOVE) )
@@ -203,47 +101,8 @@ bool wxCheckForInterrupt(wxWindow *wnd)
         ::DispatchMessage(&msg);
     }
 
-    return TRUE;
-}
-
-// MSW only: get user-defined resource from the .res file.
-// Returns NULL or newly-allocated memory, so use delete[] to clean up.
-
-#ifndef __WXMICROWIN__
-wxChar *wxLoadUserResource(const wxString& resourceName, const wxString& resourceType)
-{
-    HRSRC hResource = ::FindResource(wxGetInstance(), resourceName, resourceType);
-    if ( hResource == 0 )
-        return NULL;
-
-    HGLOBAL hData = ::LoadResource(wxGetInstance(), hResource);
-    if ( hData == 0 )
-        return NULL;
-
-    wxChar *theText = (wxChar *)::LockResource(hData);
-    if ( !theText )
-        return NULL;
-
-    // Not all compilers put a zero at the end of the resource (e.g. BC++ doesn't).
-    // so we need to find the length of the resource.
-    int len = ::SizeofResource(wxGetInstance(), hResource);
-    wxChar  *s = new wxChar[len+1];
-    wxStrncpy(s,theText,len);
-    s[len]=0;
-
-    // wxChar *s = copystring(theText);
-
-    // Obsolete in WIN32
-#ifndef __WIN32__
-    UnlockResource(hData);
-#endif
-
-    // No need??
-    //  GlobalFree(hData);
-
-    return s;
+    return true;
 }
-#endif // __WXMICROWIN__
 
 // ----------------------------------------------------------------------------
 // get display info
@@ -257,17 +116,17 @@ void wxGetMousePosition( int* x, int* y )
     GetCursorPos( & pt );
     if ( x ) *x = pt.x;
     if ( y ) *y = pt.y;
-};
+}
 
-// Return TRUE if we have a colour display
+// Return true if we have a colour display
 bool wxColourDisplay()
 {
 #ifdef __WXMICROWIN__
     // MICROWIN_TODO
-    return TRUE;
+    return true;
 #else
     // this function is called from wxDC ctor so it is called a *lot* of times
-    // hence we optimize it a bit but doign the check only once
+    // hence we optimize it a bit but doing the check only once
     //
     // this should be MT safe as only the GUI thread (holding the GUI mutex)
     // can call us
@@ -334,7 +193,7 @@ void wxDisplaySizeMM(int *width, int *height)
 
 void wxClientDisplayRect(int *x, int *y, int *width, int *height)
 {
-#if defined(__WIN16__) || defined(__WXMICROWIN__)
+#if defined(__WXMICROWIN__)
     *x = 0; *y = 0;
     wxDisplaySize(width, height);
 #else
@@ -361,8 +220,7 @@ wxString WXDLLEXPORT wxGetWindowText(WXHWND hWnd)
     if ( hWnd )
     {
         int len = GetWindowTextLength((HWND)hWnd) + 1;
-        ::GetWindowText((HWND)hWnd, str.GetWriteBuf(len), len);
-        str.UngetWriteBuf();
+        ::GetWindowText((HWND)hWnd, wxStringBuffer(str, len), len);
     }
 
     return str;
@@ -380,9 +238,8 @@ wxString WXDLLEXPORT wxGetWindowClass(WXHWND hWnd)
 
         for ( ;; )
         {
-            int count = ::GetClassName((HWND)hWnd, str.GetWriteBuf(len), len);
+            int count = ::GetClassName((HWND)hWnd, wxStringBuffer(str, len), len);
 
-            str.UngetWriteBuf();
             if ( count == len )
             {
                 // the class name might have been truncated, retry with larger
@@ -400,23 +257,17 @@ wxString WXDLLEXPORT wxGetWindowClass(WXHWND hWnd)
     return str;
 }
 
-WXWORD WXDLLEXPORT wxGetWindowId(WXHWND hWnd)
+int WXDLLEXPORT wxGetWindowId(WXHWND hWnd)
 {
-#ifndef __WIN32__
-    return (WXWORD)GetWindowWord((HWND)hWnd, GWW_ID);
-#else // Win32
-    return (WXWORD)GetWindowLong((HWND)hWnd, GWL_ID);
-#endif // Win16/32
+    return ::GetWindowLong((HWND)hWnd, GWL_ID);
 }
 
 // ----------------------------------------------------------------------------
 // Metafile helpers
 // ----------------------------------------------------------------------------
 
-extern void PixelToHIMETRIC(LONG *x, LONG *y)
+void PixelToHIMETRIC(LONG *x, LONG *y, HDC hdcRef)
 {
-    ScreenHDC hdcRef;
-
     int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE),
         iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE),
         iWidthPels = GetDeviceCaps(hdcRef, HORZRES),
@@ -428,10 +279,8 @@ extern void PixelToHIMETRIC(LONG *x, LONG *y)
     *y /= iHeightPels;
 }
 
-extern void HIMETRICToPixel(LONG *x, LONG *y)
+void HIMETRICToPixel(LONG *x, LONG *y, HDC hdcRef)
 {
-    ScreenHDC hdcRef;
-
     int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE),
         iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE),
         iWidthPels = GetDeviceCaps(hdcRef, HORZRES),
@@ -443,6 +292,16 @@ extern void HIMETRICToPixel(LONG *x, LONG *y)
     *y /= (iHeightMM * 100);
 }
 
+void HIMETRICToPixel(LONG *x, LONG *y)
+{
+    HIMETRICToPixel(x, y, ScreenHDC());
+}
+
+void PixelToHIMETRIC(LONG *x, LONG *y)
+{
+    PixelToHIMETRIC(x, y, ScreenHDC());
+}
+
 void wxDrawLine(HDC hdc, int x1, int y1, int x2, int y2)
 {
 #ifdef __WXWINCE__
@@ -458,3 +317,164 @@ void wxDrawLine(HDC hdc, int x1, int y1, int x2, int y2)
 }
 
 
+// ----------------------------------------------------------------------------
+// Shell API wrappers
+// ----------------------------------------------------------------------------
+
+extern bool wxEnableFileNameAutoComplete(HWND hwnd)
+{
+#if wxUSE_DYNLIB_CLASS
+    typedef HRESULT (WINAPI *SHAutoComplete_t)(HWND, DWORD);
+
+    static SHAutoComplete_t s_pfnSHAutoComplete = NULL;
+    static bool s_initialized = false;
+
+    if ( !s_initialized )
+    {
+        s_initialized = true;
+
+        wxLogNull nolog;
+        wxDynamicLibrary dll(wxT("shlwapi.dll"));
+        if ( dll.IsLoaded() )
+        {
+            s_pfnSHAutoComplete =
+                (SHAutoComplete_t)dll.GetSymbol(wxT("SHAutoComplete"));
+            if ( s_pfnSHAutoComplete )
+            {
+                // won't be unloaded until the process termination, no big deal
+                dll.Detach();
+            }
+        }
+    }
+
+    if ( !s_pfnSHAutoComplete )
+        return false;
+
+    HRESULT hr = s_pfnSHAutoComplete(hwnd, 0x10 /* SHACF_FILESYS_ONLY */);
+    if ( FAILED(hr) )
+    {
+        wxLogApiError(wxT("SHAutoComplete"), hr);
+        return false;
+    }
+
+    return true;
+#else
+    wxUnusedVar(hwnd);
+    return false;
+#endif // wxUSE_DYNLIB_CLASS/!wxUSE_DYNLIB_CLASS
+}
+
+// ----------------------------------------------------------------------------
+// Launch document with default app
+// ----------------------------------------------------------------------------
+
+bool wxLaunchDefaultApplication(const wxString& document, int flags)
+{
+    wxUnusedVar(flags);
+
+    WinStruct<SHELLEXECUTEINFO> sei;
+    sei.lpFile = document.wx_str();
+    sei.lpVerb = wxT("open");
+#ifdef __WXWINCE__
+    sei.nShow = SW_SHOWNORMAL; // SW_SHOWDEFAULT not defined under CE (#10216)
+#else
+    sei.nShow = SW_SHOWDEFAULT;
+#endif
+
+    // avoid Windows message box in case of error for consistency with
+    // wxLaunchDefaultBrowser() even if don't show the error ourselves in this
+    // function
+    sei.fMask = SEE_MASK_FLAG_NO_UI;
+
+    if ( ::ShellExecuteEx(&sei) )
+        return true;
+
+    return false;
+}
+
+// ----------------------------------------------------------------------------
+// Launch default browser
+// ----------------------------------------------------------------------------
+
+bool wxDoLaunchDefaultBrowser(const wxString& url, const wxString& scheme, int flags)
+{
+    wxUnusedVar(flags);
+
+#if wxUSE_IPC
+    if ( flags & wxBROWSER_NEW_WINDOW )
+    {
+        // ShellExecuteEx() opens the URL in an existing window by default so
+        // we can't use it if we need a new window
+        wxRegKey key(wxRegKey::HKCR, scheme + wxT("\\shell\\open"));
+        if ( !key.Exists() )
+        {
+            // try the default browser, it must be registered at least for http URLs
+            key.SetName(wxRegKey::HKCR, wxT("http\\shell\\open"));
+        }
+
+        if ( key.Exists() )
+        {
+            wxRegKey keyDDE(key, wxT("DDEExec"));
+            if ( keyDDE.Exists() )
+            {
+                // we only know the syntax of WWW_OpenURL DDE request for IE,
+                // optimistically assume that all other browsers are compatible
+                // with it
+                static const wxChar *TOPIC_OPEN_URL = wxT("WWW_OpenURL");
+                wxString ddeCmd;
+                wxRegKey keyTopic(keyDDE, wxT("topic"));
+                bool ok = keyTopic.Exists() &&
+                            keyTopic.QueryDefaultValue() == TOPIC_OPEN_URL;
+                if ( ok )
+                {
+                    ddeCmd = keyDDE.QueryDefaultValue();
+                    ok = !ddeCmd.empty();
+                }
+
+                if ( ok )
+                {
+                    // for WWW_OpenURL, the index of the window to open the URL
+                    // in is -1 (meaning "current") by default, replace it with
+                    // 0 which means "new" (see KB article 160957)
+                    ok = ddeCmd.Replace(wxT("-1"), wxT("0"),
+                                        false /* only first occurrence */) == 1;
+                }
+
+                if ( ok )
+                {
+                    // and also replace the parameters: the topic should
+                    // contain a placeholder for the URL
+                    ok = ddeCmd.Replace(wxT("%1"), url, false) == 1;
+                }
+
+                if ( ok )
+                {
+                    // try to send it the DDE request now but ignore the errors
+                    wxLogNull noLog;
+
+                    const wxString ddeServer = wxRegKey(keyDDE, wxT("application"));
+                    if ( wxExecuteDDE(ddeServer, TOPIC_OPEN_URL, ddeCmd) )
+                        return true;
+
+                    // this is not necessarily an error: maybe browser is
+                    // simply not running, but no matter, in any case we're
+                    // going to launch it using ShellExecuteEx() below now and
+                    // we shouldn't try to open a new window if we open a new
+                    // browser anyhow
+                }
+            }
+        }
+    }
+#endif // wxUSE_IPC
+
+    WinStruct<SHELLEXECUTEINFO> sei;
+    sei.lpFile = url.c_str();
+    sei.lpVerb = wxT("open");
+    sei.nShow = SW_SHOWNORMAL;
+    sei.fMask = SEE_MASK_FLAG_NO_UI; // we give error message ourselves
+
+    if ( ::ShellExecuteEx(&sei) )
+        return true;
+
+    return false;
+}