04-08更新2.0 剪贴板文本输入器,可以输入不能粘贴的输入框

使用就是打开就行,设好参数点击开始,其中设置CTRL+V会导致原本粘贴无效
04-08更新,可以记录剪贴板历史记录了,选中那一下就可以输入哪一项了

04-08更新2.0   剪贴板文本输入器,可以输入不能粘贴的输入框

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <tchar.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 IDC_LISTBOX_CLIPBOARD_RECORDS 105
#define IDC_BUTTON_DELETE 107
#define IDC_BUTTON_CLEAR 109 // 新增清空按钮ID
#define IDC_CHECKBOX_TOPMOST 108 // 复选框ID

// 定义定时器ID
#define TIMER_ID_RESET_INTERVAL 1

// 在头文件部分添加以下定义
#ifndef LB_END
#define LB_END (-1)
#endif

// 全局变量
WCHAR** g_ClipboardRecords = NULL;
int g_ClipboardRecordCount = 0;
HWND g_hListBox = NULL;

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; // 0: Ctrl+E, 1: Ctrl+Q, 2: Ctrl+V, 3: Alt+V, 4: 无快捷键
HANDLE g_hInputThread = NULL; // 输入线程句柄
WCHAR* g_pszClipboardText = NULL; // 剪贴板文本
BOOL g_bTopMost = FALSE; // 窗口是否置于顶层

// 函数声明
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);

// DLL 入口点
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: // Ctrl+E
                    if (pkbllhs->vkCode == VK_E && bCtrlPressed && !bAltPressed) {
                        bBlock = TRUE;
                    }
                    break;
                case 1: // Ctrl+Q
                    if (pkbllhs->vkCode == VK_Q && bCtrlPressed && !bAltPressed) {
                        bBlock = TRUE;
                    }
                    break;
                case 2: // Ctrl+V
                    if (pkbllhs->vkCode == VK_V && bCtrlPressed && !bAltPressed) {
                        bBlock = TRUE;
                    }
                    break;
                case 3: // Alt+V
                    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'' && !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",
            "剪贴板文本输入器2.0",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT, 400, 500,
            NULL,
            NULL,
            g_hInst,
            NULL
        );

        if (g_hMainWnd) {
            ShowWindow(g_hMainWnd, SW_SHOW);
            UpdateUIState();

            // 注册剪贴板更新消息
            AddClipboardFormatListener(g_hMainWnd);
        }
    }
}

