303 lines
9.7 KiB
C++
303 lines
9.7 KiB
C++
|
|
#include "LOGIC/Lgc_Func_Button_Private.h"
|
||
|
|
|
||
|
|
#include <QtCore/QUrl>
|
||
|
|
#include <QtGui/QDesktopServices>
|
||
|
|
#include <Windows.h>
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
|
||
|
|
constexpr DWORD LGC_FUNCTIONBUTTON_KEY_HOLD_DELAY_MS = 12;
|
||
|
|
constexpr DWORD LGC_FUNCTIONBUTTON_SEQUENCE_STEP_DELAY_MS = 60;
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
Lgc_FunctionButton_Struct_WindowsKey Lgc_FunctionButton_GetWindowsKey(quint16 Usage)
|
||
|
|
{
|
||
|
|
switch (Usage)
|
||
|
|
{
|
||
|
|
case 0x0053: return { VK_NUMLOCK, 0 };
|
||
|
|
case 0x0054: return { VK_DIVIDE, KEYEVENTF_EXTENDEDKEY };
|
||
|
|
case 0x0055: return { VK_MULTIPLY, 0 };
|
||
|
|
case 0x0056: return { VK_SUBTRACT, 0 };
|
||
|
|
case 0x0057: return { VK_ADD, 0 };
|
||
|
|
case 0x0058: return { VK_RETURN, KEYEVENTF_EXTENDEDKEY };
|
||
|
|
case 0x0059: return { VK_NUMPAD1, 0 };
|
||
|
|
case 0x005A: return { VK_NUMPAD2, 0 };
|
||
|
|
case 0x005B: return { VK_NUMPAD3, 0 };
|
||
|
|
case 0x005C: return { VK_NUMPAD4, 0 };
|
||
|
|
case 0x005D: return { VK_NUMPAD5, 0 };
|
||
|
|
case 0x005E: return { VK_NUMPAD6, 0 };
|
||
|
|
case 0x005F: return { VK_NUMPAD7, 0 };
|
||
|
|
case 0x0060: return { VK_NUMPAD8, 0 };
|
||
|
|
case 0x0061: return { VK_NUMPAD9, 0 };
|
||
|
|
case 0x0062: return { VK_NUMPAD0, 0 };
|
||
|
|
case 0x0063: return { VK_DECIMAL, 0 };
|
||
|
|
case 0x00E0: return { VK_CONTROL, 0, true };
|
||
|
|
case 0x00E1: return { VK_SHIFT, 0, true };
|
||
|
|
case 0x00E2: return { VK_MENU, 0, true };
|
||
|
|
case 0x00E3: return { VK_LWIN, 0, true };
|
||
|
|
case 0x00E4: return { VK_CONTROL, KEYEVENTF_EXTENDEDKEY, true };
|
||
|
|
case 0x00E5: return { VK_SHIFT, 0, true };
|
||
|
|
case 0x00E6: return { VK_MENU, KEYEVENTF_EXTENDEDKEY, true };
|
||
|
|
case 0x00E7: return { VK_RWIN, 0, true };
|
||
|
|
default:
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Lgc_FunctionButton_SendWindowsKey(
|
||
|
|
const Lgc_FunctionButton_Struct_WindowsKey& Key,
|
||
|
|
bool IsPressed)
|
||
|
|
{
|
||
|
|
if (Key.VirtualKey == 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
INPUT InputData = {};
|
||
|
|
InputData.type = INPUT_KEYBOARD;
|
||
|
|
InputData.ki.wVk = Key.VirtualKey;
|
||
|
|
InputData.ki.dwFlags = Key.ExtraFlags;
|
||
|
|
if (!IsPressed)
|
||
|
|
{
|
||
|
|
InputData.ki.dwFlags |= KEYEVENTF_KEYUP;
|
||
|
|
}
|
||
|
|
|
||
|
|
return SendInput(1, &InputData, sizeof(INPUT)) == 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Lgc_FunctionButton_SendKeyCombination(
|
||
|
|
const QVector<Lgc_FunctionButton_Struct_SequenceKey>& KeyList)
|
||
|
|
{
|
||
|
|
QVector<Lgc_FunctionButton_Struct_WindowsKey> ModifierList;
|
||
|
|
QVector<Lgc_FunctionButton_Struct_WindowsKey> NormalKeyList;
|
||
|
|
|
||
|
|
for (const auto& KeyItem : KeyList)
|
||
|
|
{
|
||
|
|
if (KeyItem.Key.VirtualKey == 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (KeyItem.Key.IsModifier)
|
||
|
|
{
|
||
|
|
bool IsDuplicate = false;
|
||
|
|
for (const auto& OldModifier : ModifierList)
|
||
|
|
{
|
||
|
|
if (Lgc_FunctionButton_IsSameWindowsKey(OldModifier, KeyItem.Key))
|
||
|
|
{
|
||
|
|
IsDuplicate = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (!IsDuplicate)
|
||
|
|
{
|
||
|
|
ModifierList.append(KeyItem.Key);
|
||
|
|
}
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
NormalKeyList.append(KeyItem.Key);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int ModifierIndex = 0; ModifierIndex < ModifierList.size(); ++ModifierIndex)
|
||
|
|
{
|
||
|
|
const auto& ModifierKey = ModifierList.at(ModifierIndex);
|
||
|
|
if (!Lgc_FunctionButton_SendWindowsKey(ModifierKey, true))
|
||
|
|
{
|
||
|
|
for (int Index = ModifierIndex - 1; Index >= 0; --Index)
|
||
|
|
{
|
||
|
|
Lgc_FunctionButton_SendWindowsKey(ModifierList.at(Index), false);
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
Sleep(LGC_FUNCTIONBUTTON_KEY_HOLD_DELAY_MS);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (NormalKeyList.isEmpty())
|
||
|
|
{
|
||
|
|
for (int Index = ModifierList.size() - 1; Index >= 0; --Index)
|
||
|
|
{
|
||
|
|
if (!Lgc_FunctionButton_SendWindowsKey(ModifierList.at(Index), false))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
Sleep(LGC_FUNCTIONBUTTON_KEY_HOLD_DELAY_MS);
|
||
|
|
}
|
||
|
|
return !ModifierList.isEmpty();
|
||
|
|
}
|
||
|
|
|
||
|
|
for (const auto& NormalKey : NormalKeyList)
|
||
|
|
{
|
||
|
|
if (!Lgc_FunctionButton_SendWindowsKey(NormalKey, true))
|
||
|
|
{
|
||
|
|
for (int Index = ModifierList.size() - 1; Index >= 0; --Index)
|
||
|
|
{
|
||
|
|
Lgc_FunctionButton_SendWindowsKey(ModifierList.at(Index), false);
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
Sleep(LGC_FUNCTIONBUTTON_KEY_HOLD_DELAY_MS);
|
||
|
|
if (!Lgc_FunctionButton_SendWindowsKey(NormalKey, false))
|
||
|
|
{
|
||
|
|
for (int Index = ModifierList.size() - 1; Index >= 0; --Index)
|
||
|
|
{
|
||
|
|
Lgc_FunctionButton_SendWindowsKey(ModifierList.at(Index), false);
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
Sleep(LGC_FUNCTIONBUTTON_KEY_HOLD_DELAY_MS);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int Index = ModifierList.size() - 1; Index >= 0; --Index)
|
||
|
|
{
|
||
|
|
if (!Lgc_FunctionButton_SendWindowsKey(ModifierList.at(Index), false))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
Sleep(LGC_FUNCTIONBUTTON_KEY_HOLD_DELAY_MS);
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Lgc_FunctionButton_SendShortcutSequence(
|
||
|
|
const QVector<QVector<Lgc_FunctionButton_Struct_SequenceKey>>& CombinationList)
|
||
|
|
{
|
||
|
|
for (int Index = 0; Index < CombinationList.size(); ++Index)
|
||
|
|
{
|
||
|
|
const auto& Combination = CombinationList.at(Index);
|
||
|
|
if (!Lgc_FunctionButton_SendKeyCombination(Combination))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (Index + 1 < CombinationList.size())
|
||
|
|
{
|
||
|
|
Sleep(LGC_FUNCTIONBUTTON_SEQUENCE_STEP_DELAY_MS);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Lgc_FunctionButton_RunKeyCombination(
|
||
|
|
const Lgc_FunctionFeature_Definition& Feature,
|
||
|
|
quint16 SourceUsage,
|
||
|
|
QString* p_TextStatus)
|
||
|
|
{
|
||
|
|
const QString CombinationText = Feature.SequenceText.trimmed();
|
||
|
|
if (CombinationText.isEmpty())
|
||
|
|
{
|
||
|
|
*p_TextStatus = QStringLiteral("%1 的快捷键尚未配置。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
QVector<Lgc_FunctionButton_Struct_SequenceKey> KeyList;
|
||
|
|
QString ErrorText;
|
||
|
|
if (!Lgc_FunctionButton_ParseKeyCombinationText(
|
||
|
|
CombinationText,
|
||
|
|
SourceUsage,
|
||
|
|
&KeyList,
|
||
|
|
&ErrorText))
|
||
|
|
{
|
||
|
|
QVector<quint16> UsageList;
|
||
|
|
if (!Lgc_FunctionButton_ParseLegacySequenceText(
|
||
|
|
CombinationText,
|
||
|
|
SourceUsage,
|
||
|
|
&UsageList,
|
||
|
|
&ErrorText))
|
||
|
|
{
|
||
|
|
*p_TextStatus = QStringLiteral("%1 的快捷键无效:%2")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature), ErrorText);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
KeyList = Lgc_FunctionButton_ConvertUsageListToSequenceKeys(UsageList);
|
||
|
|
if (KeyList.isEmpty())
|
||
|
|
{
|
||
|
|
*p_TextStatus = QStringLiteral("%1 的快捷键无效:存在无法执行的按键。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
*p_TextStatus = Lgc_FunctionButton_SendKeyCombination(KeyList)
|
||
|
|
? QStringLiteral("%1 已输出快捷键:%2")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature),
|
||
|
|
Lgc_FunctionButton_FormatKeyCombination(KeyList))
|
||
|
|
: QStringLiteral("%1 输出快捷键失败。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
}
|
||
|
|
|
||
|
|
void Lgc_FunctionButton_RunKeySequence(
|
||
|
|
const Lgc_FunctionFeature_Definition& Feature,
|
||
|
|
quint16 SourceUsage,
|
||
|
|
QString* p_TextStatus)
|
||
|
|
{
|
||
|
|
const QString SequenceText = Feature.SequenceText.trimmed();
|
||
|
|
if (SequenceText.isEmpty())
|
||
|
|
{
|
||
|
|
*p_TextStatus = QStringLiteral("%1 的快捷键序列尚未配置。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
QVector<QVector<Lgc_FunctionButton_Struct_SequenceKey>> CombinationList;
|
||
|
|
QString ErrorText;
|
||
|
|
if (!Lgc_FunctionButton_ParseShortcutSequenceText(
|
||
|
|
SequenceText,
|
||
|
|
SourceUsage,
|
||
|
|
&CombinationList,
|
||
|
|
&ErrorText))
|
||
|
|
{
|
||
|
|
QVector<quint16> UsageList;
|
||
|
|
if (!Lgc_FunctionButton_ParseLegacySequenceText(
|
||
|
|
SequenceText,
|
||
|
|
SourceUsage,
|
||
|
|
&UsageList,
|
||
|
|
&ErrorText))
|
||
|
|
{
|
||
|
|
*p_TextStatus = QStringLiteral("%1 的快捷键序列无效:%2")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature), ErrorText);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const QVector<Lgc_FunctionButton_Struct_SequenceKey> KeyList =
|
||
|
|
Lgc_FunctionButton_ConvertUsageListToSequenceKeys(UsageList);
|
||
|
|
CombinationList = Lgc_FunctionButton_GroupSequenceKeysIntoCombinations(KeyList);
|
||
|
|
if (CombinationList.isEmpty())
|
||
|
|
{
|
||
|
|
*p_TextStatus = QStringLiteral("%1 的快捷键序列无效:存在无法执行的按键。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
*p_TextStatus = Lgc_FunctionButton_SendShortcutSequence(CombinationList)
|
||
|
|
? QStringLiteral("%1 已输出快捷键序列:%2")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature),
|
||
|
|
Lgc_FunctionButton_FormatShortcutSequence(CombinationList))
|
||
|
|
: QStringLiteral("%1 输出快捷键序列失败。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
}
|
||
|
|
|
||
|
|
void Lgc_FunctionButton_RunOpenWebsite(
|
||
|
|
const Lgc_FunctionFeature_Definition& Feature,
|
||
|
|
QString* p_TextStatus)
|
||
|
|
{
|
||
|
|
const QString UrlText = Feature.WebsiteUrl.trimmed();
|
||
|
|
const QUrl Url = QUrl::fromUserInput(UrlText);
|
||
|
|
if (UrlText.isEmpty() || !Url.isValid() || Url.isEmpty())
|
||
|
|
{
|
||
|
|
*p_TextStatus = QStringLiteral("%1 的网址配置无效。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
*p_TextStatus = QDesktopServices::openUrl(Url)
|
||
|
|
? QStringLiteral("%1 已打开网址:%2")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature), Url.toString())
|
||
|
|
: QStringLiteral("%1 打开网址失败。")
|
||
|
|
.arg(Lgc_FunctionButton_GetFeatureName(Feature));
|
||
|
|
}
|