#include "APP/APP_UIWindow.h" #include "APP/APP_UIWindow_Private.h" #include #include #include #include #include #include #include #include namespace APP { namespace { bool App_Func_IsModifierRecordToken(const QString& Token) { return (Token == QStringLiteral("Ctrl")) || (Token == QStringLiteral("Shift")) || (Token == QStringLiteral("Alt")) || (Token == QStringLiteral("Win")); } QStringList App_Func_GetOrderedRecordedModifierTokens(const QSet& PressedKeySet) { const QStringList ModifierOrder = { QStringLiteral("Ctrl"), QStringLiteral("Shift"), QStringLiteral("Alt"), QStringLiteral("Win") }; QStringList Result; for (const QString& ModifierToken : ModifierOrder) { if (PressedKeySet.contains(ModifierToken)) { Result.append(ModifierToken); } } return Result; } QString App_Func_GetRecordedCombinationText( const QSet& PressedKeySet, const QString& TriggerToken) { QStringList TokenList = App_Func_GetOrderedRecordedModifierTokens(PressedKeySet); if (!TriggerToken.isEmpty() && !App_Func_IsModifierRecordToken(TriggerToken)) { TokenList.append(TriggerToken); } return TokenList.join(QStringLiteral("+")); } bool App_Func_TryGetRawKeyboard(void* p_Message, RAWKEYBOARD* p_Keyboard) { if ((p_Message == nullptr) || (p_Keyboard == nullptr)) { return false; } MSG* p_Msg = reinterpret_cast(p_Message); if (p_Msg->message != WM_INPUT) { return false; } UINT NeedSize = 0; GetRawInputData( reinterpret_cast(p_Msg->lParam), RID_INPUT, nullptr, &NeedSize, sizeof(RAWINPUTHEADER)); if (NeedSize == 0) { return false; } QByteArray Buffer(static_cast(NeedSize), 0); if (GetRawInputData( reinterpret_cast(p_Msg->lParam), RID_INPUT, Buffer.data(), &NeedSize, sizeof(RAWINPUTHEADER)) == static_cast(-1)) { return false; } const RAWINPUT* p_Input = reinterpret_cast(Buffer.constData()); if (p_Input->header.dwType != RIM_TYPEKEYBOARD) { return false; } *p_Keyboard = p_Input->data.keyboard; return true; } QString App_Func_GetRecordedKeyToken(const RAWKEYBOARD& Keyboard) { const bool IsE0 = (Keyboard.Flags & RI_KEY_E0) != 0; const USHORT VirtualKey = Keyboard.VKey; if ((VirtualKey >= 'A') && (VirtualKey <= 'Z')) { return QString(QChar(static_cast(VirtualKey))); } if ((VirtualKey >= '0') && (VirtualKey <= '9')) { return QString(QChar(static_cast(VirtualKey))); } if ((VirtualKey >= VK_F1) && (VirtualKey <= VK_F24)) { return QStringLiteral("F%1").arg(VirtualKey - VK_F1 + 1); } switch (VirtualKey) { case VK_CONTROL: case VK_LCONTROL: case VK_RCONTROL: return QStringLiteral("Ctrl"); case VK_SHIFT: case VK_LSHIFT: case VK_RSHIFT: return QStringLiteral("Shift"); case VK_MENU: case VK_LMENU: case VK_RMENU: return QStringLiteral("Alt"); case VK_LWIN: case VK_RWIN: return QStringLiteral("Win"); case VK_RETURN: return IsE0 ? QStringLiteral("NumEnter") : QStringLiteral("Enter"); case VK_SPACE: return QStringLiteral("Space"); case VK_TAB: return QStringLiteral("Tab"); case VK_ESCAPE: return QStringLiteral("Esc"); case VK_BACK: return QStringLiteral("Backspace"); case VK_DELETE: return QStringLiteral("Delete"); case VK_INSERT: return QStringLiteral("Insert"); case VK_HOME: return QStringLiteral("Home"); case VK_END: return QStringLiteral("End"); case VK_PRIOR: return QStringLiteral("PageUp"); case VK_NEXT: return QStringLiteral("PageDown"); case VK_LEFT: return QStringLiteral("Left"); case VK_RIGHT: return QStringLiteral("Right"); case VK_UP: return QStringLiteral("Up"); case VK_DOWN: return QStringLiteral("Down"); case VK_CAPITAL: return QStringLiteral("CapsLock"); case VK_SNAPSHOT: return QStringLiteral("PrintScreen"); case VK_SCROLL: return QStringLiteral("ScrollLock"); case VK_PAUSE: return QStringLiteral("Pause"); case VK_NUMPAD0: return QStringLiteral("Num0"); case VK_NUMPAD1: return QStringLiteral("Num1"); case VK_NUMPAD2: return QStringLiteral("Num2"); case VK_NUMPAD3: return QStringLiteral("Num3"); case VK_NUMPAD4: return QStringLiteral("Num4"); case VK_NUMPAD5: return QStringLiteral("Num5"); case VK_NUMPAD6: return QStringLiteral("Num6"); case VK_NUMPAD7: return QStringLiteral("Num7"); case VK_NUMPAD8: return QStringLiteral("Num8"); case VK_NUMPAD9: return QStringLiteral("Num9"); case VK_DIVIDE: return QStringLiteral("Num/"); case VK_MULTIPLY: return QStringLiteral("Num*"); case VK_SUBTRACT: return QStringLiteral("Num-"); case VK_ADD: return QStringLiteral("Num+"); case VK_DECIMAL: return QStringLiteral("Num."); case VK_OEM_COMMA: return QStringLiteral("Comma"); case VK_OEM_PERIOD: return QStringLiteral("Period"); case VK_OEM_1: return QStringLiteral("Semicolon"); case VK_OEM_2: return QStringLiteral("Slash"); case VK_OEM_3: return QStringLiteral("Grave"); case VK_OEM_4: return QStringLiteral("LeftBracket"); case VK_OEM_5: return QStringLiteral("Backslash"); case VK_OEM_6: return QStringLiteral("RightBracket"); case VK_OEM_7: return QStringLiteral("Quote"); case VK_OEM_MINUS: return QStringLiteral("Minus"); case VK_OEM_PLUS: return QStringLiteral("Equal"); default: return QString(); } } } // namespace void App_UIWindow::App_Func_StartSequenceRecording() { const Lgc_FunctionFeature_Definition Feature = Lgc_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, appSelectedFeatureId); if (Feature.Id <= 0 || !App_Func_IsKeyRecordFeatureType(Feature.Type)) { return; } appIsSequenceRecording = true; appSequenceRecordingPressedKeySet.clear(); appLgcState.IsFunctionSequenceRecording = true; { QSignalBlocker Blocker(appFeatureSequenceEdit); appFeatureSequenceEdit->setText(QString()); } App_Func_SaveFeatureFromUi(); appLgcState.TextFunctionStatus = Feature.Type == Lgc_FunctionFeature_Type::KeySequence ? QStringLiteral("已开始录入快捷键序列,接下来按下任意键盘按键即可按组追加。") : QStringLiteral("已开始录入快捷键,请按下目标组合键。"); App_Func_UpdateSequenceRecordingUi(); if (appFeatureSequenceEdit != nullptr) { appFeatureSequenceEdit->setFocus(Qt::OtherFocusReason); } App_Func_RefreshUi(); } void App_UIWindow::App_Func_StopSequenceRecording() { appIsSequenceRecording = false; appSequenceRecordingPressedKeySet.clear(); appLgcState.IsFunctionSequenceRecording = false; appLgcState.TextFunctionStatus = QStringLiteral("已退出录入,当前功能键配置已保存。"); App_Func_UpdateSequenceRecordingUi(); App_Func_RefreshUi(); } void App_UIWindow::App_Func_UpdateSequenceRecordingUi() { const Lgc_FunctionFeature_Definition Feature = Lgc_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, appSelectedFeatureId); const bool HasFeature = Feature.Id > 0; const bool CanRecord = HasFeature && App_Func_IsKeyRecordFeatureType(Feature.Type); const bool IsLocked = appIsSequenceRecording; if (appFeatureTable != nullptr) { appFeatureTable->setEnabled(!IsLocked); } if (appFeatureAddButton != nullptr) { appFeatureAddButton->setEnabled(!IsLocked); } if (appFeatureDeleteButton != nullptr) { appFeatureDeleteButton->setEnabled(HasFeature && !IsLocked); } if (appFeatureNameEdit != nullptr) { appFeatureNameEdit->setEnabled(HasFeature && !IsLocked); } if (appFeatureDescriptionEdit != nullptr) { appFeatureDescriptionEdit->setEnabled(HasFeature && !IsLocked); } if (appFeatureTypeCombo != nullptr) { appFeatureTypeCombo->setEnabled(HasFeature && !IsLocked); } if (appFeatureWebsiteEdit != nullptr) { appFeatureWebsiteEdit->setEnabled(HasFeature && !IsLocked); } if (appFeatureSequenceEdit != nullptr) { appFeatureSequenceEdit->setReadOnly(appIsSequenceRecording); } if (appFeatureSequenceRecordStartButton != nullptr) { appFeatureSequenceRecordStartButton->setEnabled(CanRecord && !appIsSequenceRecording); } if (appFeatureSequenceRecordStopButton != nullptr) { appFeatureSequenceRecordStopButton->setEnabled(CanRecord && appIsSequenceRecording); } } bool App_UIWindow::App_Func_HandleSequenceRecordMessage(void* p_Message) { if (!appIsSequenceRecording) { return false; } RAWKEYBOARD Keyboard = {}; if (!App_Func_TryGetRawKeyboard(p_Message, &Keyboard)) { return false; } const QString Token = App_Func_GetRecordedKeyToken(Keyboard); if (Token.isEmpty()) { return false; } const bool IsPressed = (Keyboard.Flags & RI_KEY_BREAK) == 0; if (IsPressed) { if (appSequenceRecordingPressedKeySet.contains(Token)) { return false; } appSequenceRecordingPressedKeySet.insert(Token); if (!App_Func_IsModifierRecordToken(Token)) { App_Func_AppendRecordedSequenceToken(Token); return true; } return false; } appSequenceRecordingPressedKeySet.remove(Token); return false; } void App_UIWindow::App_Func_AppendRecordedSequenceToken(const QString& Token) { if (Token.isEmpty() || appFeatureSequenceEdit == nullptr) { return; } const Lgc_FunctionFeature_Definition Feature = Lgc_FunctionButton_GetFeature(appLgcState.FunctionButtonConfig, appSelectedFeatureId); if (Feature.Id <= 0 || !App_Func_IsKeyRecordFeatureType(Feature.Type)) { return; } const QString CombinationText = App_Func_GetRecordedCombinationText(appSequenceRecordingPressedKeySet, Token); if (CombinationText.isEmpty()) { return; } const QString OldText = appFeatureSequenceEdit->text().trimmed(); const QString NewText = Feature.Type == Lgc_FunctionFeature_Type::KeySequence ? (OldText.isEmpty() ? CombinationText : QStringLiteral("%1 -> %2").arg(OldText, CombinationText)) : CombinationText; { QSignalBlocker Blocker(appFeatureSequenceEdit); appFeatureSequenceEdit->setText(NewText); appFeatureSequenceEdit->setCursorPosition(NewText.size()); } App_Func_SaveFeatureFromUi(); appLgcState.TextFunctionStatus = QStringLiteral("录入中:%1").arg(NewText); App_Func_RefreshUi(); } void App_UIWindow::App_Func_HandleUiKeyPressed(quint16 Usage) { QString TextStatus; if (Lgc_FunctionButton_HasUsageFeature(appLgcState.FunctionButtonConfig, Usage)) { if (!Lgc_FunctionButton_RunBinding(&appLgcState, Usage, &TextStatus)) { TextStatus = QStringLiteral("%1 当前没有可执行功能。") .arg(Lgc_FunctionButton_GetUsageShortText(Usage)); } } else { if (Lgc_FunctionButton_SendUsageToWindows(Usage, true)) { appUiPressedUsageSet.insert(Usage); TextStatus = QStringLiteral("已模拟按下 %1。") .arg(Lgc_FunctionButton_GetUsageShortText(Usage)); } else { TextStatus = QStringLiteral("模拟按下 %1 失败。") .arg(Lgc_FunctionButton_GetUsageShortText(Usage)); } } if (!TextStatus.isEmpty()) { appLgcState.TextFunctionStatus = TextStatus; } App_Func_RefreshUi(); } void App_UIWindow::App_Func_HandleUiKeyReleased(quint16 Usage) { if (!appUiPressedUsageSet.remove(Usage)) { return; } appLgcState.TextFunctionStatus = Lgc_FunctionButton_SendUsageToWindows(Usage, false) ? QStringLiteral("已模拟抬起 %1。").arg(Lgc_FunctionButton_GetUsageShortText(Usage)) : QStringLiteral("模拟抬起 %1 失败。").arg(Lgc_FunctionButton_GetUsageShortText(Usage)); App_Func_RefreshUi(); } void App_UIWindow::App_Func_ShowKeyMenu(quint16 Usage, const QPoint& GlobalPos) { const int CurrentFeatureId = Lgc_FunctionButton_GetUsageFeatureId(appLgcState.FunctionButtonConfig, Usage); QMenu Menu(this); QAction* p_NoneAction = Menu.addAction(QStringLiteral("无功能")); p_NoneAction->setCheckable(true); p_NoneAction->setChecked(CurrentFeatureId <= 0); p_NoneAction->setData(0); const QVector FeatureIdList = Lgc_FunctionButton_GetFeatureIdList(appLgcState.FunctionButtonConfig); if (!FeatureIdList.isEmpty()) { Menu.addSeparator(); for (int FeatureId : FeatureIdList) { QAction* p_Action = Menu.addAction(QStringLiteral("绑定到 %1").arg(App_Func_GetFeatureNameById(FeatureId))); p_Action->setCheckable(true); p_Action->setChecked(FeatureId == CurrentFeatureId); p_Action->setData(FeatureId); p_Action->setToolTip(App_Func_GetFeatureDescriptionById(FeatureId)); } } else { Menu.addSeparator(); QAction* p_EmptyAction = Menu.addAction(QStringLiteral("暂无功能,请先到功能表添加")); p_EmptyAction->setEnabled(false); } Menu.addSeparator(); QAction* p_OpenFeaturePageAction = Menu.addAction(QStringLiteral("打开功能表")); p_OpenFeaturePageAction->setData(-1); QAction* p_SelectedAction = Menu.exec(GlobalPos); if (p_SelectedAction == nullptr) { return; } const int ActionData = p_SelectedAction->data().toInt(); if (ActionData == -1) { App_Func_SelectFeature(CurrentFeatureId, true); return; } App_Func_AssignFeatureToUsage(Usage, ActionData); if (ActionData > 0) { App_Func_SelectFeature(ActionData); } } } // namespace APP