]> git.saurik.com Git - wxWidgets.git/commitdiff
1. '\n's in tooltip messages are handled (replaced by spaces anyhow, tooltip
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 23 Jan 2000 23:23:46 +0000 (23:23 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 23 Jan 2000 23:23:46 +0000 (23:23 +0000)
    made multiline if comctl32 supports it)
2. added wxTAB_TRAVERSAL to default wxScrolledWindow style
3. improved arrows handling in radiobox (still problems for multirow ones)
4. [Alt]-<mnemonic> works in nested panels as well now because we use
   WS_EX_CONTROLPARENT for all windows with wxTAB_TRAVERSAL style
5. tooltips for radioboxes work again, even if I'm not really satisfied with
   solution :-( but I spent 2 hours trying to make TTM_WINDOWFROMPOINT handler
   work and I don't have more time to waste on this.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5620 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

13 files changed:
docs/changes.txt
include/wx/generic/scrolwin.h
include/wx/msw/private.h
include/wx/msw/radiobox.h
include/wx/msw/spinbutt.h
include/wx/msw/spinctrl.h
include/wx/msw/tooltip.h
src/generic/panelg.cpp
src/msw/app.cpp
src/msw/radiobox.cpp
src/msw/textctrl.cpp
src/msw/tooltip.cpp
src/msw/window.cpp

index f5d72a1ffa03540fef3cfcdda762b63e6dba263c..c955171a8a0351f375df1e7cf386d49612b404e9 100644 (file)
@@ -56,6 +56,8 @@ wxMSW:
 - wxTreeCtrl::IsVisible() bug fixed (thanks to Gary Chessun)
 - loading/saving big (> 32K) files in wxTextCtrl works
 - tooltips work with wxRadioBox
+- wxBitmap/wxIcon may be constructed from XPM included into a program, as in
+  Unix ports
 - returning FALSE from OnPrintPage() aborts printing
 
 wxGTK:
index ce7a477fec0bc6cd1abaa2c393076c57d56ee075..7a6302a8bf2aedd68778ae71568ba4a0dad30d39 100644 (file)
@@ -1,52 +1,65 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        scrolwin.h
+// Name:        wx/generic/scrolwin.h
 // Purpose:     wxScrolledWindow class
 // Author:      Julian Smart
 // Modified by:
 // Created:     01/02/97
 // RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart and Markus Holzem
-// Licence:    wxWindows license
+// Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
-#ifndef __SCROLWINH_G__
-#define __SCROLWINH_G__
+#ifndef _WX_GENERIC_SCROLLWIN_H_
+#define _WX_GENERIC_SCROLLWIN_H_
 
 #ifdef __GNUG__
-#pragma interface "scrolwin.h"
+    #pragma interface "scrolwin.h"
 #endif
 
+// ----------------------------------------------------------------------------
+// headers and constants
+// ----------------------------------------------------------------------------
+
 #include "wx/window.h"
 #include "wx/panel.h"
 
 WXDLLEXPORT_DATA(extern const wxChar*) wxPanelNameStr;
 
+// default scrolled window style
+#define wxScrolledWindowStyle (wxHSCROLL | wxVSCROLL | wxTAB_TRAVERSAL)
+
+// ----------------------------------------------------------------------------
+// wxScrolledWindow
+// ----------------------------------------------------------------------------
+
 class WXDLLEXPORT wxScrolledWindow : public wxPanel
 {
 public:
     wxScrolledWindow();
-    inline wxScrolledWindow(wxWindow *parent, wxWindowID id = -1,
-           const wxPoint& pos = wxDefaultPosition,
-           const wxSize& size = wxDefaultSize,
-           long style = wxHSCROLL|wxVSCROLL,
-           const wxString& name = wxPanelNameStr)
+    wxScrolledWindow(wxWindow *parent,
+                     wxWindowID id = -1,
+                     const wxPoint& pos = wxDefaultPosition,
+                     const wxSize& size = wxDefaultSize,
+                     long style = wxScrolledWindowStyle,
+                     const wxString& name = wxPanelNameStr)
     {
-      Create(parent, id, pos, size, style, name);
+        Create(parent, id, pos, size, style, name);
     }
 
     ~wxScrolledWindow();
 
-    bool Create(wxWindow *parent, wxWindowID id,
-           const wxPoint& pos = wxDefaultPosition,
-           const wxSize& size = wxDefaultSize,
-           long style = wxHSCROLL|wxVSCROLL,
-           const wxString& name = wxPanelNameStr);
+    bool Create(wxWindow *parent,
+                wxWindowID id,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxScrolledWindowStyle,
+                const wxString& name = wxPanelNameStr);
 
-    // Normally the wxScrolledWindow will scroll itself, but in 
-    // some rare occasions you might want it to scroll another 
-    // window (e.g. a child of it in order to scroll only a portion 
+    // Normally the wxScrolledWindow will scroll itself, but in
+    // some rare occasions you might want it to scroll another
+    // window (e.g. a child of it in order to scroll only a portion
     // the area between the scrollbars (spreadsheet: only cell area
-    // will move). 
+    // will move).
     virtual void SetTargetWindow( wxWindow *target );
     virtual wxWindow *GetTargetWindow();
 
@@ -56,21 +69,21 @@ public:
     virtual void SetScrollbars(int pixelsPerUnitX, int pixelsPerUnitY,
                              int noUnitsX, int noUnitsY,
                              int xPos = 0, int yPos = 0,
-                            bool noRefresh = FALSE );
+                             bool noRefresh = FALSE );
 
     // Physically scroll the window
     virtual void Scroll(int x_pos, int y_pos);
 
 #if WXWIN_COMPATIBILITY
     virtual void GetScrollUnitsPerPage(int *x_page, int *y_page) const;
-    virtual void CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const ;
+    virtual void CalcUnscrolledPosition(int x, int y, float *xx, float *yy) const;
 #endif
 
-    int GetScrollPageSize(int orient) const ;
+    int GetScrollPageSize(int orient) const;
     void SetScrollPageSize(int orient, int pageSize);
 
     virtual void GetScrollPixelsPerUnit(int *x_unit, int *y_unit) const;
-    
+
     // Enable/disable Windows scrolling in either direction.
     // If TRUE, wxWindows scrolls the canvas and only a bit of
     // the canvas is invalidated; no Clear() is necessary.
@@ -93,8 +106,8 @@ public:
     double GetScaleX() const { return m_scaleX; }
     double GetScaleY() const { return m_scaleY; }
 
-    virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const ;
-    virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const ;
+    virtual void CalcScrolledPosition(int x, int y, int *xx, int *yy) const;
+    virtual void CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const;
 
     // Adjust the scrollbars
     virtual void AdjustScrollbars(void);
@@ -135,4 +148,4 @@ private:
 };
 
 #endif
-    // __SCROLWINH_G__
+    // _WX_GENERIC_SCROLLWIN_H_
index 1f143400409de315294545fad8713ea4310e81e3..51e044b0226d204dee039612459b7071893d913c 100644 (file)
@@ -235,6 +235,15 @@ extern void PixelToHIMETRIC(LONG *x, LONG *y);
 // to invert the mask each time we pass one/get one to/from Windows
 extern HBITMAP wxInvertMask(HBITMAP hbmpMask, int w = 0, int h = 0);
 
+// get (x, y) from DWORD - notice that HI/LOWORD can *not* be used because they
+// will fail on system with multiple monitors where the coords may be negative
+//
+// these macros are standard now (Win98) but some older headers don't have them
+#ifndef GET_X_LPARAM
+    #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+    #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+#endif // GET_X_LPARAM
+
 // ---------------------------------------------------------------------------
 // small helper classes
 // ---------------------------------------------------------------------------
@@ -337,6 +346,12 @@ inline bool wxStyleHasBorder(long style)
                    wxSUNKEN_BORDER | wxDOUBLE_BORDER)) != 0;
 }
 
