diff --git a/DDrawCompat/Input/Input.cpp b/DDrawCompat/Input/Input.cpp index 2f97713..e1d91cf 100644 --- a/DDrawCompat/Input/Input.cpp +++ b/DDrawCompat/Input/Input.cpp @@ -97,13 +97,14 @@ namespace { if (HC_ACTION == nCode) { + auto& llHook = *reinterpret_cast(lParam); + if (WM_MOUSEMOVE == wParam) { POINT cp = g_cursorPos; POINT origCp = {}; GetCursorPos(&origCp); - auto& llHook = *reinterpret_cast(lParam); cp.x += (llHook.pt.x - origCp.x); cp.y += (llHook.pt.y - origCp.y); cp.x = std::min(std::max(g_monitorRect.left, cp.x), g_monitorRect.right); @@ -127,6 +128,10 @@ namespace case WM_MOUSEMOVE: g_capture->onMouseMove(cp); break; + + case WM_MOUSEWHEEL: + g_capture->onMouseWheel(cp, HIWORD(llHook.mouseData)); + break; } return 1; diff --git a/DDrawCompat/Overlay/ConfigWindow.cpp b/DDrawCompat/Overlay/ConfigWindow.cpp index 30b7364..19c8b7f 100644 --- a/DDrawCompat/Overlay/ConfigWindow.cpp +++ b/DDrawCompat/Overlay/ConfigWindow.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -26,13 +28,41 @@ namespace { + struct SettingRow + { + Config::Setting* setting; + Overlay::SettingControl::UpdateFunc updateFunc; + }; + const int CAPTION_HEIGHT = 22; + const int ROW_HEIGHT = 25; + const int ROWS = 15; + + std::array g_settingRows = { { + { &Config::alternatePixelCenter }, + { &Config::antialiasing, &D3dDdi::Device::updateAllConfig }, + { &Config::bltFilter }, + { &Config::colorKeyMethod, &D3dDdi::Device::updateAllConfig }, + { &Config::depthFormat, &D3dDdi::Device::updateAllConfig }, + { &Config::displayFilter }, + { &Config::fontAntialiasing }, + { &Config::fpsLimiter }, + { &Config::renderColorDepth, &D3dDdi::Device::updateAllConfig }, + { &Config::resolutionScale, &D3dDdi::Device::updateAllConfig }, + { &Config::resolutionScaleFilter }, + { &Config::spriteDetection }, + { &Config::spriteFilter, &D3dDdi::Device::updateAllConfig }, + { &Config::spriteTexCoord, &D3dDdi::Device::updateAllConfig }, + { &Config::textureFilter, &D3dDdi::Device::updateAllConfig }, + { &Config::vSync } + } }; } namespace Overlay { ConfigWindow::ConfigWindow() - : Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 480 }, WS_BORDER, Config::configHotKey.get()) + : Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH + ARROW_SIZE + BORDER / 2, ROWS * ROW_HEIGHT + 80 }, + WS_BORDER, Config::configHotKey.get()) , m_buttonCount(0) , m_focus(nullptr) { @@ -42,22 +72,13 @@ namespace Overlay r = { m_rect.right - CAPTION_HEIGHT, 0, m_rect.right, CAPTION_HEIGHT }; m_captionCloseButton.reset(new ButtonControl(*this, r, "X", onClose)); - addControl(Config::alternatePixelCenter); - addControl(Config::antialiasing); - addControl(Config::bltFilter); - addControl(Config::colorKeyMethod); - addControl(Config::depthFormat); - addControl(Config::displayFilter); - addControl(Config::fontAntialiasing); - addControl(Config::fpsLimiter); - addControl(Config::renderColorDepth); - addControl(Config::resolutionScale); - addControl(Config::resolutionScaleFilter); - addControl(Config::spriteDetection); - addControl(Config::spriteFilter); - addControl(Config::spriteTexCoord); - addControl(Config::textureFilter); - addControl(Config::vSync); + r.left = SettingControl::TOTAL_WIDTH; + r.top = CAPTION_HEIGHT + BORDER; + r.right = r.left + ARROW_SIZE; + r.bottom = r.top + ROWS * ROW_HEIGHT; + m_scrollBar.reset(new ScrollBarControl(*this, r, 0, g_settingRows.size() - ROWS)); + + addSettingControls(); m_closeButton = addButton("Close", onClose); m_exportButton = addButton("Export", onExport); @@ -80,14 +101,23 @@ namespace Overlay return std::make_unique(*this, r, label, clickHandler); } - void ConfigWindow::addControl(Config::Setting& setting) + void ConfigWindow::addSettingControl(Config::Setting& setting, SettingControl::UpdateFunc updateFunc) { const int index = m_settingControls.size(); - const int rowHeight = 25; - - RECT rect = { 0, index * rowHeight + BORDER / 2, m_rect.right, (index + 1) * rowHeight + BORDER / 2 }; + RECT rect = { 0, index * ROW_HEIGHT + BORDER, SettingControl::TOTAL_WIDTH, (index + 1) * ROW_HEIGHT + BORDER }; OffsetRect(&rect, 0, CAPTION_HEIGHT); - m_settingControls.emplace_back(*this, rect, setting); + m_settingControls.emplace_back(*this, rect, setting, updateFunc); + } + + void ConfigWindow::addSettingControls() + { + m_settingControls.clear(); + const int pos = m_scrollBar->getPos(); + for (int i = 0; i < ROWS; ++i) + { + auto& row = g_settingRows[pos + i]; + addSettingControl(*row.setting, row.updateFunc); + } } RECT ConfigWindow::calculateRect(const RECT& monitorRect) const @@ -159,6 +189,20 @@ namespace Overlay static_cast(control.getParent())->importSettings(); } + void ConfigWindow::onMouseWheel(POINT pos, SHORT delta) + { + m_scrollBar->onMouseWheel(pos, delta); + } + + void ConfigWindow::onNotify(Control& control) + { + if (m_scrollBar.get() == &control) + { + addSettingControls(); + onMouseMove(Input::getRelativeCursorPos()); + } + } + void ConfigWindow::onResetAll(Control& control) { static_cast(control.getParent())->resetSettings(); diff --git a/DDrawCompat/Overlay/ConfigWindow.h b/DDrawCompat/Overlay/ConfigWindow.h index aa6aa18..65450cb 100644 --- a/DDrawCompat/Overlay/ConfigWindow.h +++ b/DDrawCompat/Overlay/ConfigWindow.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -16,6 +17,8 @@ namespace Overlay public: ConfigWindow(); + virtual void onMouseWheel(POINT pos, SHORT delta) override; + virtual void onNotify(Control& control) override; virtual void setVisible(bool isVisible) override; void setFocus(SettingControl* control); @@ -30,7 +33,8 @@ namespace Overlay virtual RECT calculateRect(const RECT& monitorRect) const override; std::unique_ptr addButton(const std::string& label, ButtonControl::ClickHandler clickHandler); - void addControl(Config::Setting& setting); + void addSettingControl(Config::Setting& setting, SettingControl::UpdateFunc updateFunc); + void addSettingControls(); std::string constructFileContent(); void exportSettings(); void importSettings(); @@ -43,6 +47,7 @@ namespace Overlay std::unique_ptr m_exportButton; std::unique_ptr m_importButton; std::unique_ptr m_resetAllButton; + std::unique_ptr m_scrollBar; std::list m_settingControls; SettingControl* m_focus; std::string m_fileContent; diff --git a/DDrawCompat/Overlay/Control.cpp b/DDrawCompat/Overlay/Control.cpp index 5e6adcb..9f2fed4 100644 --- a/DDrawCompat/Overlay/Control.cpp +++ b/DDrawCompat/Overlay/Control.cpp @@ -20,6 +20,11 @@ namespace Overlay if (m_parent) { m_parent->m_children.erase(this); + if (this == m_parent->m_highlightedChild) + { + m_parent->m_highlightedChild = nullptr; + } + m_parent->invalidate(); } } @@ -158,7 +163,13 @@ namespace Overlay } } - void Control::propagateMouseEvent(void(Control::* onEvent)(POINT), POINT pos) + void Control::onMouseWheel(POINT pos, SHORT delta) + { + propagateMouseEvent(&Control::onMouseWheel, pos, delta); + } + + template + void Control::propagateMouseEvent(void(Control::* onEvent)(POINT, Params...), POINT pos, Params... params) { if (m_style & WS_DISABLED) { @@ -169,7 +180,7 @@ namespace Overlay { if (PtInRect(&child->m_rect, pos)) { - (child->*onEvent)(pos); + (child->*onEvent)(pos, params...); return; } } diff --git a/DDrawCompat/Overlay/Control.h b/DDrawCompat/Overlay/Control.h index 2785a75..adb2d98 100644 --- a/DDrawCompat/Overlay/Control.h +++ b/DDrawCompat/Overlay/Control.h @@ -26,6 +26,7 @@ namespace Overlay virtual void onLButtonDown(POINT pos); virtual void onLButtonUp(POINT pos); virtual void onMouseMove(POINT pos); + virtual void onMouseWheel(POINT pos, SHORT delta); virtual void onNotify(Control& /*control*/) {} virtual void setVisible(bool isVisible); @@ -44,7 +45,9 @@ namespace Overlay static const COLORREF HIGHLIGHT_COLOR = RGB(255, 255, 0); void drawArrow(HDC dc, RECT rect, UINT state); - void propagateMouseEvent(void(Control::* onEvent)(POINT), POINT pos); + + template + void propagateMouseEvent(void(Control::* onEvent)(POINT, Params...), POINT pos, Params... params); Control* m_parent; RECT m_rect; diff --git a/DDrawCompat/Overlay/ScrollBarControl.cpp b/DDrawCompat/Overlay/ScrollBarControl.cpp index 01ba93d..39840a8 100644 --- a/DDrawCompat/Overlay/ScrollBarControl.cpp +++ b/DDrawCompat/Overlay/ScrollBarControl.cpp @@ -22,21 +22,26 @@ namespace Overlay ScrollBarControl::ScrollBarControl(Control& parent, const RECT& rect, int min, int max) : Control(&parent, rect, WS_VISIBLE) , m_min(min) - , m_max(max) + , m_max(std::max(min, max)) , m_pos(min) - , m_leftArrow{ rect.left, rect.top, rect.left + ARROW_SIZE, rect.bottom } - , m_rightArrow{ rect.right - ARROW_SIZE, rect.top, rect.right, rect.bottom } , m_state(State::IDLE) + , m_left(isHorizontal() ? &RECT::left : &RECT::top) + , m_top(isHorizontal() ? &RECT::top : &RECT::left) + , m_right(isHorizontal() ? &RECT::right : &RECT::bottom) + , m_bottom(isHorizontal() ? &RECT::bottom : &RECT::right) + , m_x(isHorizontal() ? &POINT::x : &POINT::y) { } void ScrollBarControl::draw(HDC dc) { - drawArrow(dc, m_leftArrow, DFCS_SCROLLLEFT); - drawArrow(dc, m_rightArrow, DFCS_SCROLLRIGHT); + drawArrow(dc, getLeftArrowRect(), isHorizontal() ? DFCS_SCROLLLEFT : DFCS_SCROLLUP); + drawArrow(dc, getRightArrowRect(), isHorizontal() ? DFCS_SCROLLRIGHT : DFCS_SCROLLDOWN); - 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); + RECT r = m_rect; + r.*m_left += ARROW_SIZE - 1; + r.*m_right -= ARROW_SIZE - 1; + CALL_ORIG_FUNC(Rectangle)(dc, r.left, r.top, r.right, r.bottom); r = getThumbRect(); SelectObject(dc, GetStockObject(DC_BRUSH)); @@ -44,6 +49,20 @@ namespace Overlay SelectObject(dc, GetStockObject(NULL_BRUSH)); } + RECT ScrollBarControl::getLeftArrowRect() const + { + RECT r = m_rect; + r.*m_right = r.*m_left + ARROW_SIZE; + return r; + } + + RECT ScrollBarControl::getRightArrowRect() const + { + RECT r = m_rect; + r.*m_left = r.*m_right - ARROW_SIZE; + return r; + } + int ScrollBarControl::getPageSize() const { return std::max((m_max - m_min) / 20, 1); @@ -51,19 +70,27 @@ namespace Overlay 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 }; + const int thumbPos = (m_pos - m_min) * (m_rect.*m_right - m_rect.*m_left - 3 * ARROW_SIZE) / (m_max - m_min); + RECT r = m_rect; + r.*m_left = m_rect.*m_left + ARROW_SIZE + thumbPos; + r.*m_right = r.*m_left + ARROW_SIZE; + return r; + } + + bool ScrollBarControl::isHorizontal() const + { + return m_rect.right - m_rect.left > m_rect.bottom - m_rect.top; } void ScrollBarControl::onLButtonDown(POINT pos) { Input::setCapture(this); - - if (PtInRect(&m_leftArrow, pos)) + + if (pos.*m_x < m_rect.*m_left + ARROW_SIZE) { m_state = State::LEFT_ARROW_PRESSED; } - else if (PtInRect(&m_rightArrow, pos)) + else if (pos.*m_x >= m_rect.*m_right - ARROW_SIZE) { m_state = State::RIGHT_ARROW_PRESSED; } @@ -74,7 +101,7 @@ namespace Overlay { m_state = State::THUMB_PRESSED; } - else if (pos.x < r.left) + else if (pos.*m_x < r.*m_left) { m_state = State::LEFT_SHAFT_PRESSED; } @@ -110,6 +137,14 @@ namespace Overlay } } + void ScrollBarControl::onMouseWheel(POINT /*pos*/, SHORT delta) + { + if (State::IDLE == m_state) + { + setPos(m_pos - delta / WHEEL_DELTA * getPageSize()); + } + } + void ScrollBarControl::onRepeat() { stopRepeatTimer(); @@ -135,14 +170,14 @@ namespace Overlay break; case State::LEFT_SHAFT_PRESSED: - if (Input::getRelativeCursorPos().x < getThumbRect().left) + if (Input::getRelativeCursorPos().*m_x < getThumbRect().*m_left) { setPos(m_pos - getPageSize()); } break; case State::RIGHT_SHAFT_PRESSED: - if (Input::getRelativeCursorPos().x >= getThumbRect().right) + if (Input::getRelativeCursorPos().*m_x >= getThumbRect().*m_right) { setPos(m_pos + getPageSize()); } @@ -150,12 +185,12 @@ namespace Overlay 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)); + auto pos = Input::getRelativeCursorPos().*m_x; + const auto minPos = m_rect.*m_left + ARROW_SIZE + ARROW_SIZE / 2; + const auto maxPos = m_rect.*m_right - ARROW_SIZE - ARROW_SIZE / 2; + pos = std::max(pos, minPos); + pos = std::min(pos, maxPos); + setPos(m_min + roundDiv((pos - minPos) * (m_max - m_min), maxPos - minPos)); break; } } @@ -168,6 +203,7 @@ namespace Overlay if (pos != m_pos) { m_pos = pos; + m_parent->invalidate(); m_parent->onNotify(*this); } } diff --git a/DDrawCompat/Overlay/ScrollBarControl.h b/DDrawCompat/Overlay/ScrollBarControl.h index 5b38cf7..d581e04 100644 --- a/DDrawCompat/Overlay/ScrollBarControl.h +++ b/DDrawCompat/Overlay/ScrollBarControl.h @@ -9,6 +9,11 @@ namespace Overlay public: ScrollBarControl(Control& parent, const RECT& rect, int min, int max); + virtual void onLButtonDown(POINT pos) override; + virtual void onLButtonUp(POINT pos) override; + virtual void onMouseMove(POINT pos) override; + virtual void onMouseWheel(POINT pos, SHORT delta) override; + int getPos() const { return m_pos; } void setPos(int pos); @@ -24,12 +29,12 @@ namespace Overlay }; virtual void draw(HDC dc) override; - virtual void onLButtonDown(POINT pos) override; - virtual void onLButtonUp(POINT pos) override; - virtual void onMouseMove(POINT pos) override; + RECT getLeftArrowRect() const; + RECT getRightArrowRect() const; int getPageSize() const; RECT getThumbRect() const; + bool isHorizontal() const; void onRepeat(); void scroll(); @@ -40,8 +45,11 @@ namespace Overlay int m_min; int m_max; int m_pos; - RECT m_leftArrow; - RECT m_rightArrow; State m_state; + LONG RECT::* m_left; + LONG RECT::* m_top; + LONG RECT::* m_right; + LONG RECT::* m_bottom; + LONG POINT::* m_x; }; } diff --git a/DDrawCompat/Overlay/SettingControl.cpp b/DDrawCompat/Overlay/SettingControl.cpp index 9975aff..f4d7197 100644 --- a/DDrawCompat/Overlay/SettingControl.cpp +++ b/DDrawCompat/Overlay/SettingControl.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -32,9 +31,10 @@ namespace namespace Overlay { - SettingControl::SettingControl(ConfigWindow& parent, const RECT& rect, Config::Setting& setting) + SettingControl::SettingControl(ConfigWindow& parent, const RECT& rect, Config::Setting& setting, UpdateFunc updateFunc) : Control(&parent, rect, WS_VISIBLE | WS_TABSTOP) , m_setting(setting) + , m_updateFunc(updateFunc) , m_settingLabel(*this, { rect.left, rect.top, rect.left + SETTING_LABEL_WIDTH, rect.bottom }, setting.getName() + ':', 0) { const RECT r = { rect.left + SETTING_LABEL_WIDTH, rect.top + BORDER / 2, @@ -72,6 +72,14 @@ namespace Overlay } } + void SettingControl::onMouseWheel(POINT pos, SHORT delta) + { + if (m_paramControl) + { + m_paramControl->onMouseWheel(pos, delta); + } + } + void SettingControl::onNotify(Control& control) { if (&control == m_paramControl.get()) @@ -83,16 +91,9 @@ namespace Overlay onValueChanged(); } - if (&Config::antialiasing == &m_setting || - &Config::colorKeyMethod == &m_setting || - &Config::depthFormat == &m_setting || - &Config::renderColorDepth == &m_setting || - &Config::resolutionScale == &m_setting || - &Config::spriteFilter == &m_setting || - &Config::spriteTexCoord == &m_setting || - &Config::textureFilter == &m_setting) + if (m_updateFunc) { - D3dDdi::Device::updateAllConfig(); + m_updateFunc(); } invalidate(); diff --git a/DDrawCompat/Overlay/SettingControl.h b/DDrawCompat/Overlay/SettingControl.h index bee9f2d..f8ff460 100644 --- a/DDrawCompat/Overlay/SettingControl.h +++ b/DDrawCompat/Overlay/SettingControl.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -18,6 +19,8 @@ namespace Overlay class SettingControl : public Control { public: + typedef std::function UpdateFunc; + static const int PARAM_LABEL_WIDTH = 70; static const int PARAM_CONTROL_WIDTH = 241; static const int SETTING_LABEL_WIDTH = 130; @@ -25,10 +28,11 @@ namespace Overlay static const int TOTAL_WIDTH = SETTING_LABEL_WIDTH + SETTING_CONTROL_WIDTH + PARAM_LABEL_WIDTH + PARAM_CONTROL_WIDTH + BORDER; - SettingControl(ConfigWindow& parent, const RECT& rect, Config::Setting& setting); + SettingControl(ConfigWindow& parent, const RECT& rect, Config::Setting& setting, UpdateFunc updateFunc); virtual RECT getHighlightRect() const override; virtual void onLButtonDown(POINT pos) override; + virtual void onMouseWheel(POINT pos, SHORT delta) override; virtual void onNotify(Control& control) override; Config::Setting& getSetting() const { return m_setting; } @@ -40,6 +44,7 @@ namespace Overlay void onValueChanged(); Config::Setting& m_setting; + UpdateFunc m_updateFunc; LabelControl m_settingLabel; std::unique_ptr m_valueControl; std::unique_ptr m_paramLabel;