]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
update column highlight when mouse hovers over the control
[wxWidgets.git] / src / msw / window.cpp
index 557fc3d937b0d05661a285bfc28bc91e6f65c53c..b147823bea98ad45e6c5cb4c4f8467bd2209e6ab 100644 (file)
 extern wxMenu *wxCurrentPopupMenu;
 #endif
 
-#ifdef __WXWINCE__
-extern       wxChar *wxCanvasClassName;
-#else
-extern const wxChar *wxCanvasClassName;
-#endif
-
 // true if we had already created the std colour map, used by
 // wxGetStdColourMap() and wxWindow::OnSysColourChanged()           (FIXME-MT)
 static bool gs_hasStdCmap = false;
@@ -281,12 +275,11 @@ static void EnsureParentHasControlParentStyle(wxWindow *parent)
      */
     while ( parent && !parent->IsTopLevel() )
     {
-        LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
+        LONG exStyle = wxGetWindowExStyle(parent);
         if ( !(exStyle & WS_EX_CONTROLPARENT) )
         {
             // force the parent to have this style
-            ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
-                            exStyle | WS_EX_CONTROLPARENT);
+            wxSetWindowExStyle(parent, exStyle | WS_EX_CONTROLPARENT);
         }
 
         parent = parent->GetParent();
@@ -590,6 +583,12 @@ wxWindowMSW::~wxWindowMSW()
 
 }
 
+/* static */
+const wxChar *wxWindowMSW::MSWGetRegisteredClassName()
+{
+    return wxApp::GetRegisteredClassName(_T("wxWindow"), COLOR_BTNFACE);
+}
+
 // real construction (Init() must have been called before!)
 bool wxWindowMSW::Create(wxWindow *parent,
                          wxWindowID id,
@@ -622,7 +621,8 @@ bool wxWindowMSW::Create(wxWindow *parent,
         msflags |= WS_VISIBLE;
     }
 
-    if ( !MSWCreate(wxCanvasClassName, NULL, pos, size, msflags, exstyle) )
+    if ( !MSWCreate(MSWGetRegisteredClassName(),
+                    NULL, pos, size, msflags, exstyle) )
         return false;
 
     InheritAttributes();
@@ -716,15 +716,27 @@ bool wxWindowMSW::Show(bool show)
         ::ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE);
     }
 