+// find the window for HWND which is part of some wxWindow, returns just the
+// corresponding wxWindow for HWND which just is one
+//
+// may return NULL
+extern wxWindow *wxGetWindowFromHWND(WXHWND hwnd);
+
 #endif // wxUSE_GUI
 
 #endif
index d574266121be8dd32d499cb4f2648e65321a1a1a..3736dc4dcf1ad7b35e0d33b9944484b6ecf76914 100644 (file)
@@ -89,6 +89,7 @@ public:
     int GetNumVer() const;
     int GetNumHor() const;
 
+    // compatibility ctor
 #if WXWIN_COMPATIBILITY
     wxRadioBox(wxWindow *parent, wxFunction func, const char *title,
             int x = -1, int y = -1, int width = -1, int height = -1,
index 2828753d570a92c53f410c7c96ec2b8b066d0e32..e7c54bdb3f763696e6909dda3eefc1e965761591 100644 (file)
@@ -58,6 +58,9 @@ public:
     virtual bool MSWOnScroll(int orientation, WXWORD wParam,
                              WXWORD pos, WXHWND control);
 
+    // a wxSpinButton can't do anything useful with focus, only wxSpinCtrl can
+    virtual bool AcceptsFocus() const { return FALSE; }
+
 protected:
    virtual wxSize DoGetBestSize() const;
 
index 746cf4d70749e9ec694a679fa5a8c506bc22d2df..9a160ff7aae9021a008487d61e2e5e21e832393b 100644 (file)
@@ -65,6 +65,8 @@ public:
     virtual bool Enable(bool enable = TRUE);
     virtual bool Show(bool show = TRUE);
 
+    virtual bool AcceptsFocus() const { return TRUE; }
+
 protected:
     virtual void DoMoveWindow(int x, int y, int width, int height);
     virtual wxSize DoGetBestSize() const;
index 7c637340c27392e0bb41dd8299fbf94c49373cff..d79dbfd01dda0dbd0b995d30cca54e6ee8a9b1d7 100644 (file)
@@ -31,14 +31,19 @@ public:
         // set the delay after which the tooltip appears
     static void SetDelay(long milliseconds);
 
-    // implementation
+    // implementation only from now on
+    // -------------------------------
+
+    // should be called in responde to WM_MOUSEMOVE
     void RelayEvent(WXMSG *msg);
 
 private:
+    // the one and only one tooltip control we use - never access it directly
+    // but use GetToolTipCtrl() which will create it when needed
     static WXHWND ms_hwndTT;
 
     // create the tooltip ctrl if it doesn't exist yet and return its HWND
-    WXHWND GetToolTipCtrl();
+    static WXHWND GetToolTipCtrl();
 
     // remove this tooltip from the tooltip control
     void Remove();
index 4c58bd15a1ddde5eec181b19ce7806c295aa92a0..140ff789ad9cb38b1fe6132fda63926d5b396efd 100644 (file)
@@ -121,11 +121,11 @@ void wxPanel::OnSize(wxSizeEvent& WXUNUSED(event))
 
 void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event )
 {
-    // the event is propagated downwards if the event emitter was our parent
-    bool goingDown = event.GetEventObject() == GetParent();
+    const wxWindowList& children = GetChildren();
 
-    // we're not interested in "notebook page change" events here
-    if ( event.IsWindowChange() )
+    // there is not much to do if we don't have children and we're not
+    // interested in "notebook page change" events here
+    if ( !children.GetCount() || event.IsWindowChange() )
     {
         wxWindow *parent = GetParent();
         if ( !parent || !parent->GetEventHandler()->ProcessEvent(event) )
@@ -143,7 +143,8 @@ void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event )
     // next acceptable child
     wxWindowList::Node *node, *start_node;
 
-    const wxWindowList& children = GetChildren();
+    // the event is propagated downwards if the event emitter was our parent
+    bool goingDown = event.GetEventObject() == GetParent();
 
     // we should start from the first/last control and not from the one which
     // had focus the last time if we're propagating the event downwards because
index eb56bcfa0507cb1dd7cfd84f671e68fc42bc40b2..1be88f6a6eb0f08a7a33f50c0e58a02d78d00cf2 100644 (file)
     #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...
 #ifndef wxUSE_NORLANDER_HEADERS
 #if defined(__GNUWIN32__) || defined(__SC__) || defined(__SALFORDC__)
@@ -959,19 +963,24 @@ bool wxApp::ProcessMessage(WXMSG *wxmsg)
 {
     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) )
