]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
update the popup menu item when it's [un]checked too, as it already happens for the...
[wxWidgets.git] / src / msw / window.cpp
index 50d4d88eb767e447e56e0da4cb1aa0745cde0d6b..00465394809251ea48d2cd48bbbf5cefab636f4c 100644 (file)
@@ -93,6 +93,7 @@
 
 #include "wx/notebook.h"
 #include "wx/listctrl.h"
+#include "wx/dynlib.h"
 
 #include <string.h>
 
 #endif
 #endif
 
-#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE)
+#if defined(TME_LEAVE) && defined(WM_MOUSELEAVE) && wxUSE_DYNLIB_CLASS
     #define HAVE_TRACKMOUSEEVENT
 #endif // everything needed for TrackMouseEvent()
 
@@ -802,7 +803,30 @@ bool wxWindowMSW::SetCursor(const wxCursor& cursor)
     // don't "overwrite" busy cursor
     if ( m_cursor.Ok() && !wxIsBusy() )
     {
-        ::SetCursor(GetHcursorOf(m_cursor));
+        // normally we should change the cursor only if it's over this window
+        // but we should do it always if we capture the mouse currently
+        bool set = HasCapture();
+        if ( !set )
+        {
+            HWND hWnd = GetHwnd();
+
+            POINT point;
+#ifdef __WXWINCE__
+            ::GetCursorPosWinCE(&point);
+#else
+            ::GetCursorPos(&point);
+#endif
+
+            RECT rect = wxGetWindowRect(hWnd);
+
+            set = ::PtInRect(&rect, point) != 0;
+        }
+
+        if ( set )
+        {
+            ::SetCursor(GetHcursorOf(m_cursor));
+        }
+        //else: will be set later when the mouse enters this window
     }
 
     return true;
@@ -1539,9 +1563,13 @@ void wxWindowMSW::Update()
 // drag and drop
 // ---------------------------------------------------------------------------
 
+#if wxUSE_DRAG_AND_DROP || !defined(__WXWINCE__)
+
+#if wxUSE_STATBOX
+
 // we need to lower the sibling static boxes so controls contained within can be
 // a drop target
-static inline void AdjustStaticBoxZOrder(wxWindow *parent)
+static void AdjustStaticBoxZOrder(wxWindow *parent)
 {
     // no sibling static boxes if we have no parent (ie TLW)
     if ( !parent )
@@ -1560,6 +1588,16 @@ static inline void AdjustStaticBoxZOrder(wxWindow *parent)
     }
 }
 
