本文对以下相似问题具有参考价值:爱写作不让复制粘贴怎么办?被设置不能复制粘贴怎么办?如何解决爱写作不让复制粘贴问题;“允许粘贴”关闭/被关闭怎么办?模拟键盘一个一个打字的C语言程序
正文:为了应对Iwrite作业禁止粘贴的问题,许多圈内人已提出解决方案。不过,作为计算机专业且热爱C语言编程的学生,我仍然尝试编写了一个C语言小程序,通过模拟键盘输入,逐字打字,以规避粘贴检测。也算是学以致用,把知识用到实践中去。(文章末尾我会放置点开即用的程序软件,不用编程直接使用)
不说废话了,直接源代码:
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAX_STRING_LENGTH 1024
#define BUFFER_SIZE (MAX_STRING_LENGTH * 10)
// 保存原始控制台属性
WORD originalAttributes;
void SetColor(int ForgC) {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
wchar_t wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hStdOut, wColor);
}
}
void TypeCharacter(char c) {
SHORT vkCode = VkKeyScanA(c);
if (vkCode == -1) {
return; // 跳过无效字符
}
BYTE key = LOBYTE(vkCode);
bool needShift = HIBYTE(vkCode) & 0x01;
bool isCapsLock = (GetKeyState(VK_CAPITAL) & 0x0001);
needShift ^= isCapsLock; // 考虑大写锁定状态
INPUT inputs[4] = {0};
int inputCount = 0;
// Shift按下
if (needShift) {
inputs[inputCount].type = INPUT_KEYBOARD;
inputs[inputCount].ki.wVk = VK_SHIFT;
inputCount++;
}
// 字符键按下
inputs[inputCount].type = INPUT_KEYBOARD;
inputs[inputCount].ki.wVk = key;
inputCount++;
// 字符键释放
inputs[inputCount].type = INPUT_KEYBOARD;
inputs[inputCount].ki.wVk = key;
inputs[inputCount].ki.dwFlags = KEYEVENTF_KEYUP;
inputCount++;
// Shift释放
if (needShift) {
inputs[inputCount].type = INPUT_KEYBOARD;
inputs[inputCount].ki.wVk = VK_SHIFT;
inputs[inputCount].ki.dwFlags = KEYEVENTF_KEYUP;
inputCount++;
}
SendInput(inputCount, inputs, sizeof(INPUT));
}
void PressEnter() {
INPUT inputs[2] = {0};
// 按下Enter键
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_RETURN;
// 释放Enter键
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = VK_RETURN;
inputs[1].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(2, inputs, sizeof(INPUT));
}
int main() {
char str[MAX_STRING_LENGTH] = {0};
char buffer[BUFFER_SIZE] = {0};
size_t buffer_len = 0;
// 保存原始控制台属性
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hStdOut, (PCONSOLE_SCREEN_BUFFER_INFO)&originalAttributes);
SetColor(11);
printf("欢迎使用模拟键盘打字(仅限英语版) ");
SetColor(8);
printf("作者:孤星寒月 2024年12月22日\n\n");
SetColor(14);
printf("使用说明(简洁):\n");
printf("1. 输入文本(支持换行)\n");
printf("2. 单独输入#结束输入\n");
printf("3. 10秒后自动开始模拟输入\n\n");
SetColor(15);
printf("详细说明:\n");
printf("- 用Enter换行,用#+Enter结束输入\n");
printf("- 文本中的#会被转换为换行\n");
printf("- 确保最后切换到英文输入法和目标窗口\n\n");
SetColor(10);
printf("请输入文本(以单独#结束):\n");
SetColor(15);
// 读取输入
while (fgets(str, MAX_STRING_LENGTH, stdin)) {
// 移除换行符
size_t len = strcspn(str, "\n");
str[len] = 0;
// 检查结束标记
if (strcmp(str, "#") == 0) {
break;
}
// 处理#替换
char processed[MAX_STRING_LENGTH] = {0};
strncpy(processed, str, sizeof(processed)-1);
char *p = processed;
while ((p = strchr(p, '#')) != NULL) {
*p++ = '\n';
}
// 计算剩余空间
size_t remain = BUFFER_SIZE - buffer_len - 1;
size_t add_len = strlen(processed);
if (add_len >= remain) {
SetColor(12);
printf("\n错误:输入内容过长!\n");
break;
}
// 追加内容(保留用户原始换行)
strcat(buffer + buffer_len, processed);
buffer_len += add_len;
// 添加换行符
if (buffer_len < BUFFER_SIZE-1) {
buffer[buffer_len++] = '\n';
buffer[buffer_len] = 0;
}
}
SetColor(10);
printf("\n10秒后开始打印,请准备...\n");
Sleep(10000);
// 执行模拟输入
const char *ptr = buffer;
while (*ptr) {
if (*ptr == '\n') {
PressEnter();
} else {
TypeCharacter(*ptr);
}
ptr++;
Sleep(50);
}
// 恢复原始控制台颜色
SetColor(15);
printf("\n打印完成,请检查结果。\n");
printf("3秒后自动退出...\n");
Sleep(3000);
return 0;
}