index a7e5101893eaa2c9ed5752282edc14e1b6706c44..5b908961894fe00c90e202e0ce7ed353c80a1767 100644 (file)
 #include "wx/msw/private.h"
 
 #if wxUSE_TOOLTIPS
-
-#ifndef __GNUWIN32__
-    #include <commctrl.h>
-#endif
+    #ifndef __GNUWIN32__
+        #include <commctrl.h>
+    #endif
 
     #include "wx/tooltip.h"
 #endif // wxUSE_TOOLTIPS
 
 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
 
-// VZ: the new behaviour is to create the radio buttons as children of the
-//     radiobox instead of creating them as children of the radiobox' parent.
+// there are two possible ways to create the radio buttons: either as children
+// of the radiobox or as siblings of it - allow playing with both variants for
+// now, eventually we will choose the best one for our purposes
 //
-//     This seems more logical, more consistent with what other frameworks do
-//     and allows tooltips to work with radioboxes, so there should be no
-//     reason to revert to the backward compatible behaviour - but I still
-//     leave this possibility just in case.
-
+// two main problems are the keyboard navigation inside the radiobox (arrows
+// should switch between buttons, not pass focus to the next control) and the
+// tooltips - a tooltip is associated with the radiobox itself, not the
+// children...
+//
+// the problems with setting this to 1:
+// a) Alt-<mnemonic of radiobox> isn't handled properly by IsDialogMessage()
+//    because it sets focus to the next control accepting it which is not a
+//    radio button but a radiobox sibling in this case - the only solution to
+//    this would be to handle Alt-<mnemonic> ourselves
+// b) the problems with setting radiobox colours under Win98/2K were reported
+//    but I couldn't reproduce it so I have no idea about what causes it
+//
+// the problems with setting this to 0:
+// a) the tooltips are not shown for the radiobox - possible solution: make
+//    TTM_WINDOWFROMPOS handling code in msw/tooltip.cpp work (easier said than
+//    done because I don't know why it doesn't work)
 #define RADIOBTN_PARENT_IS_RADIOBOX 0
 
 // ---------------------------------------------------------------------------
