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

Added ConfigHotKey setting

This commit is contained in:
narzoul 2022-02-19 18:14:33 +01:00
parent 408ccee3d8
commit 8905f421cf
15 changed files with 371 additions and 28 deletions

View File

@ -4,6 +4,7 @@ namespace Config
{
Settings::AlternatePixelCenter alternatePixelCenter;
Settings::Antialiasing antialiasing;
Settings::ConfigHotKey configHotKey;
Settings::CpuAffinity cpuAffinity;
Settings::DesktopColorDepth desktopColorDepth;
Settings::DisplayFilter displayFilter;

View File

@ -2,6 +2,7 @@
#include <Config/Settings/AlternatePixelCenter.h>
#include <Config/Settings/Antialiasing.h>
#include <Config/Settings/ConfigHotKey.h>
#include <Config/Settings/CpuAffinity.h>
#include <Config/Settings/DesktopColorDepth.h>
#include <Config/Settings/DisplayFilter.h>
@ -20,6 +21,7 @@ namespace Config
extern Settings::AlternatePixelCenter alternatePixelCenter;
extern Settings::Antialiasing antialiasing;
extern Settings::ConfigHotKey configHotKey;
extern Settings::CpuAffinity cpuAffinity;
extern Settings::DesktopColorDepth desktopColorDepth;
extern Settings::DisplayFilter displayFilter;

View File

@ -0,0 +1,24 @@
#pragma once
#include <vector>
#include <Config/Setting.h>
#include <Input/HotKey.h>
namespace Config
{
class HotKeySetting : public Setting
{
public:
const Input::HotKey& get() const { return m_value; }
virtual std::string getValueStr() const override { return toString(m_value); }
protected:
HotKeySetting(const std::string& name, const std::string& default) : Setting(name, default) {}
virtual void setValue(const std::string& value) override { m_value = Input::parseHotKey(value); }
private:
Input::HotKey m_value;
};
}

View File

@ -11,7 +11,7 @@ namespace Config
protected:
ListSetting(const std::string& name, const std::string& default);
void setValue(const std::string& value) override;
virtual void setValue(const std::string& value) override;
virtual void setValues(const std::vector<std::string>& values) = 0;
};
}

View File

@ -10,7 +10,6 @@
namespace
{
void setConfig(const std::string& name, const std::string& value, const std::string& source);
std::string tolower(const std::string& str);
auto& getSettings()
{
@ -76,23 +75,13 @@ namespace
try
{
it->second.set(tolower(value), source);
it->second.set(Config::Parser::tolower(value), source);
}
catch (const Config::ParsingError& error)
{
throw Config::ParsingError(it->second.getName() + ": " + error.what());
}
}
std::string tolower(const std::string& str)
{
std::string result(str);
for (auto& c : result)
{
c = std::tolower(c, std::locale());
}
return result;
}
}
namespace Config
@ -191,6 +180,16 @@ namespace Config
return value;
}
std::string tolower(const std::string& str)
{
std::string result(str);
for (auto& c : result)
{
c = std::tolower(c, std::locale());
}
return result;
}
std::string trim(const std::string& str)
{
auto result(str);

View File

@ -23,6 +23,7 @@ namespace Config
int parseInt(const std::string& value, int min, int max);
void registerSetting(Setting& setting);
std::string removeParam(const std::string& value);
std::string tolower(const std::string& str);
std::string trim(const std::string& str);
}
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <Config/HotKeySetting.h>
namespace Config
{
namespace Settings
{
class ConfigHotKey : public HotKeySetting
{
public:
ConfigHotKey() : HotKeySetting("ConfigHotKey", "shift+f11") {}
};
}
}

View File

