[PATCH v3 5/5] uxtheme: Support scroll bar state tracking in non-client areas.

Zhiyi Zhang zzhang at codeweavers.com
Tue Jul 20 08:12:15 CDT 2021


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
v3: Supersede 209912. Fix a style inconsistency.

 dlls/user32/controls.h  |  3 +++
 dlls/user32/defwnd.c    | 11 +++++++++++
 dlls/user32/nonclient.c | 33 +++++++++++++++++++++++++++++++++
 dlls/user32/scroll.c    | 37 ++++++++++++++++++++++++++++++++++---
 4 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h
index bf32097f95c..2b3d405ae69 100644
--- a/dlls/user32/controls.h
+++ b/dlls/user32/controls.h
@@ -171,6 +171,8 @@ extern LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam ) DE
 extern LRESULT NC_HandleNCCalcSize( HWND hwnd, WPARAM wParam, RECT *winRect ) DECLSPEC_HIDDEN;
 extern LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN;
 extern LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
+extern LRESULT NC_HandleNCMouseMove( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN;
+extern LRESULT NC_HandleNCMouseLeave( HWND hwnd ) DECLSPEC_HIDDEN;
 extern LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
 extern LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam) DECLSPEC_HIDDEN;
 extern LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN;
@@ -184,6 +186,7 @@ extern void SCROLL_DrawNCScrollBar( HWND hwnd, HDC hdc, BOOL draw_horizontal, BO
 extern void SCROLL_DrawScrollBar( HWND hwnd, HDC hdc, INT nBar, enum SCROLL_HITTEST hit_test,
                                   const struct SCROLL_TRACKING_INFO *tracking_info, BOOL arrows,
                                   BOOL interior ) DECLSPEC_HIDDEN;
+extern void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt ) DECLSPEC_HIDDEN;
 extern void SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt ) DECLSPEC_HIDDEN;
 
 /* combo box */
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c
index a3d92e84aef..5eb056ebd9e 100644
--- a/dlls/user32/defwnd.c
+++ b/dlls/user32/defwnd.c
@@ -245,6 +245,17 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
     case WM_NCPAINT:
         return NC_HandleNCPaint( hwnd, (HRGN)wParam );
 
+    case WM_NCMOUSEMOVE:
+        {
+            POINT pt;
+            pt.x = (short)LOWORD(lParam);
+            pt.y = (short)HIWORD(lParam);
+            return NC_HandleNCMouseMove( hwnd, pt );
+        }
+
+    case WM_NCMOUSELEAVE:
+        return NC_HandleNCMouseLeave( hwnd );
+
     case WM_NCHITTEST:
         {
             POINT pt;
diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c
index 50ecb0c4e2e..02e6ad92320 100644
--- a/dlls/user32/nonclient.c
+++ b/dlls/user32/nonclient.c
@@ -635,6 +635,39 @@ LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt )
     return HTNOWHERE;
 }
 
+LRESULT NC_HandleNCMouseMove(HWND hwnd, POINT pt)
+{
+    LONG hittest;
+    RECT rect;
+
+    TRACE("hwnd=%p pt=%s\n", hwnd, wine_dbgstr_point(&pt));
+
+    hittest = NC_HandleNCHitTest(hwnd, pt);
+    if (hittest != HTHSCROLL && hittest != HTVSCROLL)
+        return 0;
+
+    WIN_GetRectangles(hwnd, COORDS_CLIENT, &rect, NULL);
+    ScreenToClient(hwnd, &pt);
+    pt.x -= rect.left;
+    pt.y -= rect.top;
+    SCROLL_HandleScrollEvent(hwnd, hittest == HTHSCROLL ? SB_HORZ : SB_VERT, WM_NCMOUSEMOVE, pt);
+    return 0;
+}
+
+LRESULT NC_HandleNCMouseLeave(HWND hwnd)
+{
+    LONG style = GetWindowLongW(hwnd, GWL_STYLE);
+    POINT pt = {0, 0};
+
+    TRACE("hwnd=%p\n", hwnd);
+
+    if (style & WS_HSCROLL)
+        SCROLL_HandleScrollEvent(hwnd, SB_HORZ, WM_NCMOUSELEAVE, pt);
+    if (style & WS_VSCROLL)
+        SCROLL_HandleScrollEvent(hwnd, SB_VERT, WM_NCMOUSELEAVE, pt);
+
+    return 0;
+}
 
 /******************************************************************************
  *
diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c
index c4c06476b9c..088e41eee43 100644
--- a/dlls/user32/scroll.c
+++ b/dlls/user32/scroll.c
@@ -751,7 +751,7 @@ static void SCROLL_HandleKbdEvent(HWND hwnd, WPARAM wParam, LPARAM lParam)
  * 'pt' is the location of the mouse event in client (for SB_CTL) or
  * windows coordinates.
  */
