#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string.h>
#define VK_E 0x45
#define VK_Q 0x51
#define VK_V 0x56
#define IDC_BUTTON_START 101
#define IDC_BUTTON_STOP 102
#define IDC_EDIT_INTERVAL 103
#define IDC_COMBO_HOTKEY 104
#define TIMER_ID_RESET_INTERVAL 1
HINSTANCE
g_hInst = NULL;
HHOOK
g_hHook = NULL;
BOOL
g_bHookInstalled = FALSE;
HWND
g_hMainWnd = NULL;
int
g_nInputInterval = 20;
BOOL
g_bTerminateInput = FALSE;
int
g_nSelectedHotkey = 0;
HANDLE
g_hInputThread = NULL;
WCHAR
* g_pszClipboardText = NULL;
LRESULT
CALLBACK KeyboardProc(
int
nCode,
WPARAM
wParam,
LPARAM
lParam);
LRESULT
CALLBACK WndProc(
HWND
hWnd,
UINT
message,
WPARAM
wParam,
LPARAM
lParam);
void
SetClipboardHook();
void
RemoveClipboardHook();
void
SimulateTextInput(
const
WCHAR
* text);
void
SimulateCharInput(
WCHAR
ch);
void
CreateMainWindow();
void
UpdateUIState();
DWORD
WINAPI SimulateTextInputThread(
LPVOID
lpParam);
BOOL
APIENTRY DllMain(
HMODULE
hModule,
DWORD
ul_reason_for_call,
LPVOID
lpReserved) {
g_hInst = (
HINSTANCE
)hModule;
return
TRUE;
}
LRESULT
CALLBACK KeyboardProc(
int
nCode,
WPARAM
wParam,
LPARAM
lParam) {
if
(nCode >= 0) {
KBDLLHOOKSTRUCT* pkbllhs = (KBDLLHOOKSTRUCT*)lParam;
if
(wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) {
BOOL
bBlock = FALSE;
BOOL
bAltPressed = (GetAsyncKeyState(VK_MENU) & 0x8000) != 0;
BOOL
bCtrlPressed = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0;
switch
(g_nSelectedHotkey) {
case
0:
if
(pkbllhs->vkCode == VK_E && bCtrlPressed && !bAltPressed) {
bBlock = TRUE;
}
break
;
case
1:
if
(pkbllhs->vkCode == VK_Q && bCtrlPressed && !bAltPressed) {
bBlock = TRUE;
}
break
;
case
2:
if
(pkbllhs->vkCode == VK_V && bCtrlPressed && !bAltPressed) {
bBlock = TRUE;
}
break
;
case
3:
if
(pkbllhs->vkCode == VK_V && bAltPressed && !bCtrlPressed) {
bBlock = TRUE;
}
break
;
}
if
(bBlock) {
if
(g_hInputThread != NULL) {
g_bTerminateInput = TRUE;
}
else
{
if
(OpenClipboard(NULL)) {
HANDLE
hData = GetClipboardData(CF_UNICODETEXT);
if
(hData != NULL) {
g_pszClipboardText = (
WCHAR
*)GlobalLock(hData);
if
(g_pszClipboardText != NULL) {
g_hInputThread = CreateThread(NULL, 0, SimulateTextInputThread, (
LPVOID
)g_pszClipboardText, 0, NULL);
}
GlobalUnlock(hData);
}
CloseClipboard();
}
}
return
1;
}
}
}
return
CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
void
SetClipboardHook() {
if
(!g_bHookInstalled) {
g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, g_hInst, 0);
if
(g_hHook != NULL) {
g_bHookInstalled = TRUE;
UpdateUIState();
}
}
}
void
RemoveClipboardHook() {
if
(g_bHookInstalled) {
UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
g_bHookInstalled = FALSE;
UpdateUIState();
}
}
void
SimulateTextInput(
const
WCHAR
* text) {
g_bTerminateInput = FALSE;
for
(
const
WCHAR
* p = text; *p != L
'\0'
&& !g_bTerminateInput; ++p) {
SimulateCharInput(*p);
Sleep(g_nInputInterval);
}
if
(g_bTerminateInput) {
g_bTerminateInput = FALSE;
}
}
void
SimulateCharInput(
WCHAR
ch) {
INPUT input[2] = {0};
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = 0;
input[0].ki.wScan = ch;
input[0].ki.dwFlags = KEYEVENTF_UNICODE;
input[1].type = INPUT_KEYBOARD;
input[1].ki.wVk = 0;
input[1].ki.wScan = ch;
input[1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
SendInput(2, input,
sizeof
(INPUT));
}
void
CreateMainWindow() {
WNDCLASSEX wc = {0};
wc.cbSize =
sizeof
(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = g_hInst;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName =
"ClipboardHookWndClass"
;
if
(RegisterClassEx(&wc)) {
g_hMainWnd = CreateWindowEx(
0,
"ClipboardHookWndClass"
,
"剪贴板文本输入器1.0"
,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 350, 250,
NULL,
NULL,
g_hInst,
NULL
);
if
(g_hMainWnd) {
ShowWindow(g_hMainWnd, SW_SHOW);
UpdateUIState();
}
}
}
void
UpdateUIState() {
if
(g_hMainWnd) {
EnableWindow(GetDlgItem(g_hMainWnd, IDC_BUTTON_START), !g_bHookInstalled);
EnableWindow(GetDlgItem(g_hMainWnd, IDC_BUTTON_STOP), g_bHookInstalled);
}
}
LRESULT
CALLBACK WndProc(
HWND
hWnd,
UINT
message,
WPARAM
wParam,
LPARAM
lParam) {
static
HWND
hEditInterval = NULL;
static
HWND
hComboHotkey = NULL;
switch
(message) {
case
WM_CREATE:
{
CreateWindow(
"BUTTON"
,
"开启"
,
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
20, 30, 80, 30, hWnd, (
HMENU
)IDC_BUTTON_START, g_hInst, NULL);
CreateWindow(
"BUTTON"
,
"关闭"
,
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
120, 30, 80, 30, hWnd, (
HMENU
)IDC_BUTTON_STOP, g_hInst, NULL);
hEditInterval = CreateWindow(
"EDIT"
,
"50"
,
WS_TABSTOP | WS_VISIBLE | WS_CHILD | ES_NUMBER,
170, 80, 140, 30, hWnd, (
HMENU
)IDC_EDIT_INTERVAL, g_hInst, NULL);
CreateWindow(
"STATIC"
,
"输入间隔(毫秒):"
,
WS_VISIBLE | WS_CHILD | SS_LEFT,
20, 80, 130, 30, hWnd, NULL, g_hInst, NULL);
CreateWindow(
"STATIC"
,
"快捷键(再按终止)):"
,
WS_VISIBLE | WS_CHILD | SS_LEFT,
20, 120, 150, 100, hWnd, NULL, g_hInst, NULL);
hComboHotkey = CreateWindowW(L
"COMBOBOX"
, NULL,
WS_TABSTOP | WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST,
160, 120, 165, 100, hWnd, (
HMENU
)IDC_COMBO_HOTKEY, g_hInst, NULL);
SendMessageW(hComboHotkey, CB_ADDSTRING, 0, (
LPARAM
)L
"Ctrl+E"
);
SendMessageW(hComboHotkey, CB_ADDSTRING, 0, (
LPARAM
)L
"Ctrl+Q"
);
SendMessageW(hComboHotkey, CB_ADDSTRING, 0, (
LPARAM
)L
"Ctrl+V"
);
SendMessageW(hComboHotkey, CB_ADDSTRING, 0, (
LPARAM
)L
"Alt+V"
);
SendMessageW(hComboHotkey, CB_SETCURSEL, 0, 0);
SetTimer(hWnd, TIMER_ID_RESET_INTERVAL, 100, NULL);
UpdateUIState();
break
;
}
case
WM_CTLCOLORSTATIC:
{
HDC
hdc = (
HDC
)wParam;
HWND
hwndStatic = (
HWND
)lParam;
SetBkColor(hdc, RGB(255, 255, 255));
return
(
LRESULT
)GetStockObject(WHITE_BRUSH);
}
case
WM_COMMAND:
{
int
wmId = LOWORD(wParam);
if
(wmId == IDC_BUTTON_START) {
SetClipboardHook();
}
else
if
(wmId == IDC_BUTTON_STOP) {
RemoveClipboardHook();
}
else
if
(wmId == IDC_EDIT_INTERVAL) {
if
(HIWORD(wParam) == EN_CHANGE) {
TCHAR
buffer[32];
GetWindowText(hEditInterval, buffer, 32);
g_nInputInterval = _ttoi(buffer);
}
}
else
if
(wmId == IDC_COMBO_HOTKEY) {
if
(HIWORD(wParam) == CBN_SELCHANGE) {
int
index = SendMessage(hComboHotkey, CB_GETCURSEL, 2, 0);
g_nSelectedHotkey = index;
}
}
break
;
}
case
WM_TIMER:
{
if
(wParam == TIMER_ID_RESET_INTERVAL) {
KillTimer(hWnd, TIMER_ID_RESET_INTERVAL);
g_nInputInterval = 20;
TCHAR
buffer[32];
_itot(g_nInputInterval, buffer, 10);
SetWindowText(hEditInterval, buffer);
}
break
;
}
case
WM_CLOSE:
RemoveClipboardHook();
DestroyWindow(hWnd);
break
;
case
WM_DESTROY:
PostQuitMessage(0);
break
;
default
:
return
DefWindowProc(hWnd, message, wParam, lParam);
}
return
0;
}
int
WINAPI WinMain(
HINSTANCE
hInstance,
HINSTANCE
hPrevInstance,
LPSTR
lpCmdLine,
int
nCmdShow) {
CreateMainWindow();
MSG msg;
while
(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return
0;
}
DWORD
WINAPI SimulateTextInputThread(
LPVOID
lpParam) {
SimulateTextInput((
WCHAR
*)lpParam);
g_hInputThread = NULL;
return
0;
}