@@ -74,7 +86,7 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hWnd,
 // ---------------------------------------------------------------------------
 
 // the pointer to standard radio button wnd proc
-static WXFARPROC s_wndprocRadioBtn = (WXFARPROC)NULL;
+static WNDPROC s_wndprocRadioBtn = (WNDPROC)NULL;
 
 #endif // __WIN32__
 
@@ -668,15 +680,17 @@ void wxRadioBox::Command(wxCommandEvent & event)
     ProcessCommand (event);
 }
 
+// NB: if this code is changed, wxGetWindowForHWND() which relies on having the
+//     radiobox pointer in GWL_USERDATA for radio buttons must be updated too!
 void wxRadioBox::SubclassRadioButton(WXHWND hWndBtn)
 {
+    // No GWL_USERDATA in Win16, so omit this subclassing.
 #ifdef __WIN32__
     HWND hwndBtn = (HWND)hWndBtn;
 
     if ( !s_wndprocRadioBtn )
-        s_wndprocRadioBtn = (WXFARPROC)::GetWindowLong(hwndBtn, GWL_WNDPROC);
+        s_wndprocRadioBtn = (WNDPROC)::GetWindowLong(hwndBtn, GWL_WNDPROC);
 
-    // No GWL_USERDATA in Win16, so omit this subclassing.
     ::SetWindowLong(hwndBtn, GWL_WNDPROC, (long)wxRadioBtnWndProc);
     ::SetWindowLong(hwndBtn, GWL_USERDATA, (long)this);
 #endif // __WIN32__
@@ -706,14 +720,21 @@ bool wxRadioBox::SetFont(const wxFont& font)
         ::SendMessage((HWND)m_radioButtons[n], WM_SETFONT, (WPARAM)hfont, 0L);
     }
 
+    // this is needed because otherwise the buttons are not redrawn correctly
+    Refresh();
+
     return TRUE;
 }
 
+// ----------------------------------------------------------------------------
+// our window proc
+// ----------------------------------------------------------------------------
+
 long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
     switch ( nMsg )
     {
-#ifndef __WIN16__
+#ifdef __WIN32__
         case WM_CTLCOLORSTATIC:
             // set the colour of the radio buttons to be the same as ours
             {
@@ -727,7 +748,7 @@ long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 
                 return (WXHBRUSH)brush->GetResourceHandle();
             }
-#endif
+#endif // Win32
 
         // This is required for the radiobox to be sensitive to mouse input,
         // e.g. for Dialog Editor.
@@ -743,11 +764,10 @@ long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
                 if (yPos < 10)
                     return (long)HTCLIENT;
             }