-static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt)
+void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt )
 {
       /* Previous mouse position for timer events */
     static POINT prevPt;
@@ -773,7 +773,8 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt)
     SCROLLBAR_INFO *infoPtr = SCROLL_GetInternalInfo( hwnd, nBar, FALSE );
     if (!infoPtr) return;
     if ((g_tracking_info.hit_test == SCROLL_NOWHERE)
-        && (msg != WM_LBUTTONDOWN && msg != WM_MOUSEMOVE && msg != WM_MOUSELEAVE))
+         && (msg != WM_LBUTTONDOWN && msg != WM_MOUSEMOVE && msg != WM_MOUSELEAVE
+         && msg != WM_NCMOUSEMOVE && msg != WM_NCMOUSELEAVE))
 		  return;
 
     if (nBar == SB_CTL && (GetWindowLongW( hwnd, GWL_STYLE ) & (SBS_SIZEGRIP | SBS_SIZEBOX)))
@@ -841,6 +842,32 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt)
 
           break;
 
+     case WM_NCMOUSEMOVE:
+          hittest = SCROLL_HitTest( hwnd, nBar, pt, vertical == g_tracking_info.vertical && GetCapture() == hwnd );
+          prevPt = pt;
+
+          if (nBar == SB_CTL)
+              break;
+
+          tme.cbSize = sizeof(tme);
+          tme.dwFlags = TME_QUERY;
+          TrackMouseEvent( &tme );
+          if (((tme.dwFlags & (TME_NONCLIENT | TME_LEAVE)) != (TME_NONCLIENT | TME_LEAVE)) || tme.hwndTrack != hwnd)
+          {
+              tme.dwFlags = TME_NONCLIENT | TME_LEAVE;
+              tme.hwndTrack = hwnd;
+              TrackMouseEvent( &tme );
+          }
+
+          break;
+
+      case WM_NCMOUSELEAVE:
+          if (nBar == SB_CTL)
+              return;
+
+          hittest = SCROLL_NOWHERE;
+          break;
+
       case WM_MOUSELEAVE:
           if (nBar != SB_CTL)
               return;
@@ -870,7 +897,7 @@ static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt)
     switch (g_tracking_info.hit_test)
     {
     case SCROLL_NOWHERE:  /* No tracking in progress */
-        if (msg == WM_MOUSEMOVE || msg == WM_MOUSELEAVE)
+        if (msg == WM_MOUSEMOVE || msg == WM_MOUSELEAVE || msg == WM_NCMOUSEMOVE || msg == WM_NCMOUSELEAVE)
             SCROLL_DrawScrollBar( hwnd, hdc, nBar, hittest, &g_tracking_info, TRUE, TRUE );
         break;
 
@@ -1049,6 +1076,8 @@ void SCROLL_TrackScrollBar( HWND hwnd, INT scrollbar, POINT pt )
         if (msg.message == WM_LBUTTONUP ||
             msg.message == WM_MOUSEMOVE ||
             msg.message == WM_MOUSELEAVE ||
+            msg.message == WM_NCMOUSEMOVE ||
+            msg.message == WM_NCMOUSELEAVE ||
             (msg.message == WM_SYSTIMER && msg.wParam == SCROLL_TIMER))
         {
             pt.x = (short)LOWORD(msg.lParam) - rect.left;
@@ -1383,6 +1412,8 @@ LRESULT WINAPI USER_ScrollBarProc( HWND hwnd, UINT message, WPARAM wParam, LPARA
 	}
         break;
     case WM_LBUTTONUP:
+    case WM_NCMOUSEMOVE:
+    case WM_NCMOUSELEAVE:
     case WM_MOUSEMOVE:
     case WM_MOUSELEAVE:
     case WM_SYSTIMER:
-- 
2.30.2



More information about the wine-devel mailing list