+#else // !wxUSE_STATBOX
+
+static inline void AdjustStaticBoxZOrder(wxWindow * WXUNUSED(parent))
+{
+}
+
+#endif // wxUSE_STATBOX/!wxUSE_STATBOX
+
+#endif // drag and drop is used
+
 #if wxUSE_DRAG_AND_DROP
 void wxWindowMSW::SetDropTarget(wxDropTarget *pDropTarget)
 {
@@ -1701,6 +1739,13 @@ void wxWindowMSW::DoGetPosition(int *x, int *y) const
         // children, not for the dialogs/frames
         if ( !IsTopLevel() )
         {
+            if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+            {
+                // In RTL mode, we want the logical left x-coordinate,
+                // which would be the physical right x-coordinate.
+                point.x = rect.right;
+            }
+
             // Since we now have the absolute screen coords, if there's a
             // parent we must subtract its top left corner
             if ( parent )
@@ -2133,10 +2178,13 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
             switch ( msg->wParam )
             {
                 case VK_TAB:
-                    if ( lDlgCode & DLGC_WANTTAB ) {
+                    if ( (lDlgCode & DLGC_WANTTAB) && !bCtrlDown )
+                    {
+                        // let the control have the TAB
                         bProcess = false;
                     }
-                    else {
+                    else // use it for navigation
+                    {
                         // Ctrl-Tab cycles thru notebook pages
                         bWindowChange = bCtrlDown;
                         bForward = !bShiftDown;
@@ -2166,9 +2214,9 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
                     // we treat PageUp/Dn as arrows because chances are that
                     // a control which needs arrows also needs them for
                     // navigation (e.g. wxTextCtrl, wxListCtrl, ...)
-                    if ( (lDlgCode & DLGC_WANTARROWS) || !bCtrlDown )
+                    if ( (lDlgCode & DLGC_WANTARROWS) && !bCtrlDown )
                         bProcess = false;
-                    else
+                    else // OTOH Ctrl-PageUp/Dn works as [Shift-]Ctrl-Tab
                         bWindowChange = true;
                     break;
 
@@ -2623,7 +2671,8 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
 
 #ifdef HAVE_TRACKMOUSEEVENT
         case WM_MOUSELEAVE:
-            // filter out excess WM_MOUSELEAVE events sent after PopupMenu() (on XP at least)
+            // filter out excess WM_MOUSELEAVE events sent after PopupMenu()
+            // (on XP at least)
             if ( m_mouseInWindow )
             {
                 GenerateMouseLeave();
@@ -2815,12 +2864,12 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
 #endif // defined(WM_DRAWITEM)
 
         case WM_GETDLGCODE:
-            if ( !IsOfStandardClass() )
+            if ( !IsOfStandardClass() || HasFlag(wxWANTS_CHARS) )
             {
                 // we always want to get the char events
                 rc.result = DLGC_WANTCHARS;
 
-                if ( GetWindowStyleFlag() & wxWANTS_CHARS )
+                if ( HasFlag(wxWANTS_CHARS) )
                 {
                     // in fact, we want everything
                     rc.result |= DLGC_WANTARROWS |
@@ -3943,6 +3992,19 @@ bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
 #endif
 }
 
+bool wxWindowMSW::IsDoubleBuffered() const
+{
+    for ( const wxWindowMSW *wnd = this;
+          wnd && !wnd->IsTopLevel(); wnd =
+          wnd->GetParent() )
+    {
+        if ( ::GetWindowLong(GetHwndOf(wnd), GWL_EXSTYLE) & WS_EX_COMPOSITED )
+            return true;
+    }
+
+    return false;
+}
+
 // ---------------------------------------------------------------------------
 // owner drawn stuff
 // ---------------------------------------------------------------------------
@@ -4358,7 +4420,7 @@ void wxWindowMSW::OnPaint(wxPaintEvent& event)
 
 bool wxWindowMSW::HandleEraseBkgnd(WXHDC hdc)
 {
-    wxDCTemp dc(hdc);
+    wxDCTemp dc(hdc, GetClientSize());
 
     dc.SetHDC(hdc);
     dc.SetWindow((wxWindow *)this);
@@ -4461,11 +4523,37 @@ WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint)
     return 0;
 }
 
-bool wxWindowMSW::HandlePrintClient(WXHDC WXUNUSED(hDC))
+bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
 {
-    // TODO: handle wxBG_STYLE_CUSTOM and/or wxBG_STYLE_COLOUR here so when
-    // DrawParentThemeBackground() from uxtheme.dll is called we don't get
-    // the default background e.g. the border when custom drawing buttons
+    // we receive this message when DrawThemeParentBackground() is
+    // called from def window proc of several controls under XP and we
+    // must draw properly themed background here
+    //
+    // note that naively I'd expect filling the client rect with the
+    // brush returned by MSWGetBgBrush() work -- but for some reason it
+    // doesn't and we have to call parents MSWPrintChild() which is
+    // supposed to call DrawThemeBackground() with appropriate params
+    //
+    // also note that in this case lParam == PRF_CLIENT but we're
+    // clearly expected to paint the background and nothing else!
+
+    if ( IsTopLevel() || InheritsBackgroundColour() )
+        return false;
+
+    // sometimes we don't want the parent to handle it at all, instead
+    // return whatever value this window wants
+    if ( !MSWShouldPropagatePrintChild() )
+        return MSWPrintChild(hDC, (wxWindow *)this);
+
+    for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
+    {
+        if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
+            return true;
+
+        if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
+            break;
+    }
+
     return false;
 }
 
@@ -4872,14 +4960,41 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
             m_mouseInWindow = true;
 
 #ifdef HAVE_TRACKMOUSEEVENT
-            WinStruct<TRACKMOUSEEVENT> trackinfo;
+            typedef BOOL (WINAPI *_TrackMouseEvent_t)(LPTRACKMOUSEEVENT);
+#ifdef __WXWINCE__
+            static const _TrackMouseEvent_t
+                s_pfn_TrackMouseEvent = _TrackMouseEvent;
+#else // !__WXWINCE__
+            static _TrackMouseEvent_t s_pfn_TrackMouseEvent;
+            static bool s_initDone = false;
+            if ( !s_initDone )
+            {
+                wxLogNull noLog;
 
-            trackinfo.dwFlags = TME_LEAVE;
-            trackinfo.hwndTrack = GetHwnd();
+                wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
+                if ( dllComCtl32.IsLoaded() )
+                {
+                    s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
+                        dllComCtl32.GetSymbol(_T("_TrackMouseEvent"));
+                }
 
-            // Use the commctrl.h _TrackMouseEvent(), which will call the real
-            // TrackMouseEvent() if available or emulate it
-            _TrackMouseEvent(&trackinfo);
+                s_initDone = true;
+
+                // notice that it's ok to unload comctl32.dll here as it won't
+                // be really unloaded, being still in use because we link to it
+                // statically too
+            }
+
+            if ( s_pfn_TrackMouseEvent )
+#endif // __WXWINCE__/!__WXWINCE__
+            {
+                WinStruct<TRACKMOUSEEVENT> trackinfo;
+
+                trackinfo.dwFlags = TME_LEAVE;
+                trackinfo.hwndTrack = GetHwnd();
+
+                (*s_pfn_TrackMouseEvent)(&trackinfo);
+            }
 #endif // HAVE_TRACKMOUSEEVENT
 
             wxMouseEvent event(wxEVT_ENTER_WINDOW);
@@ -4889,7 +5004,7 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
         }
     }
 #ifdef HAVE_TRACKMOUSEEVENT
-    else
+    else // mouse not in window
     {
         // Check if we need to send a LEAVE event
         // Windows doesn't send WM_MOUSELEAVE if the mouse has been captured so