-            // fall through
-
-        default:
-            return wxControl::MSWWindowProc(nMsg, wParam, lParam);
+            break;
     }
+
+    return wxControl::MSWWindowProc(nMsg, wParam, lParam);
 }
 
 // ---------------------------------------------------------------------------
@@ -757,95 +777,103 @@ long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 #ifdef __WIN32__
 
 LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
-                                           UINT msg,
+                                           UINT message,
                                            WPARAM wParam,
                                            LPARAM lParam)
 {
-    bool processed = FALSE;
-    if ( msg == WM_KEYDOWN
-#if wxUSE_TOOLTIPS
-         || msg == WM_NOTIFY
-#endif // wxUSE_TOOLTIPS
-       )
+    switch ( message )
     {
-        wxRadioBox *radiobox = (wxRadioBox *)::GetWindowLong(hwnd, GWL_USERDATA);
-
-        wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
+        case WM_GETDLGCODE:
+            // we must tell IsDialogMessage()/our kbd processing code that we
+            // want to process arrows ourselves because neither of them is
+            // smart enough to handle arrows properly for us
+            {
+                long lDlgCode = ::CallWindowProc(s_wndprocRadioBtn, hwnd,
+                                                 message, wParam, lParam);
+                return lDlgCode | DLGC_WANTARROWS;
+            }
 
-#if wxUSE_TOOLTIPS && !defined(__GNUWIN32__)
-        if ( msg == WM_NOTIFY )
-        {
-            NMHDR* hdr = (NMHDR *)lParam;
-            if ( (int)hdr->code == TTN_NEEDTEXT )
+#if wxUSE_TOOLTIPS
+        case WM_NOTIFY:
             {
-                wxToolTip *tt = radiobox->GetToolTip();
-                if ( tt )
+                NMHDR* hdr = (NMHDR *)lParam;
+                if ( (int)hdr->code == TTN_NEEDTEXT )
                 {
-                    TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
-                    ttt->lpszText = (wxChar *)tt->GetTip().c_str();
+                    wxRadioBox *radiobox = (wxRadioBox *)
+                        ::GetWindowLong(hwnd, GWL_USERDATA);
 
-                    processed = TRUE;
+                    wxCHECK_MSG( radiobox, 0,
+                                 wxT("radio button without radio box?") );
+
+                    wxToolTip *tooltip = radiobox->GetToolTip();
+                    if ( tooltip )
+                    {
+                        TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
+                        ttt->lpszText = (wxChar *)tooltip->GetTip().c_str();
+                    }
+
+                    // processed
+                    return 0;
                 }
             }
-        }
-        else // msg == WM_KEYDOWN
+            break;
 #endif // wxUSE_TOOLTIPS
-        {
-            processed = TRUE;
 
-            int sel = radiobox->GetSelection();
-
-            switch ( wParam )
+        case WM_KEYDOWN:
             {
-                case VK_UP:
-                    sel--;
-                    break;
+                wxRadioBox *radiobox = (wxRadioBox *)
+                    ::GetWindowLong(hwnd, GWL_USERDATA);
 
-                case VK_LEFT:
-                    sel -= radiobox->GetNumVer();
-                    break;
+                wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
 
-                case VK_DOWN:
-                    sel++;
-                    break;
+                bool processed = TRUE;
 
-                case VK_RIGHT:
-                    sel += radiobox->GetNumVer();
-                    break;
+                int selOld = radiobox->GetSelection();
+                int selNew = selOld;
 
-                case VK_TAB:
-                    {
-                        wxNavigationKeyEvent event;
-                        event.SetDirection(!(::GetKeyState(VK_SHIFT) & 0x100));
-                        event.SetWindowChange(FALSE);
-                        event.SetEventObject(radiobox);
+                switch ( wParam )
+                {
+                    case VK_UP:
+                        selNew--;
+                        break;
 
-                        if ( radiobox->GetEventHandler()->ProcessEvent(event) )
-                            return 0;
-                    }
-                    // fall through
+                    case VK_LEFT:
+                        selNew -= radiobox->GetNumVer();
+                        break;
 
-                default:
-                    processed = FALSE;
-            }
+                    case VK_DOWN:
+                        selNew++;
+                        break;
 
-            if ( processed )
-            {
-                if ( sel >= 0 && sel < radiobox->Number() )
+                    case VK_RIGHT:
+                        selNew += radiobox->GetNumVer();
+                        break;
+
+                    default:
+                        processed = FALSE;
+                }
+
+                if ( processed )
                 {
-                    radiobox->SetSelection(sel);
+                    // ensure that selNew is in range [0..num)
+                    int num = radiobox->Number();
+                    selNew += num;
+                    selNew %= num;
+
+                    if ( selNew != selOld )
+                    {
+                        radiobox->SetSelection(selNew);
+
+                        // emulate the button click
+                        radiobox->SendNotificationEvent();
 
-                    // emulate the button click
-                    radiobox->SendNotificationEvent();
+                        return 0;
+                    }
                 }
             }
-        }
     }
 
-    if ( processed )
-        return 0;
-
-    return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, msg, wParam, lParam);
+    return ::CallWindowProc(s_wndprocRadioBtn, hwnd, message, wParam, lParam);
 }
 
 #endif // __WIN32__
