/***************************************************************** * ShowCaret (USER32.@) */ BOOL WINAPI ShowCaret( HWND hwnd ) { BOOL ret; RECT r; int hidden = 0; SERVER_START_REQ( set_caret_info ) { req->flags = SET_CARET_HIDE|SET_CARET_STATE; req->handle = wine_server_user_handle( hwnd ); req->x = 0; req->y = 0; req->hide = -1; req->state = 1; if ((ret = !wine_server_call_err( req ))) { hwnd = wine_server_ptr_handle( reply->full_handle ); r.left = reply->old_rect.left; r.top = reply->old_rect.top; r.right = reply->old_rect.right; r.bottom = reply->old_rect.bottom; hidden = reply->old_hide; } } SERVER_END_REQ; if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */ { CARET_DisplayCaret( hwnd, &r ); SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback ); } return ret; }
/***************************************************************** * SetCaretPos (USER32.@) */ BOOL WINAPI SetCaretPos( INT x, INT y ) { BOOL ret; HWND hwnd = 0; RECT r; int old_state = 0; int hidden = 0; SERVER_START_REQ( set_caret_info ) { req->flags = SET_CARET_POS|SET_CARET_STATE; req->handle = 0; req->x = x; req->y = y; req->hide = 0; req->state = 1; if ((ret = !wine_server_call_err( req ))) { hwnd = wine_server_ptr_handle( reply->full_handle ); r.left = reply->old_rect.left; r.top = reply->old_rect.top; r.right = reply->old_rect.right; r.bottom = reply->old_rect.bottom; old_state = reply->old_state; hidden = reply->old_hide; } } SERVER_END_REQ; if (ret && !hidden && (x != r.left || y != r.top)) { if (old_state) CARET_DisplayCaret( hwnd, &r ); r.right += x - r.left; r.bottom += y - r.top; r.left = x; r.top = y; CARET_DisplayCaret( hwnd, &r ); USER_Driver->pUpdateCandidatePos( hwnd, &r ); SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback ); } return ret; }
BOOL WINAPI TrackMouseEvent (TRACKMOUSEEVENT *ptme) { HWND hwnd; POINT pos; DWORD hover_time; INT hittest; TRACE("%x, %x, %p, %u\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime); if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) { WARN("wrong TRACKMOUSEEVENT size from app\n"); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */ if (ptme->dwFlags & TME_QUERY ) { *ptme = tracking_info.tme; /* set cbSize in the case it's not initialized yet */ ptme->cbSize = sizeof(TRACKMOUSEEVENT); return TRUE; /* return here, TME_QUERY is retrieving information */ } if (!IsWindow(ptme->hwndTrack)) { SetLastError(ERROR_INVALID_WINDOW_HANDLE); return FALSE; } hover_time = ptme->dwHoverTime; /* if HOVER_DEFAULT was specified replace this with the systems current value. * TME_LEAVE doesn't need to specify hover time so use default */ if (hover_time == HOVER_DEFAULT || hover_time == 0 || !(ptme->dwHoverTime&TME_HOVER)) SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hover_time, 0); GetCursorPos(&pos); hwnd = WINPOS_WindowFromPoint(ptme->hwndTrack, pos, &hittest); TRACE("point %s hwnd %p hittest %d\n", wine_dbgstr_point(&pos), hwnd, hittest); if (ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT)) FIXME("Unknown flag(s) %08x\n", ptme->dwFlags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_NONCLIENT)); if (ptme->dwFlags & TME_CANCEL) { if (tracking_info.tme.hwndTrack == ptme->hwndTrack) { tracking_info.tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL); /* if we aren't tracking on hover or leave remove this entry */ if (!(tracking_info.tme.dwFlags & (TME_HOVER | TME_LEAVE))) { KillSystemTimer(tracking_info.tme.hwndTrack, timer); timer = 0; tracking_info.tme.hwndTrack = 0; tracking_info.tme.dwFlags = 0; tracking_info.tme.dwHoverTime = 0; } } } else { /* In our implementation it's possible that another window will receive a * WM_MOUSEMOVE and call TrackMouseEvent before TrackMouseEventProc is * called. In such a situation post the WM_MOUSELEAVE now */ if (tracking_info.tme.dwFlags & TME_LEAVE && tracking_info.tme.hwndTrack != NULL) check_mouse_leave(hwnd, hittest); if (timer) { KillSystemTimer(tracking_info.tme.hwndTrack, timer); timer = 0; tracking_info.tme.hwndTrack = 0; tracking_info.tme.dwFlags = 0; tracking_info.tme.dwHoverTime = 0; } if (ptme->hwndTrack == hwnd) { /* Adding new mouse event to the tracking list */ tracking_info.tme = *ptme; tracking_info.tme.dwHoverTime = hover_time; /* Initialize HoverInfo variables even if not hover tracking */ tracking_info.pos = pos; timer = SetSystemTimer(tracking_info.tme.hwndTrack, (UINT_PTR)&tracking_info.tme, hover_time, TrackMouseEventProc); } } return TRUE; }
static void SCROLL_HandleScrollEvent( HWND hwnd, INT nBar, UINT msg, POINT pt) { /* Previous mouse position for timer events */ static POINT prevPt; /* Thumb position when tracking started. */ static UINT trackThumbPos; /* Position in the scroll-bar of the last button-down event. */ static INT lastClickPos; /* Position in the scroll-bar of the last mouse event. */ static INT lastMousePos; enum SCROLL_HITTEST hittest; HWND hwndOwner, hwndCtl; BOOL vertical; SCROLLINFO si; SCROLLBARINFO sbi; DRAW_CONTEXT context; si.cbSize = sizeof(si); sbi.cbSize = sizeof(sbi); si.fMask = SIF_ALL; GetScrollInfo(hwnd, nBar, &si); GetScrollBarInfo(hwnd, SCROLL_getObjectId(nBar), &sbi); vertical = SCROLL_IsVertical(hwnd, nBar); if(sbi.rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE && sbi.rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE ) { return; } ThemeInitDrawContext(&context, hwnd, 0); #ifndef ROS_SUCKS /* The scrollbar rect is in screen coordinates */ // OffsetRect(&sbi.rcScrollBar, -context.wi.rcWindow.left, -context.wi.rcWindow.top); #endif if ((SCROLL_trackHitTest == SCROLL_NOWHERE) && (msg != WM_LBUTTONDOWN)) return; hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd) : hwnd; hwndCtl = (nBar == SB_CTL) ? hwnd : 0; switch(msg) { case WM_LBUTTONDOWN: /* Initialise mouse tracking */ HideCaret(hwnd); /* hide caret while holding down LBUTTON */ SCROLL_trackVertical = vertical; SCROLL_trackHitTest = hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE ); lastClickPos = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left); lastMousePos = lastClickPos; trackThumbPos = sbi.xyThumbTop; prevPt = pt; SetCapture( hwnd ); break; case WM_MOUSEMOVE: hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, TRUE ); prevPt = pt; break; case WM_LBUTTONUP: hittest = SCROLL_NOWHERE; ReleaseCapture(); /* if scrollbar has focus, show back caret */ if (hwnd==GetFocus()) ShowCaret(hwnd); break; case WM_SYSTIMER: pt = prevPt; hittest = SCROLL_HitTest( hwnd, &sbi, vertical, pt, FALSE ); break; default: return; /* Should never happen */ } //TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n", // hwnd, nBar, SPY_GetMsgName(msg,hwnd), pt.x, pt.y, hittest ); switch(SCROLL_trackHitTest) { case SCROLL_NOWHERE: /* No tracking in progress */ break; case SCROLL_TOP_ARROW: if (hittest == SCROLL_trackHitTest) { SCROLL_DrawArrows( &context, &sbi, vertical, SCROLL_trackHitTest, 0 ); if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) { SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEUP, (LPARAM)hwndCtl ); } SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); } else { SCROLL_DrawArrows( &context, &sbi, vertical, 0, 0 ); KillSystemTimer( hwnd, SCROLL_TIMER ); } break; case SCROLL_TOP_RECT: SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0); if (hittest == SCROLL_trackHitTest) { if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) { SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEUP, (LPARAM)hwndCtl ); } SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); } else KillSystemTimer( hwnd, SCROLL_TIMER ); break; case SCROLL_THUMB: if (msg == WM_LBUTTONDOWN) { SCROLL_TrackingWin = hwnd; SCROLL_TrackingBar = nBar; SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos; SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical, SCROLL_TrackingPos ); if (!SCROLL_MovingThumb) SCROLL_DrawMovingThumb(&context, &sbi, vertical); } else if (msg == WM_LBUTTONUP) { if (SCROLL_MovingThumb) SCROLL_DrawMovingThumb(&context, &sbi, vertical); SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, 0, SCROLL_trackHitTest ); } else /* WM_MOUSEMOVE */ { INT pos; if (!SCROLL_PtInRectEx( &sbi.rcScrollBar, pt, vertical )) pos = lastClickPos; else { pt = SCROLL_ClipPos( &sbi.rcScrollBar, pt ); pos = vertical ? (pt.y - sbi.rcScrollBar.top) : (pt.x - sbi.rcScrollBar.left); } if ( (pos != lastMousePos) || (!SCROLL_MovingThumb) ) { if (SCROLL_MovingThumb) SCROLL_DrawMovingThumb( &context, &sbi, vertical); lastMousePos = pos; SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos; SCROLL_TrackingVal = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical, SCROLL_TrackingPos ); SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal), (LPARAM)hwndCtl ); if (!SCROLL_MovingThumb) SCROLL_DrawMovingThumb( &context, &sbi, vertical); } } break; case SCROLL_BOTTOM_RECT: if (hittest == SCROLL_trackHitTest) { SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, SCROLL_trackHitTest, 0 ); if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) { SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEDOWN, (LPARAM)hwndCtl ); } SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); } else { SCROLL_DrawInterior( &context, &sbi, sbi.xyThumbTop, vertical, 0, 0 ); KillSystemTimer( hwnd, SCROLL_TIMER ); } break; case SCROLL_BOTTOM_ARROW: if (hittest == SCROLL_trackHitTest) { SCROLL_DrawArrows( &context, &sbi, vertical, SCROLL_trackHitTest, 0 ); if ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)) { SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEDOWN, (LPARAM)hwndCtl ); } SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, NULL ); } else { SCROLL_DrawArrows( &context, &sbi, vertical, 0, 0 ); KillSystemTimer( hwnd, SCROLL_TIMER ); } break; } if (msg == WM_LBUTTONDOWN) { if (hittest == SCROLL_THUMB) { UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical, trackThumbPos + lastMousePos - lastClickPos ); SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM( SB_THUMBTRACK, val ), (LPARAM)hwndCtl ); } } if (msg == WM_LBUTTONUP) { hittest = SCROLL_trackHitTest; SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */ if (hittest == SCROLL_THUMB) { UINT val = SCROLL_GetThumbVal( &si, &sbi.rcScrollBar, vertical, trackThumbPos + lastMousePos - lastClickPos ); SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM( SB_THUMBPOSITION, val ), (LPARAM)hwndCtl ); } /* SB_ENDSCROLL doesn't report thumb position */ SendMessageW( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL, SB_ENDSCROLL, (LPARAM)hwndCtl ); /* Terminate tracking */ SCROLL_TrackingWin = 0; } ThemeCleanupDrawContext(&context); }
/*********************************************************************** * IntScrollHandleScrollEvent * * Handle a mouse or timer event for the scrollbar. * 'Pt' is the location of the mouse event in drawing coordinates */ static VOID FASTCALL IntScrollHandleScrollEvent(HWND Wnd, INT SBType, UINT Msg, POINT Pt) { static POINT PrevPt; /* Previous mouse position for timer events */ static UINT TrackThumbPos; /* Thumb position when tracking started. */ static INT LastClickPos; /* Position in the scroll-bar of the last button-down event. */ static INT LastMousePos; /* Position in the scroll-bar of the last mouse event. */ DWORD HitTest; HWND WndOwner, WndCtl; BOOL Vertical; HDC Dc; SCROLLBARINFO ScrollBarInfo; SETSCROLLBARINFO NewInfo; if (! IntGetScrollBarInfo(Wnd, SBType, &ScrollBarInfo)) { return; } if (SCROLL_NOWHERE == ScrollTrackHitTest && WM_LBUTTONDOWN != Msg) { return; } NewInfo.nTrackPos = ScrollTrackingVal; NewInfo.reserved = ScrollBarInfo.reserved; memcpy(NewInfo.rgstate, ScrollBarInfo.rgstate, (CCHILDREN_SCROLLBAR + 1) * sizeof(DWORD)); if (SB_CTL == SBType && 0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & (SBS_SIZEGRIP | SBS_SIZEBOX))) { switch(Msg) { case WM_LBUTTONDOWN: /* Initialise mouse tracking */ HideCaret(Wnd); /* hide caret while holding down LBUTTON */ SetCapture(Wnd); PrevPt = Pt; ScrollTrackHitTest = HitTest = SCROLL_THUMB; break; case WM_MOUSEMOVE: GetClientRect(GetParent(GetParent(Wnd)), &ScrollBarInfo.rcScrollBar); PrevPt = Pt; break; case WM_LBUTTONUP: ReleaseCapture(); ScrollTrackHitTest = HitTest = SCROLL_NOWHERE; if (Wnd == GetFocus()) { ShowCaret(Wnd); } break; case WM_SYSTIMER: Pt = PrevPt; break; } return; } Dc = GetDCEx(Wnd, 0, DCX_CACHE | ((SB_CTL == SBType) ? 0 : DCX_WINDOW)); if (SB_VERT == SBType) { Vertical = TRUE; } else if (SB_HORZ == SBType) { Vertical = FALSE; } else { Vertical = (0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & SBS_VERT)); } WndOwner = (SB_CTL == SBType) ? GetParent(Wnd) : Wnd; WndCtl = (SB_CTL == SBType) ? Wnd : NULL; switch (Msg) { case WM_LBUTTONDOWN: /* Initialise mouse tracking */ HideCaret(Wnd); /* hide caret while holding down LBUTTON */ ScrollTrackVertical = Vertical; ScrollTrackHitTest = HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, FALSE ); LastClickPos = Vertical ? (Pt.y - ScrollBarInfo.rcScrollBar.top) : (Pt.x - ScrollBarInfo.rcScrollBar.left); LastMousePos = LastClickPos; TrackThumbPos = ScrollBarInfo.xyThumbTop; PrevPt = Pt; if (SB_CTL == SBType && 0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & WS_TABSTOP)) { SetFocus(Wnd); } SetCapture(Wnd); ScrollBarInfo.rgstate[ScrollTrackHitTest] |= STATE_SYSTEM_PRESSED; NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); break; case WM_MOUSEMOVE: HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, TRUE); PrevPt = Pt; break; case WM_LBUTTONUP: HitTest = SCROLL_NOWHERE; ReleaseCapture(); /* if scrollbar has focus, show back caret */ if (Wnd == GetFocus()) { ShowCaret(Wnd); } ScrollBarInfo.rgstate[ScrollTrackHitTest] &= ~STATE_SYSTEM_PRESSED; NewInfo.rgstate[ScrollTrackHitTest] = ScrollBarInfo.rgstate[ScrollTrackHitTest]; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); break; case WM_SYSTIMER: Pt = PrevPt; HitTest = IntScrollHitTest(&ScrollBarInfo, Vertical, Pt, FALSE); break; default: return; /* Should never happen */ } switch (ScrollTrackHitTest) { case SCROLL_NOWHERE: /* No tracking in progress */ break; case SCROLL_TOP_ARROW: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEUP, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; case SCROLL_TOP_RECT: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEUP, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; case SCROLL_THUMB: if (WM_LBUTTONDOWN == Msg) { ScrollTrackingWin = Wnd; ScrollTrackingBar = SBType; ScrollTrackingPos = TrackThumbPos + LastMousePos - LastClickPos; ScrollTrackingVal = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, ScrollTrackingPos); NewInfo.nTrackPos = ScrollTrackingVal; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); IntScrollDrawMovingThumb(Dc, &ScrollBarInfo, Vertical); } else if (WM_LBUTTONUP == Msg) { ScrollTrackingWin = 0; ScrollTrackingVal = 0; IntDrawScrollInterior(Wnd, Dc, SBType, Vertical, &ScrollBarInfo); } else /* WM_MOUSEMOVE */ { UINT Pos; if (! IntScrollPtInRectEx(&ScrollBarInfo.rcScrollBar, Pt, Vertical)) { Pos = LastClickPos; } else { Pt = IntScrollClipPos(&ScrollBarInfo.rcScrollBar, Pt); Pos = Vertical ? (Pt.y - ScrollBarInfo.rcScrollBar.top) : (Pt.x - ScrollBarInfo.rcScrollBar.left); } if (Pos != LastMousePos || ! ScrollMovingThumb) { LastMousePos = Pos; ScrollTrackingPos = TrackThumbPos + Pos - LastClickPos; ScrollTrackingVal = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, ScrollTrackingPos); NewInfo.nTrackPos = ScrollTrackingVal; NtUserSetScrollBarInfo(Wnd, IntScrollGetObjectId(SBType), &NewInfo); IntScrollDrawMovingThumb(Dc, &ScrollBarInfo, Vertical); SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM(SB_THUMBTRACK, ScrollTrackingVal), (LPARAM) WndCtl); } } break; case SCROLL_BOTTOM_RECT: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_PAGEDOWN, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; case SCROLL_BOTTOM_ARROW: if (HitTest == ScrollTrackHitTest) { if ((WM_LBUTTONDOWN == Msg) || (WM_SYSTIMER == Msg)) { SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_LINEDOWN, (LPARAM) WndCtl); } SetSystemTimer(Wnd, SCROLL_TIMER, (WM_LBUTTONDOWN == Msg) ? SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY, (TIMERPROC) NULL); } else { KillSystemTimer(Wnd, SCROLL_TIMER); } break; } if (WM_LBUTTONDOWN == Msg) { if (SCROLL_THUMB == HitTest) { UINT Val = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, TrackThumbPos + LastMousePos - LastClickPos); SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM(SB_THUMBTRACK, Val), (LPARAM) WndCtl); } } if (WM_LBUTTONUP == Msg) { HitTest = ScrollTrackHitTest; ScrollTrackHitTest = SCROLL_NOWHERE; /* Terminate tracking */ if (SCROLL_THUMB == HitTest) { UINT Val = IntScrollGetThumbVal(Wnd, SBType, &ScrollBarInfo, Vertical, TrackThumbPos + LastMousePos - LastClickPos); SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, Val), (LPARAM) WndCtl); } SendMessageW(WndOwner, Vertical ? WM_VSCROLL : WM_HSCROLL, SB_ENDSCROLL, (LPARAM) WndCtl); } ReleaseDC(Wnd, Dc); }