]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
return begining of the selection for GetInsertionPoint to match what
[wxWidgets.git] / src / msw / window.cpp
index 67da2efe76697f0fd220e2ae98ddc1df533f3dea..58d2235f7b1d15de6e686b04524dc74958230f36 100644 (file)
@@ -782,12 +782,6 @@ void wxWindowMSW::WarpPointer (int x, int y)
 // scrolling stuff
 // ---------------------------------------------------------------------------
 
-// convert wxHORIZONTAL/wxVERTICAL to SB_HORZ/SB_VERT
-static inline int wxDirToWinStyle(int orient)
-{
-    return orient == wxHORIZONTAL ? SB_HORZ : SB_VERT;
-}
-
 inline int GetScrollPosition(HWND hWnd, int wOrient)
 {
 #ifdef __WXMICROWIN__
@@ -1052,6 +1046,8 @@ bool wxCheckWindowWndProc(WXHWND hWnd, WXFARPROC wndProc)
     // On WinCE (at least), the wndproc comparison doesn't work,
     // so have to use something like this.
 #ifdef __WXWINCE__
+    wxUnusedVar(wndProc);
+
     extern       wxChar *wxCanvasClassName;
     extern       wxChar *wxCanvasClassNameNR;
     extern const wxChar *wxMDIFrameClassName;
@@ -1126,7 +1122,7 @@ void wxWindowMSW::SetWindowStyleFlag(long flags)
 
         ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
 
-        // we must call SetWindowPos() to flash the cached extended style and
+        // we must call SetWindowPos() to flush the cached extended style and
         // also to make the change to wxSTAY_ON_TOP style take effect: just
         // setting the style simply doesn't work
         if ( !::SetWindowPos(GetHwnd(),
@@ -1150,9 +1146,11 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
 
     // using this flag results in very significant reduction in flicker,
     // especially with controls inside the static boxes (as the interior of the
-    // box is not redrawn twice).
-    // wxCLIP_CHILDREN support is for compatibility with old applications only.
-    if ((!wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children")) == 1) || (flags & wxCLIP_CHILDREN))
+    // box is not redrawn twice).but sometimes results in redraw problems, so
+    // optionally allow the old code to continue to use it provided a special
+    // system option is turned on
+    if ( !wxSystemOptions::GetOptionInt(wxT("msw.window.no-clip-children"))
+            || (flags & wxCLIP_CHILDREN) )
         style |= WS_CLIPCHILDREN;
 
     // it doesn't seem useful to use WS_CLIPSIBLINGS here as we officially
@@ -1299,7 +1297,8 @@ void wxWindowMSW::Freeze()
 {
     if ( !m_frozenness++ )
     {
-        SendSetRedraw(GetHwnd(), false);
+        if ( IsShown() )
+            SendSetRedraw(GetHwnd(), false);
     }
 }
 
@@ -1309,11 +1308,14 @@ void wxWindowMSW::Thaw()
 
     if ( !--m_frozenness )
     {
-        SendSetRedraw(GetHwnd(), true);
+        if ( IsShown() )
+        {
+            SendSetRedraw(GetHwnd(), true);
 
-        // we need to refresh everything or otherwise he invalidated area is not
-        // repainted
-        Refresh();
+            // we need to refresh everything or otherwise the invalidated area
+            // is not going to be repainted
+            Refresh();
+        }
     }
 }
 
@@ -1322,18 +1324,31 @@ void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
     HWND hWnd = GetHwnd();
     if ( hWnd )
     {
+        RECT mswRect;
+        const RECT *pRect;
         if ( rect )
         {
-            RECT mswRect;
             mswRect.left = rect->x;
             mswRect.top = rect->y;
             mswRect.right = rect->x + rect->width;
             mswRect.bottom = rect->y + rect->height;
 
-            ::InvalidateRect(hWnd, &mswRect, eraseBack);
+            pRect = &mswRect;
         }
         else
-            ::InvalidateRect(hWnd, NULL, eraseBack);
+        {
+            pRect = NULL;
+        }
+
+#ifndef __SMARTPHONE__
+        UINT flags = RDW_INVALIDATE | RDW_ALLCHILDREN;
+        if ( eraseBack )
+            flags |= RDW_ERASE;
+
+        ::RedrawWindow(hWnd, pRect, NULL, flags);
+#else
+        ::InvalidateRect(hWnd, pRect, eraseBack);
+#endif
     }
 }
 
@@ -1509,12 +1524,12 @@ void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
     // if our parent had prepared a defer window handle for us, use it (unless
     // we are a top level window)
     wxWindowMSW *parent = GetParent();
-    HDWP hdwp = (parent && !IsTopLevel()) ? (HDWP)parent->m_hDWP : NULL;
+    HDWP hdwp = parent && !IsTopLevel() ? (HDWP)parent->m_hDWP : NULL;
     if ( hdwp )
     {
         hdwp = ::DeferWindowPos(hdwp, GetHwnd(), NULL,
-                                x, y, width, height,
-                                SWP_NOZORDER);
+                            x, y, width, height,
+                            SWP_NOZORDER);
         if ( !hdwp )
         {
             wxLogLastError(_T("DeferWindowPos"));
@@ -2204,7 +2219,6 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
     {
         bool        allow;
         WXLRESULT   result;
-        WXHICON     hIcon;
         WXHBRUSH    hBrush;
     } rc;
 
@@ -2281,6 +2295,7 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
 
 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
         case WM_ACTIVATEAPP:
+            // This implicitly sends a wxEVT_ACTIVATE_APP event
             wxTheApp->SetActive(wParam != 0, FindFocus());
             break;
 #endif
@@ -2303,55 +2318,34 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
             processed = HandleKillFocus((WXHWND)(HWND)wParam);
             break;
 
-        case WM_PAINT:
-            {
-                if ( wParam )
-                {
-                    // cast to wxWindow is needed for wxUniv
-                    wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
-                    processed = HandlePaint();
-                }
-                else
-                {
-                    processed = HandlePaint();
-                }
-                break;
-            }
-
-#ifdef WM_PRINT
         case WM_PRINTCLIENT:
-            if ( GetParent() &&
-                  GetParent()->MSWPrintChild((wxWindow *)this, wParam, lParam) )
-            {
-                processed = true;
-            }
+            processed = HandlePrintClient((WXHDC)wParam);
             break;
 
-        case WM_PRINT:
+        case WM_PAINT:
+            if ( wParam )
             {
-                if ( lParam & PRF_ERASEBKGND )
-                    HandleEraseBkgnd((WXHDC)(HDC)wParam);
-
                 wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
 
                 processed = HandlePaint();
             }
+            else // no DC given
+            {
+                processed = HandlePaint();
+            }
             break;
-#endif // WM_PRINT
 
         case WM_CLOSE:
 #ifdef __WXUNIVERSAL__
             // Universal uses its own wxFrame/wxDialog, so we don't receive
             // close events unless we have this.
             Close();
-            processed = true;
-            rc.result = TRUE;
-#else
+#endif // __WXUNIVERSAL__
+
             // don't let the DefWindowProc() destroy our window - we'll do it
             // ourselves in ~wxWindow
             processed = true;
             rc.result = TRUE;
-#endif
             break;
 
         case WM_SHOWWINDOW:
@@ -3228,7 +3222,7 @@ bool wxWindowMSW::MSWOnNotify(int WXUNUSED(idCtrl),
 
 bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
 {
-#ifndef __WXWINCE__
+#ifdef ENDSESSION_LOGOFF
     wxCloseEvent event(wxEVT_QUERY_END_SESSION, wxID_ANY);
     event.SetEventObject(wxTheApp);
     event.SetCanVeto(true);
@@ -3245,13 +3239,15 @@ bool wxWindowMSW::HandleQueryEndSession(long logOff, bool *mayEnd)
 
     return rc;
 #else
+    wxUnusedVar(logOff);
+    wxUnusedVar(mayEnd);
     return false;
 #endif
 }
 
 bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
 {
-#ifndef __WXWINCE__
+#ifdef ENDSESSION_LOGOFF
     // do nothing if the session isn't ending
     if ( !endSession )
         return false;
@@ -3267,6 +3263,8 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
 
     return wxTheApp->ProcessEvent(event);
 #else
+    wxUnusedVar(endSession);
+    wxUnusedVar(logOff);
     return false;
 #endif
 }
@@ -3576,7 +3574,7 @@ wxWindowMSW::MSWOnDrawItem(int WXUNUSED_UNLESS_ODRAWN(id),
     if ( id == 0 && pDrawStruct->CtlType == ODT_MENU )
     {
         wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
-        if (!pMenuItem) return false;
+
         wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
                          false, _T("MSWOnDrawItem: bad wxMenuItem pointer") );
 
@@ -3635,7 +3633,15 @@ wxWindowMSW::MSWOnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct)
     {
         wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
 
-        wxCHECK_MSG( pMenuItem && pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)),
+        // according to Carsten Fuchs the pointer may be NULL under XP if an
+        // MDI child frame is initially maximized, see this for more info:
+        // http://article.gmane.org/gmane.comp.lib.wxwidgets.general/27745
+        //
+        // so silently ignore it instead of asserting
+        if ( !pMenuItem )
+            return false;
+
+        wxCHECK_MSG( wxDynamicCast(pMenuItem, wxMenuItem),
                         false, _T("MSWOnMeasureItem: bad wxMenuItem pointer") );
 
         size_t w, h;
@@ -3686,12 +3692,16 @@ bool wxWindowMSW::HandleDisplayChange()
 
 #ifndef __WXMICROWIN__
 
-bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd)
+bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC hDC, WXHWND hWnd)
 {
-#if wxUSE_CONTROLS
-    wxWindow *item = FindItemByHWND(pWnd, true);
+#if !wxUSE_CONTROLS || defined(__WXUNIVERSAL__)
+    wxUnusedVar(pDC);
+    wxUnusedVar(hWnd);
+#else
+    wxControl *item = wxDynamicCast(FindItemByHWND(hWnd, true), wxControl);
+
     if ( item )
-        *brush = item->MSWControlColor(pDC);
+        *brush = item->MSWControlColor(hDC, hWnd);
     else
 #endif // wxUSE_CONTROLS
         *brush = NULL;
@@ -3701,11 +3711,6 @@ bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd)
 
 #endif // __WXMICROWIN__
 
-WXHBRUSH wxWindowMSW::MSWControlColor(WXHDC WXUNUSED(hDC))
-{
-    return (WXHBRUSH)0;
-}
-
 bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
 {
 #if wxUSE_PALETTE
@@ -3967,92 +3972,95 @@ void wxWindowMSW::OnEraseBackground(wxEraseEvent& event)
 
 
     // do default background painting
-    if ( !DoEraseBackground(*event.GetDC()) )
+    if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
     {
         // let the system paint the background
         event.Skip();
     }
 }
 
-bool wxWindowMSW::DoEraseBackground(wxDC& dc)
+bool wxWindowMSW::DoEraseBackground(WXHDC hDC)
 {
-    HBRUSH hBrush = (HBRUSH)MSWGetBgBrush(dc.GetHDC());
-    if ( !hBrush )
+    HBRUSH hbr = (HBRUSH)MSWGetBgBrush(hDC);
+    if ( !hbr )
         return false;
 
-    RECT rc;
-    ::GetClientRect(GetHwnd(), &rc);
-    ::FillRect(GetHdcOf(dc), &rc, hBrush);
+    wxFillRect(GetHwnd(), (HDC)hDC, hbr);
 
     return true;
 }
 
-WXHBRUSH wxWindowMSW::MSWGetSolidBgBrushForChild(wxWindow *child)
-{
-    wxColour col = MSWGetBgColourForChild(child);
-    if ( col.Ok() )
-    {
-        // draw children with the same colour as the parent
-        wxBrush *brush = wxTheBrushList->FindOrCreateBrush(col, wxSOLID);
-
-        return (WXHBRUSH)brush->GetResourceHandle();
-    }
-
-    return 0;
-}
-
-wxColour wxWindowMSW::MSWGetBgColourForChild(wxWindow *child)
+WXHBRUSH
+wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), WXHWND hWnd)
 {
     if ( m_hasBgCol )
     {
         // our background colour applies to:
         //  1. this window itself, always
         //  2. all children unless the colour is "not inheritable"
-        //  3. immediate transparent children which should show the same
-        //     background as we do, but not for transparent grandchildren
-        //     which use the background of their immediate parent instead
-        if ( m_inheritBgCol ||
-                child == this ||
-                    (child->HasTransparentBackground() &&
-                        child->GetParent() == this) )
+        //  3. even if it is not inheritable, our immediate transparent
+        //     children should still inherit it -- but not any transparent
+        //     children because it would look wrong if a child of non
+        //     transparent child would show our bg colour when the child itself
+        //     does not
+        wxWindow *win = wxFindWinFromHandle(hWnd);
+        if ( win == this ||
+                m_inheritBgCol ||
+                    (win && win->HasTransparentBackground() &&
+                        win->GetParent() == this) )
         {
-            return GetBackgroundColour();
+            // draw children with the same colour as the parent
+            wxBrush *
+                brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
+
+            return (WXHBRUSH)GetHbrushOf(*brush);
         }
     }
 
-    return wxNullColour;
+    return 0;
 }
 
-WXHBRUSH wxWindowMSW::MSWGetBgBrushForSelf(wxWindow *parent, WXHDC hDC)
+WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, WXHWND hWndToPaint)
 {
-    return parent->MSWGetBgBrushForChild(hDC, (wxWindow *)this);
-}
+    if ( !hWndToPaint )
+        hWndToPaint = GetHWND();
 
-WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC)
-{
-    for ( wxWindow *win = (wxWindow *)this; win; win = win->GetParent() )
+    for ( wxWindowMSW *win = this; win; win = win->GetParent() )
     {
-        WXHBRUSH hBrush = MSWGetBgBrushForSelf(win, hDC);
+        WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, hWndToPaint);
         if ( hBrush )
             return hBrush;
 
-        // background is not inherited beyond the windows which have their own
-        // fixed background such as top level windows and notebooks and for
-        // windows for which a custom colour had been explicitly set with
-        // SetOwnBackgroundColour() and so shouldn't affect its children
-        if ( win->ProvidesBackground() ||
-                (win->m_hasBgCol && !win->m_inheritBgCol) )
+        // background is not inherited beyond top level windows
+        if ( win->IsTopLevel() )
             break;
     }
 
     return 0;
 }
 
-bool
-wxWindowMSW::MSWPrintChild(wxWindow * WXUNUSED(win),
-                           WXWPARAM WXUNUSED(wParam),
-                           WXLPARAM WXUNUSED(lParam))
+bool wxWindowMSW::HandlePrintClient(WXHDC hDC)
 {
+    // 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!
+    for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
+    {
+        if ( win->MSWPrintChild(hDC, (wxWindow *)this) )
+            return true;
+
+        if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
+            break;
+    }
+
     return false;
 }
 