@ -211,12 +211,14 @@
<ClInclude Include="Common\Time.h" />
<ClInclude Include="Config\Config.h" />
<ClInclude Include="Config\EnumSetting.h" />
<ClInclude Include="Config\HotKeySetting.h" />
<ClInclude Include="Config\ListSetting.h" />
<ClInclude Include="Config\MappedSetting.h" />
<ClInclude Include="Config\Parser.h" />
<ClInclude Include="Config\Setting.h" />
<ClInclude Include="Config\Settings\AlternatePixelCenter.h" />
<ClInclude Include="Config\Settings\Antialiasing.h" />
<ClInclude Include="Config\Settings\ConfigHotKey.h" />
<ClInclude Include="Config\Settings\CpuAffinity.h" />
<ClInclude Include="Config\Settings\DesktopColorDepth.h" />
<ClInclude Include="Config\Settings\DisplayFilter.h" />
@ -315,6 +317,7 @@
<ClInclude Include="Gdi\VirtualScreen.h" />
<ClInclude Include="Gdi\Window.h" />
<ClInclude Include="Gdi\WinProc.h" />
<ClInclude Include="Input\HotKey.h" />
<ClInclude Include="Input\Input.h" />
<ClInclude Include="Overlay\ComboBoxControl.h" />
<ClInclude Include="Overlay\ComboBoxDropDown.h" />
@ -417,6 +420,7 @@
<ClCompile Include="Gdi\VirtualScreen.cpp" />
<ClCompile Include="Gdi\Window.cpp" />
<ClCompile Include="Gdi\WinProc.cpp" />
<ClCompile Include="Input\HotKey.cpp" />
<ClCompile Include="Input\Input.cpp" />
<ClCompile Include="Overlay\ComboBoxControl.cpp" />
<ClCompile Include="Overlay\ComboBoxDropDown.cpp" />

View File

@ -519,6 +519,15 @@
<ClInclude Include="Config\Settings\DisplayRefreshRate.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
<ClInclude Include="Config\HotKeySetting.h">
<Filter>Header Files\Config</Filter>
</ClInclude>
<ClInclude Include="Input\HotKey.h">
<Filter>Header Files\Input</Filter>
</ClInclude>
<ClInclude Include="Config\Settings\ConfigHotKey.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -821,6 +830,9 @@
<ClCompile Include="Config\Settings\DisplayRefreshRate.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
<ClCompile Include="Input\HotKey.cpp">
<Filter>Source Files\Input</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">

View File