+    if ( IsFrozen() )
+    {
+        // DoFreeze/DoThaw don't do anything if the window is not shown, so
+        // we have to call them from here now
+        if ( show )
+            DoFreeze();
+        else
+            DoThaw();
+    }
+
     return true;
 }
 
 bool
 wxWindowMSW::MSWShowWithEffect(bool show,
                                wxShowEffect effect,
-                               unsigned timeout,
-                               wxDirection dir)
+                               unsigned timeout)
 {
+    if ( !wxWindowBase::Show(show) )
+        return false;
+
     typedef BOOL (WINAPI *AnimateWindow_t)(HWND, DWORD, DWORD);
 
     static AnimateWindow_t s_pfnAnimateWindow = NULL;
@@ -743,22 +755,50 @@ wxWindowMSW::MSWShowWithEffect(bool show,
     if ( !s_pfnAnimateWindow )
         return Show(show);
 
+    // Show() has a side effect of sending a WM_SIZE to the window, which helps
+    // ensuring that it's laid out correctly, but AnimateWindow() doesn't do
+    // this so send the event ourselves
+    SendSizeEvent();
+
     // prepare to use AnimateWindow()
 
     if ( !timeout )
         timeout = 200; // this is the default animation timeout, per MSDN
 
     DWORD dwFlags = show ? 0 : AW_HIDE;
-    bool needsDir = false;
+
     switch ( effect )
     {
-        case wxSHOW_EFFECT_ROLL:
-            needsDir = true;
+        case wxSHOW_EFFECT_ROLL_TO_LEFT:
+            dwFlags |= AW_HOR_NEGATIVE;
             break;
 
-        case wxSHOW_EFFECT_SLIDE:
-            needsDir = true;
-            dwFlags |= AW_SLIDE;
+        case wxSHOW_EFFECT_ROLL_TO_RIGHT:
+            dwFlags |= AW_HOR_POSITIVE;
+            break;
+
+        case wxSHOW_EFFECT_ROLL_TO_TOP:
+            dwFlags |= AW_VER_NEGATIVE;
+            break;
+
+        case wxSHOW_EFFECT_ROLL_TO_BOTTOM:
+            dwFlags |= AW_VER_POSITIVE;
+            break;
+
+        case wxSHOW_EFFECT_SLIDE_TO_LEFT:
+            dwFlags |= AW_SLIDE | AW_HOR_NEGATIVE;
+            break;
+
+        case wxSHOW_EFFECT_SLIDE_TO_RIGHT:
+            dwFlags |= AW_SLIDE | AW_HOR_POSITIVE;
+            break;
+
+        case wxSHOW_EFFECT_SLIDE_TO_TOP:
+            dwFlags |= AW_SLIDE | AW_VER_NEGATIVE;
+            break;
+
+        case wxSHOW_EFFECT_SLIDE_TO_BOTTOM:
+            dwFlags |= AW_SLIDE | AW_VER_POSITIVE;
             break;
 
         case wxSHOW_EFFECT_BLEND:
@@ -779,38 +819,6 @@ wxWindowMSW::MSWShowWithEffect(bool show,
             return false;
     }
 
-    if ( needsDir )
-    {
-        switch ( dir )
-        {
-            case wxTOP:
-                dwFlags |= AW_VER_NEGATIVE;
-                break;
-
-            case wxBOTTOM:
-                dwFlags |= AW_VER_POSITIVE;
-                break;
-
-            case wxLEFT:
-                dwFlags |= AW_HOR_NEGATIVE;
-                break;
-
-            case wxRIGHT:
-                dwFlags |= AW_HOR_POSITIVE;
-                break;
-
-            default:
-                wxFAIL_MSG( _T("unknown window effect direction") );
-                return false;
-        }
-    }
-    else // animation effect which doesn't need the direction
-    {
-        wxASSERT_MSG( dir == wxBOTTOM,
-                        _T("non-default direction used unnecessarily") );
-    }
-
-
     if ( !(*s_pfnAnimateWindow)(GetHwnd(), timeout, dwFlags) )
     {
         wxLogLastError(_T("AnimateWindow"));
@@ -868,7 +876,11 @@ bool wxWindowMSW::SetFont(const wxFont& font)
     HWND hWnd = GetHwnd();
     if ( hWnd != 0 )
     {
-        WXHANDLE hFont = m_font.GetResourceHandle();
+        // note the use of GetFont() instead of m_font: our own font could have
+        // just been reset and in this case we need to change the font used by
+        // the native window to the default for this class, i.e. exactly what
+        // GetFont() returns
+        WXHANDLE hFont = GetFont().GetResourceHandle();
 
         wxASSERT_MSG( hFont, wxT("should have valid font") );
 
@@ -1130,10 +1142,10 @@ void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
 #ifdef __WXWINCE__
     wxUnusedVar(dir);
 #else
-    const HWND hwnd = GetHwnd();
-    wxCHECK_RET( hwnd, _T("layout direction must be set after window creation") );
+    wxCHECK_RET( GetHwnd(),
+                 _T("layout direction must be set after window creation") );
 
-    LONG styleOld = ::GetWindowLong(hwnd, GWL_EXSTYLE);
+    LONG styleOld = wxGetWindowExStyle(this);
 
     LONG styleNew = styleOld;
     switch ( dir )
@@ -1153,7 +1165,7 @@ void wxWindowMSW::SetLayoutDirection(wxLayoutDirection dir)
 
     if ( styleNew != styleOld )
     {
-        ::SetWindowLong(hwnd, GWL_EXSTYLE, styleNew);
+        wxSetWindowExStyle(this, styleNew);
     }
 #endif
 }
@@ -1163,12 +1175,10 @@ wxLayoutDirection wxWindowMSW::GetLayoutDirection() const
 #ifdef __WXWINCE__
     return wxLayout_Default;
 #else
-    const HWND hwnd = GetHwnd();
-    wxCHECK_MSG( hwnd, wxLayout_Default, _T("invalid window") );
+    wxCHECK_MSG( GetHwnd(), wxLayout_Default, _T("invalid window") );
 
-    return ::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL
-                ? wxLayout_RightToLeft
-                : wxLayout_LeftToRight;
+    return wxHasWindowExStyle(this, WS_EX_LAYOUTRTL) ? wxLayout_RightToLeft
+                                                     : wxLayout_LeftToRight;
 #endif
 }
 
@@ -1267,36 +1277,12 @@ void wxWindowMSW::DissociateHandle()
 bool wxCheckWindowWndProc(WXHWND hWnd,
                           WXFARPROC WXUNUSED(wndProc))
 {
-// TODO: This list of window class names should be factored out so they can be
-// managed in one place and then accessed from here and other places, such as
-// wxApp::RegisterWindowClasses() and wxApp::UnregisterWindowClasses()
+    const wxString str(wxGetWindowClass(hWnd));
 
-#ifdef __WXWINCE__
-    extern       wxChar *wxCanvasClassName;
-    extern       wxChar *wxCanvasClassNameNR;
-#else
-    extern const wxChar *wxCanvasClassName;
-    extern const wxChar *wxCanvasClassNameNR;
-#endif
-    extern const wxChar *wxMDIFrameClassName;
-    extern const wxChar *wxMDIFrameClassNameNoRedraw;
-    extern const wxChar *wxMDIChildFrameClassName;
-    extern const wxChar *wxMDIChildFrameClassNameNoRedraw;
-    wxString str(wxGetWindowClass(hWnd));
-    if (str == wxCanvasClassName ||
-        str == wxCanvasClassNameNR ||
-#if wxUSE_GLCANVAS
-        str == _T("wxGLCanvasClass") ||
-        str == _T("wxGLCanvasClassNR") ||
-#endif // wxUSE_GLCANVAS
-        str == wxMDIFrameClassName ||
-        str == wxMDIFrameClassNameNoRedraw ||
-        str == wxMDIChildFrameClassName ||
-        str == wxMDIChildFrameClassNameNoRedraw ||
-        str == _T("wxTLWHiddenParent"))
-        return true; // Effectively means don't subclass
-    else
-        return false;
+    // TODO: get rid of wxTLWHiddenParent special case (currently it's not
+    //       registered by wxApp but using ad hoc code in msw/toplevel.cpp);
+    //       there is also a hidden window class used by sockets &c
+    return wxApp::IsRegisteredClassName(str) || str == _T("wxTLWHiddenParent");
 }
 
 // ----------------------------------------------------------------------------
@@ -1379,14 +1365,14 @@ void wxWindowMSW::MSWUpdateStyle(long flagsOld, long exflagsOld)
     }
 
     // and the extended style
-    long exstyleReal = ::GetWindowLong(GetHwnd(), GWL_EXSTYLE);
+    long exstyleReal = wxGetWindowExStyle(this);
 
     if ( exstyle != exstyleOld )
     {
         exstyleReal &= ~exstyleOld;
         exstyleReal |= exstyle;
 
-        ::SetWindowLong(GetHwnd(), GWL_EXSTYLE, exstyleReal);
+        wxSetWindowExStyle(this, exstyleReal);
 
         // ex style changes don't take effect without calling SetWindowPos
         callSWP = true;
@@ -1594,7 +1580,7 @@ bool wxWindowMSW::Reparent(wxWindowBase *parent)
     ::SetParent(hWndChild, hWndParent);
 
 #ifndef __WXWINCE__
-    if ( ::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT )
+    if ( wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) )
     {
         EnsureParentHasControlParentStyle(GetParent());
     }
@@ -1612,20 +1598,22 @@ static inline void SendSetRedraw(HWND hwnd, bool on)
 
 void wxWindowMSW::DoFreeze()
 {
-    if ( IsShown() )
-        SendSetRedraw(GetHwnd(), false);
+    if ( !IsShown() )
+        return; // no point in freezing hidden window
+
+    SendSetRedraw(GetHwnd(), false);
 }
 
 void wxWindowMSW::DoThaw()
 {
-    if ( IsShown() )
-    {
-        SendSetRedraw(GetHwnd(), true);
+    if ( !IsShown() )
+        return; // hidden windows aren't frozen by DoFreeze
 
-        // we need to refresh everything or otherwise the invalidated area
-        // is not going to be repainted
-        Refresh();
-    }
+    SendSetRedraw(GetHwnd(), true);
+
+    // we need to refresh everything or otherwise the invalidated area
+    // is not going to be repainted
+    Refresh();
 }
 
 void wxWindowMSW::Refresh(bool eraseBack, const wxRect *rect)
@@ -1976,6 +1964,11 @@ void wxWindowMSW::DoMoveWindow(int x, int y, int width, int height)
 #if USE_DEFERRED_SIZING
         m_pendingPosition = wxPoint(x, y);
         m_pendingSize = wxSize(width, height);
+    }
+    else // window was moved immediately, without deferring it
+    {
+        m_pendingPosition = wxDefaultPosition;
+        m_pendingSize = wxDefaultSize;
 #endif // USE_DEFERRED_SIZING
     }
 }