// 更新UI状态
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 HBRUSH hBrush; // 背景色
    static HBRUSH hButtonBrush; // 按钮颜色
    static HBRUSH hButtonHoverBrush; // 按钮悬停颜色
    static HBRUSH hButtonPressedBrush; // 按钮按下颜色
    static HFONT hFont; // 字体
    static HWND hEditInterval = NULL;
    static HWND hComboHotkey = NULL;
    static HWND hCheckboxTopMost = NULL;
    static HWND hStartButton = NULL;
    static HWND hStopButton = NULL;
    static HWND hDeleteButton = NULL;
    static HWND hClearButton = NULL;

    switch (message) {
        case WM_CREATE:
        {
            // 创建资源
            hBrush = CreateSolidBrush(RGB(240, 240, 240));
            hButtonBrush = CreateSolidBrush(RGB(64, 128, 255));
            hButtonHoverBrush = CreateSolidBrush(RGB(50, 100, 200));
            hButtonPressedBrush = CreateSolidBrush(RGB(40, 80, 160));
            hFont = CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Segoe UI");

            // 设置窗口背景颜色
            SetClassLong(hWnd, GCL_HBRBACKGROUND, (LONG)hBrush);

            // 创建控件
            hStartButton = CreateWindow("BUTTON", "开启", 
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_FLAT,
                20, 30, 80, 30, hWnd, (HMENU)IDC_BUTTON_START, g_hInst, NULL);

            hStopButton = CreateWindow("BUTTON", "关闭", 
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_FLAT,
                120, 30, 80, 30, hWnd, (HMENU)IDC_BUTTON_STOP, g_hInst, NULL);

            // 创建“窗口置顶”按钮
            hCheckboxTopMost = CreateWindow("BUTTON", "窗口置顶",
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
                220, 30, 100, 30, hWnd, (HMENU)IDC_CHECKBOX_TOPMOST, g_hInst, NULL);

            hEditInterval = CreateWindow("EDIT", "50",
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | ES_NUMBER | WS_EX_CLIENTEDGE,
                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 = CreateWindow("COMBOBOX", NULL,
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST | WS_VSCROLL | WS_EX_CLIENTEDGE,
                160, 120, 165, 100, hWnd, (HMENU)IDC_COMBO_HOTKEY, g_hInst, NULL);

            // 添加组合框项
            SendMessage(hComboHotkey, CB_ADDSTRING, 0, (LPARAM)"Ctrl+E");
            SendMessage(hComboHotkey, CB_ADDSTRING, 0, (LPARAM)"Ctrl+Q");
            SendMessage(hComboHotkey, CB_ADDSTRING, 0, (LPARAM)"Ctrl+V");
            SendMessage(hComboHotkey, CB_ADDSTRING, 0, (LPARAM)"Alt+V");
            SendMessage(hComboHotkey, CB_ADDSTRING, 0, (LPARAM)"无快捷键");
            SendMessage(hComboHotkey, CB_SETCURSEL, 0, 0); // 默认选择第一个

            // 设置定时器,在10毫秒后触发
            SetTimer(hWnd, TIMER_ID_RESET_INTERVAL, 10, NULL);

            // 创建列表框
            g_hListBox = CreateWindow("LISTBOX", NULL,
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | LBS_STANDARD,
                20, 160, 360, 280, hWnd, (HMENU)IDC_LISTBOX_CLIPBOARD_RECORDS, g_hInst, NULL);

            // 创建删除按钮
            hDeleteButton = CreateWindow("BUTTON", "删除",
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_FLAT,
                120, 430, 80, 30, hWnd, (HMENU)IDC_BUTTON_DELETE, g_hInst, NULL);

            // 创建清空按钮
            hClearButton = CreateWindow("BUTTON", "清空",
                WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON | BS_FLAT,
                220, 430, 80, 30, hWnd, (HMENU)IDC_BUTTON_CLEAR, g_hInst, NULL);

            // 设置字体
            // 创建放大一倍的字体
            HFONT hBigFont = CreateFont(28, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Segoe UI");

            SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
            SendMessage(hStartButton, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
            SendMessage(hStopButton, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
            SendMessage(hEditInterval, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
            SendMessage(hComboHotkey, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
            SendMessage(g_hListBox, WM_SETFONT, (WPARAM)hBigFont, MAKELPARAM(TRUE, 0));
            SendMessage(hDeleteButton, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
            SendMessage(hClearButton, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
            SendMessage(hCheckboxTopMost, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));

            UpdateUIState();
            break;
        }
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

            // 绘制按钮背景
            RECT rect;
            GetClientRect(hWnd, &rect);

            // 绘制窗口背景
            FillRect(hdc, &rect, hBrush);

            // 绘制按钮
            GetClientRect(hStartButton, &rect);
            OffsetRect(&rect, 20, 30);
            FillRect(hdc, &rect, hButtonBrush);

            GetClientRect(hStopButton, &rect);
            OffsetRect(&rect, 120, 30);
            FillRect(hdc, &rect, hButtonBrush);

            GetClientRect(hDeleteButton, &rect);
            OffsetRect(&rect, 120, 320);
            FillRect(hdc, &rect, hButtonBrush);

            GetClientRect(hClearButton, &rect);
            OffsetRect(&rect, 220, 320);
            FillRect(hdc, &rect, hButtonBrush);

            // 绘制复选框背景
            GetClientRect(hCheckboxTopMost, &rect);
            OffsetRect(&rect, 220, 30);
            FillRect(hdc, &rect, hBrush);

            EndPaint(hWnd, &ps);
            break;
        }
        case WM_CLIPBOARDUPDATE:
        {
            if (OpenClipboard(NULL)) {
                HANDLE hData = GetClipboardData(CF_UNICODETEXT);
                if (hData != NULL) {
                    WCHAR* text = (WCHAR*)GlobalLock(hData);
                    if (text != NULL) {
                        // 检查内容是否已在列表中
                        BOOL found = FALSE;
                        int index = -1;
                        for (int i = 0; i < g_ClipboardRecordCount; i++) {
                            if (wcscmp(g_ClipboardRecords[i], text) == 0) {
                                found = TRUE;
                                index = i;
                                break;
                            }
                        }

                        if (found) {
                            // 将该项移到最前面
                            WCHAR* temp = g_ClipboardRecords[index];
                            for (int i = index; i > 0; i--) {
                                g_ClipboardRecords[i] = g_ClipboardRecords[i - 1];
                            }
                            g_ClipboardRecords[0] = temp;

                            // 更新列表框
                            SendMessageW(g_hListBox, LB_DELETESTRING, index, 0);
                            SendMessageW(g_hListBox, LB_INSERTSTRING, (WPARAM)0, (LPARAM)temp);
                            SendMessageW(g_hListBox, LB_SETCURSEL, 0, 0);
                        } else {
                            // 添加新项到末尾
                            WCHAR* newText = _wcsdup(text);
                            if (newText != NULL) {
                                // 动态调整记录数组的大小
                                g_ClipboardRecords = (WCHAR**)realloc(g_ClipboardRecords, (g_ClipboardRecordCount + 1) * sizeof(WCHAR*));
                                if (g_ClipboardRecords != NULL) {
                                    g_ClipboardRecords[g_ClipboardRecordCount] = newText;
                                    g_ClipboardRecordCount++;

                                    // 将新项移到最前面
                                    for (int i = g_ClipboardRecordCount - 1; i > 0; i--) {
                                        g_ClipboardRecords[i] = g_ClipboardRecords[i - 1];
                                    }
                                    g_ClipboardRecords[0] = newText;

                                    // 更新列表框
                                    SendMessageW(g_hListBox, LB_INSERTSTRING, (WPARAM)0, (LPARAM)newText);
                                    SendMessageW(g_hListBox, LB_SETCURSEL, 0, 0);
                                }
                            }
                        }

                        GlobalUnlock(hData);
                    }
                }
                CloseClipboard();
            }
            break;
        }
        case WM_CTLCOLORSTATIC:
        {
            HDC hdc = (HDC)wParam;
            HWND hwndStatic = (HWND)lParam;

            // 设置背景颜色为浅灰色
            SetBkColor(hdc, RGB(240, 240, 240));
            SetTextColor(hdc, RGB(0, 0, 0)); // 设置文本颜色为黑色
            return (LRESULT)GetStockObject(NULL_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) {
                    char buffer[32];
                    GetWindowTextA(hEditInterval, buffer, 32);
                    g_nInputInterval = atoi(buffer);
                }
            } else if (wmId == IDC_COMBO_HOTKEY) {
                if (HIWORD(wParam) == CBN_SELCHANGE) {
                    int index = SendMessageW(hComboHotkey, CB_GETCURSEL, 0, 0);
                    g_nSelectedHotkey = index;
                }
            } else if (wmId == IDC_BUTTON_DELETE) {
                int index = SendMessageW(g_hListBox, LB_GETCURSEL, 0, 0);
                if (index != LB_ERR) {
                    free(g_ClipboardRecords[index]);
                    for (int i = index; i < g_ClipboardRecordCount - 1; i++) {
                        g_ClipboardRecords[i] = g_ClipboardRecords[i + 1];
                    }
                    g_ClipboardRecordCount--;
                    SendMessageW(g_hListBox, LB_DELETESTRING, index, 0);

                    // 删除后,重新设置选中项
                    if (g_ClipboardRecordCount > 0) {
                        int newIndex = min(index, g_ClipboardRecordCount - 1);
                        SendMessageW(g_hListBox, LB_SETCURSEL, newIndex, 0);
                    }
                }
            } else if (wmId == IDC_BUTTON_CLEAR) {
                // 清空列表
                for (int i = 0; i < g_ClipboardRecordCount; i++) {
                    free(g_ClipboardRecords[i]);
                }
                free(g_ClipboardRecords);
                g_ClipboardRecords = NULL;
                g_ClipboardRecordCount = 0;
                SendMessageW(g_hListBox, LB_RESETCONTENT, 0, 0);
            } else if (wmId == IDC_LISTBOX_CLIPBOARD_RECORDS) {
                if (HIWORD(wParam) == LBN_SELCHANGE) {
                    int index = SendMessageW(g_hListBox, LB_GETCURSEL, 0, 0);
                    if (index != LB_ERR && g_ClipboardRecords[index] != NULL) {
                        // 将选中项写入剪贴板
                        if (OpenClipboard(NULL)) {
                            EmptyClipboard();
                            HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, (wcslen(g_ClipboardRecords[index]) + 1) * sizeof(WCHAR));
                            if (hMem) {
                                WCHAR* pText = (WCHAR*)GlobalLock(hMem);
                                wcscpy(pText, g_ClipboardRecords[index]);
                                GlobalUnlock(hMem);
                                SetClipboardData(CF_UNICODETEXT, hMem);
                            }
                            CloseClipboard();
                        }
                    }
                }
            } else if (wmId == IDC_CHECKBOX_TOPMOST) {
                if (HIWORD(wParam) == BN_CLICKED) {
                    g_bTopMost = IsDlgButtonChecked(hWnd, IDC_CHECKBOX_TOPMOST);
                    SetWindowPos(hWnd, g_bTopMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
                }
            }
            break;
        }
        case WM_TIMER:
        {
            if (wParam == TIMER_ID_RESET_INTERVAL) {
                // 停止定时器
                KillTimer(hWnd, TIMER_ID_RESET_INTERVAL);

                // 将输入间隔改回10
                g_nInputInterval = 10;

                // 更新编辑框的显示
                char buffer[32];
                sprintf(buffer, "%d", g_nInputInterval);
                SetWindowText(hEditInterval, buffer);
            }
            break;
        }
        case WM_CLOSE:
            RemoveClipboardHook();
            DestroyWindow(hWnd);
            break;
        case WM_DESTROY:
        {
            // 释放资源
            DeleteObject(hBrush);
            DeleteObject(hButtonBrush);
            DeleteObject(hButtonHoverBrush);
            DeleteObject(hButtonPressedBrush);
            DeleteObject(hFont);

            for (int i = 0; i < g_ClipboardRecordCount; i++) {
                free(g_ClipboardRecords[i]);
            }
            free(g_ClipboardRecords);
            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;
}

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 共50条

请登录后发表评论