1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added vertical scroll bar to config overlay

This commit is contained in:
narzoul 2023-07-02 16:31:10 +02:00
parent 1b4c127491
commit b083a04ac3
9 changed files with 183 additions and 65 deletions

View File

@ -97,13 +97,14 @@ namespace
{
if (HC_ACTION == nCode)
{
auto& llHook = *reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
if (WM_MOUSEMOVE == wParam)
{
POINT cp = g_cursorPos;
POINT origCp = {};
GetCursorPos(&origCp);
auto& llHook = *reinterpret_cast<MSLLHOOKSTRUCT*>(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;

View File

@ -1,3 +1,4 @@
#include <array>
#include <fstream>
#include <sstream>
@ -19,6 +20,7 @@
#include <Config/Settings/SpriteTexCoord.h>
#include <Config/Settings/TextureFilter.h>
#include <Config/Settings/VSync.h>
#include <D3dDdi/Device.h>
#include <Gdi/GuiThread.h>
#include <Input/Input.h>
#include <Overlay/ConfigWindow.h>
@ -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<SettingRow, 16> 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<ButtonControl>(*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<ConfigWindow*>(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<ConfigWindow*>(control.getParent())->resetSettings();

View File

@ -6,6 +6,7 @@
#include <Overlay/ButtonControl.h>
#include <Overlay/LabelControl.h>
#include <Overlay/ScrollBarControl.h>
#include <Overlay/SettingControl.h>
#include <Overlay/Window.h>
@ -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<ButtonControl> 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<ButtonControl> m_exportButton;
std::unique_ptr<ButtonControl> m_importButton;
std::unique_ptr<ButtonControl> m_resetAllButton;
std::unique_ptr<ScrollBarControl> m_scrollBar;
std::list<SettingControl> m_settingControls;
SettingControl* m_focus;
std::string m_fileContent;

View File

@ -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 <typename... Params>
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;
}
}

View File

@ -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 <typename... Params>
void propagateMouseEvent(void(Control::* onEvent)(POINT, Params...), POINT pos, Params... params);
Control* m_parent;
RECT m_rect;

View File

@ -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);
}
}

View File

@ -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;
};
}

View File

@ -7,7 +7,6 @@
#include <Config/Settings/SpriteTexCoord.h>
#include <Config/Settings/TextureFilter.h>
#include <Config/Setting.h>
#include <D3dDdi/Device.h>
#include <Overlay/ComboBoxControl.h>
#include <Overlay/ConfigWindow.h>
#include <Overlay/SettingControl.h>
@ -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();

View File

@ -1,5 +1,6 @@
#pragma once
#include <functional>
#include <memory>
#include <Overlay/LabelControl.h>
@ -18,6 +19,8 @@ namespace Overlay
class SettingControl : public Control
{
public:
typedef std::function<void()> 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<Control> m_valueControl;
std::unique_ptr<LabelControl> m_paramLabel;