index cccb111c5d843bc780f41e75cd2a036ec0e3f668..794d146e783f4a06d6d1f95a6b52191b665809e8 100644 (file)
@@ -893,30 +893,19 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
             // ourselves the fact that we got here means that the user code
             // decided to skip processing of this TAB - probably to let it
             // do its default job.
-            //
-            // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is
-            //     handled by Windows
             {
                 wxNavigationKeyEvent eventNav;
                 eventNav.SetDirection(!event.ShiftDown());
-                eventNav.SetWindowChange(FALSE);
+                eventNav.SetWindowChange(event.ControlDown());
                 eventNav.SetEventObject(this);
 
                 if ( GetParent()->GetEventHandler()->ProcessEvent(eventNav) )
                     return;
             }
             break;
-
-        default:
-            event.Skip();
-            return;
     }
 
-    // don't just call event.Skip() because this will cause TABs and ENTERs
-    // be passed upwards and we don't always want this - instead process it
-    // right here
-
-    // FIXME
+    // no, we didn't process it
     event.Skip();
 }
 
index 8b93c29007080042750182725ef6aae26c558da7..128c77e852b8ed075b717a5841d64e412d67e49d 100644 (file)
     #include <commctrl.h>
 #endif
 
+#ifndef _WIN32_IE
+    // minimal set of features by default
+    #define _WIN32_IE 0x0200
+#endif
+
 // VZ: normally, the trick with subclassing the tooltip control and processing
 //     TTM_WINDOWFROMPOINT should work but, somehow, it doesn't. I leave the
 //     code here for now (but it's not compiled) in case we need it later.
 //
-//     For now, instead of this, we just add all radiobox buttons to the
-//     tooltip control as well (see SetWindow) - this is probably less
-//     efficient, but it works.
-#define wxUSE_TTM_WINDOWFROMPOINT   1
+//     For now I use an ugly workaround and process TTN_NEEDTEXT directly in
+//     radio button wnd proc - fixing TTM_WINDOWFROMPOINT code would be nice
+//     because it would then work for all controls, not only radioboxes but for
+//     now I don't understand what's wrong with it...
+#define wxUSE_TTM_WINDOWFROMPOINT   0
 
 // ----------------------------------------------------------------------------
 // global variables
@@ -83,7 +89,7 @@ public:
         // version of it. So we always use the old size - if we ever start
         // using our lParam member, we'd have to check for comctl32 version
         // during run-time
-#if defined(_WIN32_IE) && (_WIN32_IE >= 0x0300)
+#if _WIN32_IE >= 0x0300
         cbSize = sizeof(TOOLINFO) - sizeof(LPARAM);
 #else // old headers
         cbSize = sizeof(TOOLINFO);
