|
|
本帖最后由 磊之茶 于 2026-8-19 15:25 编辑
乱码版发不出来,只能像上面那样只有一小段,其余发布后异常消失
以下是修改版
- /*
- * ============================================================================
- * TypingSimulator - 文本文件模拟键盘输入工具
- * ============================================================================
- * 功能:读取 TXT 文件内容,通过 SendInput API 逐字模拟键盘输入
- * 可绕过网页的"禁止粘贴"限制(因为本质是模拟硬件键盘事件)
- *
- * 适用:Windows 11 + 华为笔记本(实际支持所有 Windows 系统)
- * 编译:gcc typing_simulator.c -o typing_simulator.exe -luser32 -mwindows
- * 或 cl typing_simulator.c user32.lib
- *
- * 使用流程:
- * 1. 运行程序,输入 TXT 文件路径
- * 2. 程序倒计时 5 秒(给你时间切换到目标网页输入框)
- * 3. 自动开始逐字"打字"输入文件内容
- *
- * 注意:
- * - TXT 文件请保存为 UTF-8 编码(含 BOM 也可)
- * - 输入前请确保目标输入框已获得焦点(光标在闪烁)
- * - 输入过程中不要动键盘鼠标,以免干扰
- * ============================================================================
- */
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /*
- * 发送单个 Unicode 字符(核心函数)
- * 原理:使用 SendInput + KEYEVENTF_UNICODE
- * 这种方式直接向系统输入队列注入 Unicode 字符,
- * 完全绕过了输入法和粘贴检测机制
- */
- void SendUnicodeChar(wchar_t ch)
- {
- INPUT input = {0};
- /* 按下事件 */
- input.type = INPUT_KEYBOARD;
- input.ki.wVk = 0; /* 使用 Unicode 时 wVk 必须为 0 */
- input.ki.wScan = ch; /* 直接填充 Unicode 字符 */
- input.ki.dwFlags = KEYEVENTF_UNICODE;
- input.ki.time = 0;
- input.ki.dwExtraInfo = 0;
- /* 释放事件 */
- input.type = INPUT_KEYBOARD;
- input.ki.wVk = 0;
- input.ki.wScan = ch;
- input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
- input.ki.time = 0;
- input.ki.dwExtraInfo = 0;
- SendInput(2, input, sizeof(INPUT));
- }
- /*
- * 发送一个虚拟键(用于发送回车、Tab 等特殊键)
- */
- void SendVirtualKey(WORD vk)
- {
- INPUT input = {0};
- input.type = INPUT_KEYBOARD;
- input.ki.wVk = vk;
- input.ki.dwFlags = 0;
- input.type = INPUT_KEYBOARD;
- input.ki.wVk = vk;
- input.ki.dwFlags = KEYEVENTF_KEYUP;
- SendInput(2, input, sizeof(INPUT));
- }
- /*
- * 模拟"打字"一个字符串
- * text : 要输入的宽字符字符串
- * charDelay: 每个字符之间的延迟(毫秒),推荐 30~100
- */
- void SimulateTyping(const wchar_t* text, int charDelay)
- {
- for (int i = 0; text[i] != L'\0'; i++)
- {
- wchar_t ch = text[i];
- if (ch == L'\n')
- {
- /* 换行 -> 发送回车键 */
- SendVirtualKey(VK_RETURN);
- }
- else if (ch == L'\t')
- {
- /* Tab -> 发送 Tab 键 */
- SendVirtualKey(VK_TAB);
- }
- else if (ch == L'\r')
- {
- /* 忽略 \r(Windows 换行符的一部分) */
- continue;
- }
- else
- {
- /* 普通字符(含中文)-> Unicode 方式发送 */
- SendUnicodeChar(ch);
- }
- /* 字符间延迟,模拟真人打字节奏 */
- if (charDelay > 0)
- Sleep(charDelay);
- }
- }
- /*
- * 读取 UTF-8 编码的文本文件,返回宽字符字符串
- * 自动处理 BOM(字节顺序标记)
- */
- wchar_t* ReadTxtFileToWString(const char* filePath)
- {
- FILE* fp = fopen(filePath, "rb"); /* 二进制模式打开 */
- if (fp == NULL)
- {
- printf("[错误] 无法打开文件: %s\n", filePath);
- return NULL;
- }
- /* 获取文件大小 */
- fseek(fp, 0, SEEK_END);
- long fileSize = ftell(fp);
- fseek(fp, 0, SEEK_SET);
- if (fileSize <= 0)
- {
- printf("[错误] 文件为空或读取失败\n");
- fclose(fp);
- return NULL;
- }
- /* 读取全部字节 */
- char* utf8Bytes = (char*)malloc(fileSize + 1);
- if (utf8Bytes == NULL)
- {
- printf("[错误] 内存分配失败\n");
- fclose(fp);
- return NULL;
- }
- fread(utf8Bytes, 1, fileSize, fp);
- utf8Bytes[fileSize] = '\0';
- fclose(fp);
- /* 跳过 UTF-8 BOM(EF BB BF) */
- char* ptr = utf8Bytes;
- if (fileSize >= 3 &&
- (unsigned char)utf8Bytes == 0xEF &&
- (unsigned char)utf8Bytes == 0xBB &&
- (unsigned char)utf8Bytes == 0xBF)
- {
- ptr += 3;
- }
- /* 计算转换后的宽字符长度 */
- int wideLen = MultiByteToWideChar(CP_UTF8, 0, ptr, -1, NULL, 0);
- if (wideLen == 0)
- {
- printf("[错误] UTF-8 转宽字符失败(错误码: %lu)\n", GetLastError());
- free(utf8Bytes);
- return NULL;
- }
- /* 分配并转换 */
- wchar_t* wideStr = (wchar_t*)malloc(wideLen * sizeof(wchar_t));
- if (wideStr == NULL)
- {
- printf("[错误] 宽字符内存分配失败\n");
- free(utf8Bytes);
- return NULL;
- }
- MultiByteToWideChar(CP_UTF8, 0, ptr, -1, wideStr, wideLen);
- free(utf8Bytes);
- return wideStr;
- }
- /*
- * 倒计时提示
- */
- void Countdown(int seconds)
- {
- for (int i = seconds; i > 0; i--)
- {
- printf("\r倒计时 %2d 秒 —— 请切换到目标网页输入框...", i);
- fflush(stdout);
- Sleep(1000);
- }
- printf("\r倒计时结束!开始输入! \n");
- }
- /*
- * 清屏后打印程序标题
- */
- void PrintBanner(void)
- {
- printf("\n");
- printf("========================================\n");
- printf("= TypingSimulator - 模拟键盘输入工具 v1.0 =\n");
- printf("= =\n");
- printf("= 原理: SendInput + KEYEVENTF_UNICODE =\n");
- printf("= 效果: 模拟真实键盘逐字输入,绕过网页禁止粘贴限制 =\n");
- printf("= 适用: Windows 11 (华为/联想/戴尔等所有品牌) =\n");
- printf("========================================================\n\n");
- }
- int main(int argc, char* argv[])
- {
- PrintBanner();
- /* ---------- 1. 获取文件路径 ---------- */
- char filePath[MAX_PATH];
- if (argc > 1)
- {
- strcpy(filePath, argv);
- }
- else
- {
- printf("请输入 TXT 文件路径(支持拖拽文件到窗口)\n> ");
- fgets(filePath, MAX_PATH, stdin);
- /* 去掉换行符 */
- filePath[strcspn(filePath, "\r\n")] = '\0';
- }
- if (strlen(filePath) == 0)
- {
- printf("[错误] 文件路径为空\n");
- system("pause");
- return 1;
- }
- /* ---------- 2. 读取文件内容 ---------- */
- printf("\n[信息] 正在读取文件: %s\n", filePath);
- wchar_t* text = ReadTxtFileToWString(filePath);
- if (text == NULL)
- {
- system("pause");
- return 1;
- }
- /* 统计字符数 */
- int charCount = wcslen(text);
- printf("[信息] 文件读取成功,共 %d 个字符\n", charCount);
- /* 预览前 100 个字符 */
- wprintf(L"[预览] %.*s%s\n",
- (charCount > 50 ? 50 : charCount), text,
- (charCount > 50 ? L"..." : L""));
- /* ---------- 3. 获取输入速度 ---------- */
- int delayMs = 50; /* 默认 50ms */
- printf("\n请输入每个字符之间的延迟(毫秒),默认 50,回车确认\n> ");
- char delayInput;
- fgets(delayInput, 32, stdin);
- delayInput[strcspn(delayInput, "\r\n")] = '\0';
- if (strlen(delayInput) > 0)
- {
- int parsed = atoi(delayInput);
- if (parsed >= 0 && parsed <= 5000)
- delayMs = parsed;
- }
- printf("[信息] 延迟设置为 %d ms/字符\n", delayMs);
- /* ---------- 4. 倒计时 ---------- */
- printf("\n[提示] 你有 5 秒钟时间切换到目标网页,并点击输入框让光标闪烁\n");
- Countdown(5);
- /* ---------- 5. 开始模拟输入 ---------- */
- printf("[运行] 正在模拟键盘输入...\n");
- /*
- * 先检查一下当前前台窗口,提醒用户
- */
- HWND fg = GetForegroundWindow();
- if (fg == NULL)
- printf("[警告] 未检测到前台窗口,请确认已切换到目标网页\n");
- /*
- * 核心调用:逐字模拟输入
- * 使用 Unicode 方式,中文/英文/标点全部兼容
- */
- SimulateTyping(text, delayMs);
- printf("[完成] 输入完毕!共输入 %d 个字符\n", charCount);
- /* 清理 */
- free(text);
- printf("\n按任意键退出...");
- system("pause >nul");
- return 0;
- }
复制代码 修改版不能运行但是乱码版正常运行,修改版仅仅修改了注释和中文部分 |
|