@@ -4268,18 +4276,27 @@ bool wxWindowMSW::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control)
 
         return GetEventHandler()->ProcessEvent(event);
     }
-#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
     else
     {
+#if wxUSE_SPINCTRL && !defined(__WXUNIVERSAL__)
         // the text ctrl which is logically part of wxSpinCtrl sends WM_COMMAND
         // notifications to its parent which we want to reflect back to
         // wxSpinCtrl
         wxSpinCtrl *spin = wxSpinCtrl::GetSpinForTextCtrl(control);
         if ( spin && spin->ProcessTextCommand(cmd, id) )
             return true;
-    }
 #endif // wxUSE_SPINCTRL
 
+#if wxUSE_CHOICE && defined(__SMARTPHONE__)
+        // the listbox ctrl which is logically part of wxChoice sends WM_COMMAND
+        // notifications to its parent which we want to reflect back to
+        // wxChoice
+        wxChoice *choice = wxChoice::GetChoiceForListBox(control);
+        if ( choice && choice->MSWCommand(cmd, id) )
+            return true;
+#endif
+    }
+
     return false;
 }
 
@@ -5133,6 +5150,9 @@ bool wxGetKeyState(wxKeyCode key)
 {
     bool bVirtual;
 
+    wxASSERT_MSG(key != WXK_LBUTTON && key != WXK_RBUTTON && key !=
+        WXK_MBUTTON, wxT("can't use wxGetKeyState() for mouse buttons"));
+
 //High order with GetAsyncKeyState only available on WIN32
 #ifdef __WIN32__
     //If the requested key is a LED key, return
@@ -5784,6 +5804,25 @@ wxPoint wxGetMousePosition()
 
 #if wxUSE_HOTKEY
 
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+static void WinCEUnregisterHotKey(int modifiers, int id)
+{
+    // Register hotkeys for the hardware buttons
+    HINSTANCE hCoreDll;
+    typedef BOOL (WINAPI *UnregisterFunc1Proc)(UINT, UINT);
+
+    UnregisterFunc1Proc procUnregisterFunc;
+    hCoreDll = LoadLibrary(_T("coredll.dll"));
+    if (hCoreDll)
+    {
+        procUnregisterFunc = (UnregisterFunc1Proc)GetProcAddress(hCoreDll, _T("UnregisterFunc1"));
+        if (procUnregisterFunc)
+            procUnregisterFunc(modifiers, id);
+        FreeLibrary(hCoreDll);
+    }
+}
+#endif
+
 bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
 {
     UINT win_modifiers=0;
@@ -5796,6 +5835,12 @@ bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
     if ( modifiers & wxMOD_WIN )
         win_modifiers |= MOD_WIN;
 
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+    // Required for PPC and Smartphone hardware buttons
+    if (keycode >= WXK_SPECIAL1 && keycode <= WXK_SPECIAL20)
+        WinCEUnregisterHotKey(win_modifiers, hotkeyId);
+#endif
+
     if ( !::RegisterHotKey(GetHwnd(), hotkeyId, win_modifiers, keycode) )
     {
         wxLogLastError(_T("RegisterHotKey"));
@@ -5808,6 +5853,10 @@ bool wxWindowMSW::RegisterHotKey(int hotkeyId, int modifiers, int keycode)
 
 bool wxWindowMSW::UnregisterHotKey(int hotkeyId)
 {
+#if defined(__SMARTPHONE__) || defined(__POCKETPC__)
+    WinCEUnregisterHotKey(MOD_WIN, hotkeyId);
+#endif
+
     if ( !::UnregisterHotKey(GetHwnd(), hotkeyId) )
     {
         wxLogLastError(_T("UnregisterHotKey"));