diff --git a/DDrawCompat/Input/Input.cpp b/DDrawCompat/Input/Input.cpp index 1d436fc..2f97713 100644 --- a/DDrawCompat/Input/Input.cpp +++ b/DDrawCompat/Input/Input.cpp @@ -67,20 +67,6 @@ namespace return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam); } - POINT getRelativeCursorPos() - { - auto captureWindow = Input::getCaptureWindow(); - const RECT rect = captureWindow->getRect(); - const int scaleFactor = captureWindow->getScaleFactor(); - - auto cp = g_cursorPos; - cp.x /= scaleFactor; - cp.y /= scaleFactor; - cp.x -= rect.left; - cp.y -= rect.top; - return cp; - } - LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { if (HC_ACTION == nCode && @@ -126,7 +112,7 @@ namespace DDraw::RealPrimarySurface::scheduleOverlayUpdate(); } - auto cp = getRelativeCursorPos(); + auto cp = Input::getRelativeCursorPos(); switch (wParam) { @@ -249,6 +235,25 @@ namespace Input return g_cursorWindow; } + POINT getRelativeCursorPos() + { + auto captureWindow = Input::getCaptureWindow(); + if (!captureWindow) + { + return {}; + } + + const RECT rect = captureWindow->getRect(); + const int scaleFactor = captureWindow->getScaleFactor(); + + auto cp = g_cursorPos; + cp.x /= scaleFactor; + cp.y /= scaleFactor; + cp.x -= rect.left; + cp.y -= rect.top; + return cp; + } + void installHooks() { g_bmpArrow = CALL_ORIG_FUNC(LoadImageA)(Dll::g_currentModule, "BMP_ARROW", IMAGE_BITMAP, 0, 0, 0); diff --git a/DDrawCompat/Input/Input.h b/DDrawCompat/Input/Input.h index 8462002..5140480 100644 --- a/DDrawCompat/Input/Input.h +++ b/DDrawCompat/Input/Input.h @@ -20,6 +20,7 @@ namespace Input Overlay::Window* getCaptureWindow(); POINT getCursorPos(); HWND getCursorWindow(); + POINT getRelativeCursorPos(); void installHooks(); void registerHotKey(const HotKey& hotKey, std::function action, void* context, bool onKeydown = true); void setCapture(Overlay::Control* control); diff --git a/DDrawCompat/Overlay/ScrollBarControl.cpp b/DDrawCompat/Overlay/ScrollBarControl.cpp index 12fd1cb..01ba93d 100644 --- a/DDrawCompat/Overlay/ScrollBarControl.cpp +++ b/DDrawCompat/Overlay/ScrollBarControl.cpp @@ -38,41 +38,57 @@ namespace Overlay RECT r = { m_leftArrow.right, m_rect.top, m_rightArrow.left, m_rect.bottom }; CALL_ORIG_FUNC(Rectangle)(dc, r.left - 1, r.top, r.right + 1, r.bottom); - const int thumbPos = (m_pos - m_min) * (r.right - r.left - ARROW_SIZE) / (m_max - m_min); - r = { m_leftArrow.right + thumbPos, r.top, m_leftArrow.right + thumbPos + ARROW_SIZE, r.bottom }; + r = getThumbRect(); SelectObject(dc, GetStockObject(DC_BRUSH)); CALL_ORIG_FUNC(Ellipse)(dc, r.left, r.top, r.right, r.bottom); SelectObject(dc, GetStockObject(NULL_BRUSH)); } + int ScrollBarControl::getPageSize() const + { + return std::max((m_max - m_min) / 20, 1); + } + + RECT ScrollBarControl::getThumbRect() const + { + const int thumbPos = (m_pos - m_min) * (m_rightArrow.left - m_leftArrow.right - ARROW_SIZE) / (m_max - m_min); + return RECT{ m_leftArrow.right + thumbPos, m_rect.top, m_leftArrow.right + thumbPos + ARROW_SIZE, m_rect.bottom }; + } + void ScrollBarControl::onLButtonDown(POINT pos) { Input::setCapture(this); + if (PtInRect(&m_leftArrow, pos)) { - setPos(m_pos - 1); - if (State::IDLE == m_state) - { - m_state = State::LEFT_ARROW_PRESSED; - startRepeatTimer(REPEAT_DELAY); - } + m_state = State::LEFT_ARROW_PRESSED; } else if (PtInRect(&m_rightArrow, pos)) { - setPos(m_pos + 1); - if (State::IDLE == m_state) - { - m_state = State::RIGHT_ARROW_PRESSED; - startRepeatTimer(REPEAT_DELAY); - } + m_state = State::RIGHT_ARROW_PRESSED; } else { - onThumbTrack(pos); - if (State::IDLE == m_state) + RECT r = getThumbRect(); + if (PtInRect(&r, pos)) { - m_state = State::THUMB_TRACKING; + m_state = State::THUMB_PRESSED; } + else if (pos.x < r.left) + { + m_state = State::LEFT_SHAFT_PRESSED; + } + else + { + m_state = State::RIGHT_SHAFT_PRESSED; + } + } + + scroll(); + + if (State::THUMB_PRESSED != m_state) + { + startRepeatTimer(REPEAT_DELAY); } } @@ -86,39 +102,19 @@ namespace Overlay } } - void ScrollBarControl::onMouseMove(POINT pos) + void ScrollBarControl::onMouseMove(POINT /*pos*/) { - if (State::THUMB_TRACKING == m_state) + if (State::THUMB_PRESSED == m_state) { - onThumbTrack(pos); + scroll(); } } void ScrollBarControl::onRepeat() { stopRepeatTimer(); - - switch (m_state) - { - case State::LEFT_ARROW_PRESSED: - setPos(m_pos - 1); - startRepeatTimer(REPEAT_INTERVAL); - break; - - case State::RIGHT_ARROW_PRESSED: - setPos(m_pos + 1); - startRepeatTimer(REPEAT_INTERVAL); - break; - } - } - - void ScrollBarControl::onThumbTrack(POINT pos) - { - const auto minPos = m_leftArrow.right + ARROW_SIZE / 2; - const auto maxPos = m_rightArrow.left - ARROW_SIZE / 2; - pos.x = std::max(pos.x, minPos); - pos.x = std::min(pos.x, maxPos); - setPos(m_min + roundDiv((pos.x - minPos) * (m_max - m_min), maxPos - minPos)); + scroll(); + startRepeatTimer(REPEAT_INTERVAL); } void CALLBACK ScrollBarControl::repeatTimerProc(HWND /*hwnd*/, UINT /*message*/, UINT_PTR /*iTimerID*/, DWORD /*dwTime*/) @@ -126,6 +122,45 @@ namespace Overlay static_cast(Input::getCapture())->onRepeat(); } + void ScrollBarControl::scroll() + { + switch (m_state) + { + case State::LEFT_ARROW_PRESSED: + setPos(m_pos - 1); + break; + + case State::RIGHT_ARROW_PRESSED: + setPos(m_pos + 1); + break; + + case State::LEFT_SHAFT_PRESSED: + if (Input::getRelativeCursorPos().x < getThumbRect().left) + { + setPos(m_pos - getPageSize()); + } + break; + + case State::RIGHT_SHAFT_PRESSED: + if (Input::getRelativeCursorPos().x >= getThumbRect().right) + { + setPos(m_pos + getPageSize()); + } + break; + + case State::THUMB_PRESSED: + { + POINT pos = Input::getRelativeCursorPos(); + const auto minPos = m_leftArrow.right + ARROW_SIZE / 2; + const auto maxPos = m_rightArrow.left - ARROW_SIZE / 2; + pos.x = std::max(pos.x, minPos); + pos.x = std::min(pos.x, maxPos); + setPos(m_min + roundDiv((pos.x - minPos) * (m_max - m_min), maxPos - minPos)); + break; + } + } + } + void ScrollBarControl::setPos(int pos) { pos = std::max(pos, m_min); diff --git a/DDrawCompat/Overlay/ScrollBarControl.h b/DDrawCompat/Overlay/ScrollBarControl.h index c10ab08..5b38cf7 100644 --- a/DDrawCompat/Overlay/ScrollBarControl.h +++ b/DDrawCompat/Overlay/ScrollBarControl.h @@ -18,26 +18,30 @@ namespace Overlay IDLE, LEFT_ARROW_PRESSED, RIGHT_ARROW_PRESSED, - THUMB_TRACKING, + LEFT_SHAFT_PRESSED, + RIGHT_SHAFT_PRESSED, + THUMB_PRESSED }; + virtual void draw(HDC dc) override; + virtual void onLButtonDown(POINT pos) override; + virtual void onLButtonUp(POINT pos) override; + virtual void onMouseMove(POINT pos) override; + + int getPageSize() const; + RECT getThumbRect() const; + void onRepeat(); + void scroll(); + + static void CALLBACK repeatTimerProc(HWND hwnd, UINT message, UINT_PTR iTimerID, DWORD dwTime); + static void startRepeatTimer(DWORD time); + static void stopRepeatTimer(); + int m_min; int m_max; int m_pos; RECT m_leftArrow; RECT m_rightArrow; State m_state; - - virtual void draw(HDC dc) override; - virtual void onLButtonDown(POINT pos) override; - virtual void onLButtonUp(POINT pos) override; - virtual void onMouseMove(POINT pos) override; - - void onRepeat(); - void onThumbTrack(POINT pos); - - static void CALLBACK repeatTimerProc(HWND hwnd, UINT message, UINT_PTR iTimerID, DWORD dwTime); - static void startRepeatTimer(DWORD time); - static void stopRepeatTimer(); }; }