@@ -2536,8 +2529,7 @@ bool wxWindowMSW::MSWShouldPreProcessMessage(WXMSG* msg)
         {
             wxWindow * const win = node->GetData();
             if ( win->CanAcceptFocus() &&
-                    !(::GetWindowLong(GetHwndOf(win), GWL_EXSTYLE) &
-                        WS_EX_CONTROLPARENT) )
+                    !wxHasWindowExStyle(win, WS_EX_CONTROLPARENT) )
             {
                 // it shouldn't hang...
                 canSafelyCallIsDlgMsg = true;
@@ -3408,12 +3400,12 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l
                     rc.result = MSWDefWindowProc(message, wParam, lParam);
                     processed = true;
 
-                    // now alter the client size making room for drawing a themed border
-                    NCCALCSIZE_PARAMS *csparam = NULL;
+                    // now alter the client size making room for drawing a
+                    // themed border
                     RECT *rect;
                     if ( wParam )
                     {
-                        csparam = (NCCALCSIZE_PARAMS *)lParam;
+                        NCCALCSIZE_PARAMS *csparam = (NCCALCSIZE_PARAMS *)lParam;
                         rect = &csparam->rgrc[0];
                     }
                     else
@@ -3664,6 +3656,17 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
                             WXDWORD style,
                             WXDWORD extendedStyle)
 {
+    // check a common bug in the user code: if the window is created with a
+    // non-default ctor and Create() is called too, we'd create 2 HWND for a
+    // single wxWindow object and this results in all sorts of trouble,
+    // especially for wxTLWs
+    wxCHECK_MSG( !m_hWnd, true, "window can't be recreated" );
+
+    // this can happen if this function is called using the return value of
+    // wxApp::GetRegisteredClassName() which failed
+    wxCHECK_MSG( wclass, false, "failed to register window class?" );
+
+
     // choose the position/size for the new window
     int x, y, w, h;
     (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
@@ -3678,7 +3681,7 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     wxString className(wclass);
     if ( !HasFlag(wxFULL_REPAINT_ON_RESIZE) )
     {
-        className += wxT("NR");
+        className += wxApp::GetNoRedrawClassSuffix();
     }
 
     // do create the window
@@ -3829,8 +3832,7 @@ bool wxWindowMSW::HandleTooltipNotify(WXUINT code,
         // if we got TTN_NEEDTEXTW in Unicode build: in this case we just have
         // to copy the string we have into the buffer
         static wxChar buf[513];
-        wxStrncpy(buf, ttip.c_str(), WXSIZEOF(buf) - 1);
-        buf[WXSIZEOF(buf) - 1] = _T('\0');
+        wxStrlcpy(buf, ttip.c_str(), WXSIZEOF(buf));
         ttText->lpszText = buf;
     }
 
@@ -3903,7 +3905,7 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
     wxCloseEvent event(wxEVT_END_SESSION, wxID_ANY);
     event.SetEventObject(wxTheApp);
     event.SetCanVeto(false);
-    event.SetLoggingOff( (logOff == (long)ENDSESSION_LOGOFF) );
+    event.SetLoggingOff((logOff & ENDSESSION_LOGOFF) != 0);
 
     return wxTheApp->ProcessEvent(event);
 #else
@@ -4086,7 +4088,6 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
         ::DragQueryFile(hFilesInfo, wIndex,
                         wxStringBuffer(files[wIndex], len), len);
     }
-    DragFinish (hFilesInfo);
 
     wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
     event.SetEventObject(this);
@@ -4096,6 +4097,8 @@ bool wxWindowMSW::HandleDropFiles(WXWPARAM wParam)
     event.m_pos.x = dropPoint.x;
     event.m_pos.y = dropPoint.y;
 
+    DragFinish(hFilesInfo);
+
     return HandleWindowEvent(event);
 #endif
 }