@ -0,0 +1,258 @@
#include <map>
#include <Config/Parser.h>
#include <Input/HotKey.h>
namespace
{
const std::map<std::string, UINT> g_keyNames = []() {
std::map<std::string, UINT> names;
#define VK_HANGUEL 0x15
#define ADD_KEY_NAME(key) names[Config::Parser::tolower(std::string(#key).substr(3))] = key;
ADD_KEY_NAME(VK_CANCEL);
ADD_KEY_NAME(VK_BACK);
ADD_KEY_NAME(VK_TAB);
ADD_KEY_NAME(VK_CLEAR);
ADD_KEY_NAME(VK_RETURN);
ADD_KEY_NAME(VK_SHIFT);
ADD_KEY_NAME(VK_CONTROL);
ADD_KEY_NAME(VK_MENU);
ADD_KEY_NAME(VK_PAUSE);
ADD_KEY_NAME(VK_CAPITAL);
ADD_KEY_NAME(VK_KANA);
ADD_KEY_NAME(VK_HANGEUL);
ADD_KEY_NAME(VK_HANGUEL);
ADD_KEY_NAME(VK_HANGUL);
ADD_KEY_NAME(VK_IME_ON);
ADD_KEY_NAME(VK_JUNJA);
ADD_KEY_NAME(VK_FINAL);
ADD_KEY_NAME(VK_HANJA);
ADD_KEY_NAME(VK_KANJI);
ADD_KEY_NAME(VK_IME_OFF);
ADD_KEY_NAME(VK_ESCAPE);
ADD_KEY_NAME(VK_CONVERT);
ADD_KEY_NAME(VK_NONCONVERT);
ADD_KEY_NAME(VK_ACCEPT);
ADD_KEY_NAME(VK_MODECHANGE);
ADD_KEY_NAME(VK_SPACE);
ADD_KEY_NAME(VK_PRIOR);
ADD_KEY_NAME(VK_NEXT);
ADD_KEY_NAME(VK_END);
ADD_KEY_NAME(VK_HOME);
ADD_KEY_NAME(VK_LEFT);
ADD_KEY_NAME(VK_UP);
ADD_KEY_NAME(VK_RIGHT);
ADD_KEY_NAME(VK_DOWN);
ADD_KEY_NAME(VK_SELECT);
ADD_KEY_NAME(VK_PRINT);
ADD_KEY_NAME(VK_EXECUTE);
ADD_KEY_NAME(VK_SNAPSHOT);
ADD_KEY_NAME(VK_INSERT);
ADD_KEY_NAME(VK_DELETE);
ADD_KEY_NAME(VK_HELP);
ADD_KEY_NAME(VK_LWIN);
ADD_KEY_NAME(VK_RWIN);
ADD_KEY_NAME(VK_APPS);
ADD_KEY_NAME(VK_SLEEP);
ADD_KEY_NAME(VK_NUMPAD0);
ADD_KEY_NAME(VK_NUMPAD1);
ADD_KEY_NAME(VK_NUMPAD2);
ADD_KEY_NAME(VK_NUMPAD3);
ADD_KEY_NAME(VK_NUMPAD4);
ADD_KEY_NAME(VK_NUMPAD5);
ADD_KEY_NAME(VK_NUMPAD6);
ADD_KEY_NAME(VK_NUMPAD7);
ADD_KEY_NAME(VK_NUMPAD8);
ADD_KEY_NAME(VK_NUMPAD9);
ADD_KEY_NAME(VK_MULTIPLY);
ADD_KEY_NAME(VK_ADD);
ADD_KEY_NAME(VK_SEPARATOR);
ADD_KEY_NAME(VK_SUBTRACT);
ADD_KEY_NAME(VK_DECIMAL);
ADD_KEY_NAME(VK_DIVIDE);
ADD_KEY_NAME(VK_F1);
ADD_KEY_NAME(VK_F2);
ADD_KEY_NAME(VK_F3);
ADD_KEY_NAME(VK_F4);
ADD_KEY_NAME(VK_F5);
ADD_KEY_NAME(VK_F6);
ADD_KEY_NAME(VK_F7);
ADD_KEY_NAME(VK_F8);
ADD_KEY_NAME(VK_F9);
ADD_KEY_NAME(VK_F10);
ADD_KEY_NAME(VK_F11);
ADD_KEY_NAME(VK_F12);
ADD_KEY_NAME(VK_F13);
ADD_KEY_NAME(VK_F14);
ADD_KEY_NAME(VK_F15);
ADD_KEY_NAME(VK_F16);
ADD_KEY_NAME(VK_F17);
ADD_KEY_NAME(VK_F18);
ADD_KEY_NAME(VK_F19);
ADD_KEY_NAME(VK_F20);
ADD_KEY_NAME(VK_F21);
ADD_KEY_NAME(VK_F22);
ADD_KEY_NAME(VK_F23);
ADD_KEY_NAME(VK_F24);
ADD_KEY_NAME(VK_NUMLOCK);
ADD_KEY_NAME(VK_SCROLL);
ADD_KEY_NAME(VK_LSHIFT);
ADD_KEY_NAME(VK_RSHIFT);
ADD_KEY_NAME(VK_LCONTROL);
ADD_KEY_NAME(VK_RCONTROL);
ADD_KEY_NAME(VK_LMENU);
ADD_KEY_NAME(VK_RMENU);
ADD_KEY_NAME(VK_BROWSER_BACK);
ADD_KEY_NAME(VK_BROWSER_FORWARD);
ADD_KEY_NAME(VK_BROWSER_REFRESH);
ADD_KEY_NAME(VK_BROWSER_STOP);
ADD_KEY_NAME(VK_BROWSER_SEARCH);
ADD_KEY_NAME(VK_BROWSER_FAVORITES);
ADD_KEY_NAME(VK_BROWSER_HOME);
ADD_KEY_NAME(VK_VOLUME_MUTE);
ADD_KEY_NAME(VK_VOLUME_DOWN);
ADD_KEY_NAME(VK_VOLUME_UP);
ADD_KEY_NAME(VK_MEDIA_NEXT_TRACK);
ADD_KEY_NAME(VK_MEDIA_PREV_TRACK);
ADD_KEY_NAME(VK_MEDIA_STOP);
ADD_KEY_NAME(VK_MEDIA_PLAY_PAUSE);
ADD_KEY_NAME(VK_LAUNCH_MAIL);
ADD_KEY_NAME(VK_LAUNCH_MEDIA_SELECT);
ADD_KEY_NAME(VK_LAUNCH_APP1);
ADD_KEY_NAME(VK_LAUNCH_APP2);
ADD_KEY_NAME(VK_OEM_1);
ADD_KEY_NAME(VK_OEM_PLUS);
ADD_KEY_NAME(VK_OEM_COMMA);
ADD_KEY_NAME(VK_OEM_MINUS);
ADD_KEY_NAME(VK_OEM_PERIOD);
ADD_KEY_NAME(VK_OEM_2);
ADD_KEY_NAME(VK_OEM_3);
ADD_KEY_NAME(VK_OEM_4);
ADD_KEY_NAME(VK_OEM_5);
ADD_KEY_NAME(VK_OEM_6);
ADD_KEY_NAME(VK_OEM_7);
ADD_KEY_NAME(VK_OEM_8);
ADD_KEY_NAME(VK_OEM_102);
ADD_KEY_NAME(VK_PROCESSKEY);
ADD_KEY_NAME(VK_PACKET);
ADD_KEY_NAME(VK_ATTN);
ADD_KEY_NAME(VK_CRSEL);
ADD_KEY_NAME(VK_EXSEL);
ADD_KEY_NAME(VK_EREOF);
ADD_KEY_NAME(VK_PLAY);
ADD_KEY_NAME(VK_ZOOM);
ADD_KEY_NAME(VK_NONAME);
ADD_KEY_NAME(VK_PA1);
ADD_KEY_NAME(VK_OEM_CLEAR);
#undef ADD_KEY_NAME
return names;
}();
bool areExcludedModifierKeysDown(const std::set<UINT>& modifiers, UINT either, UINT left, UINT right)
{
return modifiers.find(either) == modifiers.end() &&
modifiers.find(left) == modifiers.end() &&
modifiers.find(right) == modifiers.end() &&
(GetAsyncKeyState(either) & 0x8000);
}
UINT getKeyCode(const std::string& name)
{
if (1 == name.length())
{
if (name[0] >= '0' && name[0] <= '9' ||
name[0] >= 'a' && name[0] <= 'z')
{
return std::toupper(name[0], std::locale());
}
}
auto it = g_keyNames.find(name);
if (it == g_keyNames.end())
{
throw Config::ParsingError("Invalid hotkey: '" + name + "'");
}
return it->second;
}
std::string getKeyName(UINT key)
{
if (key >= '0' && key <= '9' ||
key >= 'A' && key <= 'Z')
{
return std::string(1, static_cast<char>(std::tolower(key, std::locale())));
}
auto it = std::find_if(g_keyNames.begin(), g_keyNames.end(), [&](const auto& pair) { return pair.second == key; });
return it != g_keyNames.end() ? it->first : "none";
}
}
namespace Input
{
bool areModifierKeysDown(const std::set<UINT>& modifiers)
{
for (auto modifier : modifiers)
{
if (0 == (GetAsyncKeyState(modifier) & 0x8000))
{
return false;
}
}
return !areExcludedModifierKeysDown(modifiers, VK_SHIFT, VK_LSHIFT, VK_RSHIFT) &&
!areExcludedModifierKeysDown(modifiers, VK_CONTROL, VK_LCONTROL, VK_RCONTROL) &&
!areExcludedModifierKeysDown(modifiers, VK_MENU, VK_LMENU, VK_RMENU);
}
bool isModifierKey(UINT vk)
{
return vk >= VK_SHIFT && vk <= VK_MENU ||
vk >= VK_LSHIFT && vk <= VK_RMENU;
}
HotKey parseHotKey(std::string str)
{
HotKey hotKey;
if (str.empty() || "none" == str)
{
return hotKey;
}
int pos = str.find('+');
while (std::string::npos != pos)
{
std::string modifierName(Config::Parser::trim(str.substr(0, pos)));
UINT modifier = getKeyCode(modifierName);
if (!isModifierKey(modifier))
{
throw Config::ParsingError("Not a modifier key: '" + modifierName + "'");
}
hotKey.modifiers.insert(modifier);
str = str.substr(pos + 1);
pos = str.find('+');
}
hotKey.vk = getKeyCode(str);
if (isModifierKey(hotKey.vk))
{
throw Config::ParsingError("A hotkey cannot end with a modifier key: '" + str + "'");
}
return hotKey;
}
std::string toString(const HotKey& hotKey)
{
if (!hotKey.vk)
{
return "none";
}
std::string str;
for (UINT modifier : hotKey.modifiers)
{
str += getKeyName(modifier) + '+';
}
return str + getKeyName(hotKey.vk);
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <set>
#include <string>
#include <Windows.h>
namespace Input
{
struct HotKey
{
UINT vk;
std::set<UINT> modifiers;
HotKey() : vk(0) {}
};
bool areModifierKeysDown(const std::set<UINT>& modifiers);
bool isModifierKey(UINT vk);
HotKey parseHotKey(std::string str);
std::string toString(const HotKey& hotKey);
}

View File

@ -77,18 +77,24 @@ namespace
LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (HC_ACTION == nCode && (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam))
if (HC_ACTION == nCode &&
(WM_KEYDOWN == wParam || WM_KEYUP == wParam || WM_SYSKEYDOWN == wParam || WM_SYSKEYUP == wParam))
{
DWORD pid = 0;
GetWindowThreadProcessId(GetForegroundWindow(), &pid);
if (GetCurrentProcessId() == pid)
{
auto llHook = reinterpret_cast<const KBDLLHOOKSTRUCT*>(lParam);
auto it = std::find_if(g_hotKeys.begin(), g_hotKeys.end(),
[&](const auto& v) { return v.first.vk == llHook->vkCode; });
if (it != g_hotKeys.end())
for (auto& hotkey : g_hotKeys)
{
it->second.action(it->second.context);
if (hotkey.first.vk == llHook->vkCode && Input::areModifierKeysDown(hotkey.first.modifiers))
{
if (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam)
{
hotkey.second.action(hotkey.second.context);
}
return 1;
}
}
}
}
@ -245,10 +251,13 @@ namespace Input
void registerHotKey(const HotKey& hotKey, std::function<void(void*)> action, void* context)
{
g_hotKeys[hotKey] = { action, context };
if (!g_keyboardHook)
if (0 != hotKey.vk)
{
resetKeyboardHook();
g_hotKeys[hotKey] = { action, context };
if (!g_keyboardHook)
{
resetKeyboardHook();
}
}
}

View File

@ -1,7 +1,6 @@
#pragma once
#include <functional>
#include <set>
#include <Windows.h>
@ -13,11 +12,7 @@ namespace Overlay
namespace Input
{
struct HotKey
{
UINT vk;
std::set<UINT> modifiers;
};
struct HotKey;
bool operator<(const HotKey& lhs, const HotKey& rhs);

View File

@ -8,7 +8,7 @@
namespace Overlay
{
ConfigWindow::ConfigWindow()
: Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 200 }, { VK_F11, {} })
: Window(nullptr, { 0, 0, SettingControl::TOTAL_WIDTH, 200 }, Config::configHotKey.get())
, m_focus(nullptr)
{
addControl(Config::alternatePixelCenter);

View File

@ -5,6 +5,7 @@
#include <Windows.h>
#include <Input/Input.h>
#include <Input/HotKey.h>
#include <Overlay/Control.h>
namespace Overlay