@@ -139,27 +145,36 @@ LRESULT APIENTRY wxToolTipWndProc(HWND hwndTT,
     if ( msg == TTM_WINDOWFROMPOINT )
     {
         LPPOINT ppt = (LPPOINT)lParam;
-        // is the window under control a wxWindow?
+
+        // the window on which event occured
         HWND hwnd = ::WindowFromPoint(*ppt);
 
-        // return a HWND correspondign to wxWindow because only wxWindows are
+        OutputDebugString("TTM_WINDOWFROMPOINT: ");
+        OutputDebugString(wxString::Format("0x%08x => ", hwnd));
+
+        // return a HWND corresponding to a wxWindow because only wxWindows are
         // associated with tooltips using TTM_ADDTOOL
-        while ( hwnd && !wxFindWinFromHandle((WXHWND)hwnd) )
-        {
-            hwnd = ::GetParent(hwnd);
-        }
+        wxWindow *win = wxGetWindowFromHWND((WXHWND)hwnd);
 
-        if ( hwnd )
+        if ( win )
         {
+            hwnd = GetHwndOf(win);
+            OutputDebugString(wxString::Format("0x%08x\r\n", hwnd));
+
+#if 0
             // modify the point too!
             RECT rect;
             GetWindowRect(hwnd, &rect);
 
-            ppt->x = rect.left;
-            ppt->y = rect.top;
-
+            ppt->x = (rect.right - rect.left) / 2;
+            ppt->y = (rect.bottom - rect.top) / 2;
+#endif // 0
             return (LRESULT)hwnd;
         }
+        else
+        {
+            OutputDebugString("no window\r\n");
+        }
     }
 
     return ::CallWindowProc(CASTWNDPROC gs_wndprocToolTip, hwndTT, msg, wParam, lParam);
@@ -268,6 +283,59 @@ void wxToolTip::Add(WXHWND hWnd)
     {
         wxLogDebug(_T("Failed to create the tooltip '%s'"), m_text.c_str());
     }
+    else
+    {
+        // check for multiline toopltip
+        int index = m_text.Find(_T('\n'));
+
+        if ( index != wxNOT_FOUND )
+        {
+#if _WIN32_IE >= 0x0300
+            if ( wxTheApp->GetComCtl32Version() >= 470 )
+            {
+                // use TTM_SETMAXWIDTH to make tooltip multiline using the
+                // extent of its first line as max value
+                HFONT hfont = (HFONT)SendTooltipMessage(GetToolTipCtrl(),
+                                                        WM_GETFONT,
+                                                        0, 0);
+                if ( !hfont )
+                {
+                    hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+                    if ( !hfont )
+                    {
+                        wxLogLastError("GetStockObject(DEFAULT_GUI_FONT)");
+                    }
+                }
+
+                HDC hdc = CreateCompatibleDC(NULL);
+                if ( !hdc )
+                {
+                    wxLogLastError("CreateCompatibleDC(NULL)");
+                }
+
+                if ( !SelectObject(hdc, hfont) )
+                {
+                    wxLogLastError("SelectObject(hfont)");
+                }
+
+                SIZE sz;
+                if ( !GetTextExtentPoint(hdc, m_text, index, &sz) )
+                {
+                    wxLogLastError("GetTextExtentPoint");
+                }
+
+                DeleteDC(hdc);
+
+                SendTooltipMessage(GetToolTipCtrl(), TTM_SETMAXTIPWIDTH,
+                                   0, (void *)sz.cx);
+            }
+#endif // comctl32.dll >= 4.70
+
+            // replace the '\n's with spaces because otherwise they appear as
+            // unprintable characters in the tooltip string
+            m_text.Replace(_T("\n"), _T(" "));
+        }
+    }
 }
 
 void wxToolTip::SetWindow(wxWindow *win)
@@ -282,24 +350,30 @@ void wxToolTip::SetWindow(wxWindow *win)
         Add(m_window->GetHWND());
     }
 