@@ -4205,9 +4208,6 @@ bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
             break;
 
         case PBT_APMRESUMESUSPEND:
-#ifdef PBT_APMRESUMEAUTOMATIC
-        case PBT_APMRESUMEAUTOMATIC:
-#endif
             evtType = wxEVT_POWER_RESUME;
             break;
 
@@ -4224,6 +4224,9 @@ bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
         case PBT_APMPOWERSTATUSCHANGE:
         case PBT_APMOEMEVENT:
         case PBT_APMRESUMECRITICAL:
+#ifdef PBT_APMRESUMEAUTOMATIC
+        case PBT_APMRESUMEAUTOMATIC:
+#endif
             evtType = wxEVT_NULL;
             break;
     }
@@ -4246,17 +4249,33 @@ bool wxWindowMSW::HandlePower(WXWPARAM WXUNUSED_IN_WINCE(wParam),
 
 bool wxWindowMSW::IsDoubleBuffered() const
 {
-    for ( const wxWindowMSW *wnd = this;
-          wnd && !wnd->IsTopLevel(); wnd =
-          wnd->GetParent() )
+    for ( const wxWindowMSW *win = this; win; win = win->GetParent() )
     {
-        if ( ::GetWindowLong(GetHwndOf(wnd), GWL_EXSTYLE) & WS_EX_COMPOSITED )
+        if ( wxHasWindowExStyle(win, WS_EX_COMPOSITED) )
             return true;
+
+        if ( win->IsTopLevel() )
+            break;
     }
 
     return false;
 }
 
+void wxWindowMSW::SetDoubleBuffered(bool on)
+{
+    // Get the current extended style bits
+    long exstyle = wxGetWindowExStyle(this);
+
+    // Twiddle the bit as needed
+    if ( on )
+        exstyle |= WS_EX_COMPOSITED;
+    else
+        exstyle &= ~WS_EX_COMPOSITED;
+
+    // put it back
+    wxSetWindowExStyle(this, exstyle);
+}
+
 // ---------------------------------------------------------------------------
 // owner drawn stuff
 // ---------------------------------------------------------------------------
@@ -5067,12 +5086,8 @@ bool wxWindowMSW::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control)
     // coming from a control to wxEVT_COMMAND_MENU_SELECTED
     if ( !control )
     {
-        // If no child window, it may be an accelerator, e.g. for a popup menu
-        // command
-
-        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
+        wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, id);
         event.SetEventObject(this);
