C++模拟键盘输入字符串异常:求精准输入修正方案
Fixing Precise Keyboard Input Simulation in C++
Got it, let's tackle this problem head-on. Your current code has three main issues causing incorrect output:
- It doesn't account for modifier keys (like Shift) required for uppercase letters and special symbols.
- It ignores the current state of Caps Lock, which messes up letter casing.
- You're only sending a single key press event per character without releasing each key individually—your final single key-up isn't enough for all inputs.
Here's a revised version of your code that handles all these edge cases, ensuring precise input no matter the keyboard state:
#define WINVER 0x0500 #include <windows.h> #include <string> #include <cctype> void SimulateKeyPress(WORD virtualKey, bool pressShift = false, unsigned int pauseTime = 0) { INPUT input[4] = {0}; int inputCount = 0; // Press Shift if required if (pressShift) { input[inputCount].type = INPUT_KEYBOARD; input[inputCount].ki.wVk = VK_SHIFT; inputCount++; } // Press the target key input[inputCount].type = INPUT_KEYBOARD; input[inputCount].ki.wVk = virtualKey; inputCount++; // Wait for the specified pause before releasing if (pauseTime > 0) { Sleep(pauseTime); } // Release the target key input[inputCount].type = INPUT_KEYBOARD; input[inputCount].ki.wVk = virtualKey; input[inputCount].ki.dwFlags = KEYEVENTF_KEYUP; inputCount++; // Release Shift if we pressed it if (pressShift) { input[inputCount].type = INPUT_KEYBOARD; input[inputCount].ki.wVk = VK_SHIFT; input[inputCount].ki.dwFlags = KEYEVENTF_KEYUP; inputCount++; } // Send all input events in sequence SendInput(inputCount, input, sizeof(INPUT)); } void SendPreciseString(const std::string& str, unsigned int pauseTime) { for (char c : str) { SHORT keyInfo = VkKeyScanA(c); if (keyInfo == -1) { // Skip characters that can't be represented with the current keyboard layout continue; } WORD virtualKey = LOBYTE(keyInfo); WORD requiredModifiers = HIBYTE(keyInfo); bool needShift = (requiredModifiers & 1) != 0; // Adjust Shift requirement based on Caps Lock for alphabetic characters if (std::isalpha(c)) { bool capsLockActive = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; bool isTargetUpperCase = std::isupper(c); // Flip Shift need if Caps Lock would invert the desired case if ((capsLockActive && isTargetUpperCase) || (!capsLockActive && !isTargetUpperCase)) { needShift = false; } else if ((capsLockActive && !isTargetUpperCase) || (!capsLockActive && isTargetUpperCase)) { needShift = true; } } SimulateKeyPress(virtualKey, needShift, pauseTime); } } int main(int argc, char** argv) { // Validate command line arguments to avoid crashes if (argc != 3) { MessageBoxA(NULL, "Usage: ProgramName <InputString> <PauseMs>", "Error", MB_OK | MB_ICONERROR); return 1; } std::string inputStr = argv[1]; unsigned int pauseTime = std::stoi(argv[2]); SendPreciseString(inputStr, pauseTime); return 0; }
Key Improvements Explained:
SimulateKeyPressfunction: Handles full key press/release cycles, including modifier keys like Shift. It sends all necessary events in the correct order to mimic real keyboard input.- Caps Lock Awareness: For alphabetic characters, we check the current Caps Lock state and adjust whether we need to press Shift—this ensures your input matches the desired string regardless of the keyboard's initial Caps Lock status.
- Modifier Key Detection: Uses
VkKeyScanAto extract both the virtual key code and required modifiers (like Shift for%or{) for each character. - Basic Error Handling: Added validation for command line arguments to guide users if they input incorrect parameters.
This code will correctly output PASS_INPUT as uppercase (even if Caps Lock is off) and %9Xa{ exactly as written, no matter the initial keyboard state.
内容的提问来源于stack exchange,提问作者Aniruddh Anna
相关产品推荐
相关产品推荐