-#if 1 //!wxUSE_TTM_WINDOWFROMPOINT
     // and all of its subcontrols (e.g. radiobuttons in a radiobox) as well
     wxControl *control = wxDynamicCast(m_window, wxControl);
     if ( control )
     {
-        size_t count = control->GetSubcontrols().GetCount();
+        const wxArrayLong& subcontrols = control->GetSubcontrols();
+        size_t count = subcontrols.GetCount();
         for ( size_t n = 0; n < count; n++ )
         {
-            wxWindowID id = control->GetSubcontrols()[n];
+            int id = subcontrols[n];
             HWND hwnd = GetDlgItem(GetHwndOf(m_window), id);
-
-            if ( hwnd )
+            if ( !hwnd )
             {
-                Add((WXHWND)hwnd);
+                // may be it's a child of parent of the control, in fact?
+                // (radiobuttons are subcontrols, i.e. children of the radiobox
+                // for wxWindows but are its siblings at Windows level)
+                hwnd = GetDlgItem(GetHwndOf(m_window->GetParent()), id);
             }
+
+            // must have it by now!
+            wxASSERT_MSG( hwnd, _T("no hwnd for subcontrol?") );
+
+            Add((WXHWND)hwnd);
         }
     }
-#endif // !wxUSE_TTM_WINDOWFROMPOINT
 }
 
 void wxToolTip::SetTip(const wxString& tip)
index ee86522918bb21844670b7e298652de8ffaf5626..fea94bda8b0118f8c80e1e250bc670bc1171422c 100644 (file)
     #endif
 #endif
 
-// ---------------------------------------------------------------------------
-// macros
-// ---------------------------------------------------------------------------
-
-// standard macros missing from some compilers headers
-#ifndef GET_X_LPARAM
-    #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
-    #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
-#endif // GET_X_LPARAM
-
 // ---------------------------------------------------------------------------
 // global variables
 // ---------------------------------------------------------------------------
@@ -2293,6 +2283,13 @@ bool wxWindow::MSWCreate(int id,
     if ( width > -1 ) width1 = width;
     if ( height > -1 ) height1 = height;
 
+    // if we have wxTAB_TRAVERSAL style, we want WS_EX_CONTROLPARENT or
+    // IsDialogMessage() won't work for us
+    if ( GetWindowStyleFlag() & wxTAB_TRAVERSAL )
+    {
+        extendedStyle |= WS_EX_CONTROLPARENT;
+    }
+
     HWND hParent = (HWND)NULL;
     if ( parent )
         hParent = (HWND) parent->GetHWND();
@@ -3631,6 +3628,45 @@ wxWindow *wxGetActiveWindow()
     return NULL;
 }
 
+extern wxWindow *wxGetWindowFromHWND(WXHWND hWnd)
+{
+    HWND hwnd = (HWND)hWnd;
+
+    // For a radiobutton, we get the radiobox from GWL_USERDATA (which is set
+    // by code in msw/radiobox.cpp), for all the others we just search up the
+    // window hierarchy
+    wxWindow *win = (wxWindow *)NULL;
+    if ( hwnd )
+    {
+        win = wxFindWinFromHandle((WXHWND)hwnd);
+        if ( !win )
+        {
+            // native radiobuttons return DLGC_RADIOBUTTON here and for any
+            // wxWindow class which overrides WM_GETDLGCODE processing to
+            // do it as well, win would be already non NULL
+            if ( ::SendMessage((HWND)hwnd, WM_GETDLGCODE,
+                               0, 0) & DLGC_RADIOBUTTON )
+            {
+                win = (wxWindow *)::GetWindowLong(hwnd, GWL_USERDATA);
+            }
+            else
+            {
+                // hwnd is not a wxWindow, try its parent next below
+                hwnd = ::GetParent(hwnd);
+            }
+        }
+        //else: it's a wxRadioButton, not a radiobutton from wxRadioBox
+    }
+
+    while ( hwnd && !win )
+    {
+        win = wxFindWinFromHandle((WXHWND)hwnd);
+        hwnd = ::GetParent(hwnd);
+    }
+
+    return win;
+}
+
 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
 // in active frames and dialogs, regardless of where the focus is.
 static HHOOK wxTheKeyboardHook = 0;
@@ -3646,11 +3682,12 @@ void wxSetKeyboardHook(bool doIt)
         wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
 
 #if defined(__WIN32__) && !defined(__TWIN32__)
-            GetCurrentThreadId());
+            GetCurrentThreadId()
         //      (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
 #else
-            GetCurrentTask());
+            GetCurrentTask()
 #endif
+            );
     }
     else
     {