-        event.SetId(id);
         event.SetInt(id);
 
         return HandleWindowEvent(event);
@@ -5273,20 +5288,23 @@ bool wxWindowMSW::HandleMouseMove(int x, int y, WXUINT flags)
             static bool s_initDone = false;
             if ( !s_initDone )
             {
-                wxLogNull noLog;
-
-                wxDynamicLibrary dllComCtl32(_T("comctl32.dll"), wxDL_VERBATIM);
+                // see comment in wxApp::GetComCtl32Version() explaining the
+                // use of wxDL_GET_LOADED
+                wxDynamicLibrary dllComCtl32(_T("comctl32.dll"),
+                                             wxDL_VERBATIM |
+                                             wxDL_QUIET |
+                                             wxDL_GET_LOADED);
                 if ( dllComCtl32.IsLoaded() )
                 {
                     s_pfn_TrackMouseEvent = (_TrackMouseEvent_t)
-                        dllComCtl32.GetSymbol(_T("_TrackMouseEvent"));
+                        dllComCtl32.RawGetSymbol(_T("_TrackMouseEvent"));
                 }
 
                 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
+                // we shouldn't unload comctl32.dll here as we didn't really
+                // load it above
+                dllComCtl32.Detach();
             }
 
             if ( s_pfn_TrackMouseEvent )
@@ -5609,18 +5627,19 @@ int wxWindowMSW::HandleMenuChar(int WXUNUSED_IN_WINCE(chAccel),
     return wxNOT_FOUND;
 }
 
-bool wxWindowMSW::HandleClipboardEvent( WXUINT nMsg )
+#endif // wxUSE_MENUS
+
+bool wxWindowMSW::HandleClipboardEvent(WXUINT nMsg)
 {
-    const wxEventType type = ( nMsg == WM_CUT ) ? wxEVT_COMMAND_TEXT_CUT :
-                             ( nMsg == WM_COPY ) ? wxEVT_COMMAND_TEXT_COPY :
-                           /*( nMsg == WM_PASTE ) ? */ wxEVT_COMMAND_TEXT_PASTE;
+    const wxEventType type = nMsg == WM_CUT       ? wxEVT_COMMAND_TEXT_CUT
+                           : nMsg == WM_COPY      ? wxEVT_COMMAND_TEXT_COPY
+                           : /* nMsg == WM_PASTE */ wxEVT_COMMAND_TEXT_PASTE;
     wxClipboardTextEvent evt(type, GetId());
 
     evt.SetEventObject(this);
 
     return HandleWindowEvent(evt);
 }
-#endif // wxUSE_MENUS
 
 // ---------------------------------------------------------------------------
 // joystick