一个c++实现的剪贴板数据粘贴程序

#include <windows.h>
#include <commctrl.h>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include "mybox.h"

LRESULT CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);

bool isMinimized = true;     // 窗口最小化状态
int ctrlPressCount = 0;      // 记录 Ctrl 按下次数
DWORD lastCtrlPressTime = 0; // 上一次按下 Ctrl 的时间
int RePointIndex = 0;        // 几乎覆盖的文本的索引
int blockHight = 30;         // 块的高度
int maxRow = 15;             // 最大行数
bool clipboard = true;       // 剪贴板监控开关

// 系统托盘图标的通知结构
NOTIFYICONDATA nid = {0};
#define HOTKEY_ID 1          // 自定义热键 ID
#define IDC_TEXTCONTROL 2001 // 自定义文本控件 ID

HWND hDialog = NULL; // 全局变量,用于存储对话框句柄

struct ClipboardBlock
{
    std::string text;
    RECT rect; // 用于存储块的绘制区域
    int id;    // 块的唯一标识,
};
std::vector<ClipboardBlock> blocks; // 存储剪贴板块
int blockId = 1;                    // 初始块编号

// 创建自定义字体
HFONT hFont = CreateFont(
    16,                       // 字体高度
    0,                        // 字体宽度
    0,                        // 字符旋转角度
    0,                        // 基线旋转角度
    FW_NORMAL,                // 字体粗细
    FALSE,                    // 斜体
    FALSE,                    // 下划线
    FALSE,                    // 删除线
    ANSI_CHARSET,             // 字符集
    OUT_TT_PRECIS,            // 输出精度
    CLIP_DEFAULT_PRECIS,      // 剪辑精度
    DEFAULT_QUALITY,          // 字体质量
    FF_SWISS | DEFAULT_PITCH, // 字体族和间距
    L"Arial"                  // 字体名称
);

// 自定义对话框创建
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);

    switch (message)
    {
    case WM_INITDIALOG:
    {
        // 获取传递的文本
        std::wstring text = reinterpret_cast<std::wstring *>(lParam)[0];
        SetDlgItemTextW(hDlg, IDC_TEXTCONTROL, text.c_str());
        return (INT_PTR)TRUE;
    }
    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    case WM_ACTIVATE:
    {
        // 当对话框失去焦点时关闭
        if (LOWORD(wParam) == WA_INACTIVE)
        {
            EndDialog(hDlg, IDCANCEL);
            return (INT_PTR)TRUE;
        }
        break;
    }
    }
    return (INT_PTR)FALSE;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static HWND hEdit;

    switch (uMsg)
    {
    case WM_CREATE:
    {
        // 调用剪贴板监听
        AddClipboardFormatListener(hwnd);
        break;
    }
    case WM_HOTKEY:
    {
        if (wParam == HOTKEY_ID)
        {
            DWORD currentTime = GetTickCount();
            if (currentTime - lastCtrlPressTime <= 500)
            { // 500ms 内按下两次 Ctrl
                ctrlPressCount++;
            }
            else
            {
                ctrlPressCount = 1; // 重置计数
            }
            lastCtrlPressTime = currentTime;

            if (ctrlPressCount == 2)
            {
                if (isMinimized)
                {
                    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW); // 显示任务栏图标
                    ShowWindow(hwnd, SW_RESTORE);                                                           // 还原窗口
                }
                else
                {
                    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW); // 隐藏任务栏图标
                    ShowWindow(hwnd, SW_MINIMIZE);                                                         // 最小化窗口
                }
                isMinimized = !isMinimized; // 切换可见状态
                ctrlPressCount = 0;         // 重置计数
            }
        }
        break;
    }
    case WM_CLIPBOARDUPDATE: // 监听剪贴板变化
    {
        if (!clipboard) // 如果监控开关为false,则不处理剪贴板变化
        {
            clipboard = true;
            break; // 窗口不是最小化时,不处理剪贴板变化
        }

        if (OpenClipboard(hwnd))
        {
            HANDLE hData = GetClipboardData(CF_TEXT);
            if (hData)
            {
                char *pData = static_cast<char *>(GlobalLock(hData));
                if (pData)
                {
                    // 将新的剪贴板块添加到列表
                    ClipboardBlock block;
                    block.text = pData; // 保存剪贴板内容
                    GlobalUnlock(hData);
                    // 设置块的绘制区域

                    if (blocks.size() < maxRow) // 如果达到了最大值
                    {
                        if (blocks.empty())
                        {
                            block.rect.top = 5; // 设置第一个块的顶部
                        }
                        else
                        {
                            block.rect.top = blocks.back().rect.bottom + 5; // 与上一个块的底部间隔
                        }

                        block.id = blockId++;
                        block.rect.bottom = block.rect.top + blockHight; // 每个块的高度
                        block.rect.left = 10;
                        block.rect.right = 400;  // 固定宽度
                        blocks.push_back(block); // 添加到块列表
                    }
                    else // 如果没有达到最大值
                    {
                        blocks[RePointIndex].text = block.text; // 覆盖第n块的内容
                        blocks[RePointIndex].id = blockId++;
                        if (RePointIndex >= maxRow - 1)
                        {
                            RePointIndex = 0;
                        }
                        else
                        {
                            RePointIndex++;
                        }
                    }

                    // }
                    InvalidateRect(hwnd, NULL, TRUE); // 重新绘制窗口
                }
            }
            CloseClipboard();
        }
        break;
    }
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        HFONT oldFont = (HFONT)SelectObject(hdc, hFont);
        // 绘制每个块
        for (const auto &block : blocks)
        {
            // std::cout << block.text << std::endl;
            FillRect(hdc, &block.rect, (HBRUSH)(COLOR_WINDOW + 1));
            RECT rect = block.rect; // 填充块背景

            // 拼接字符串
            std::stringstream ss;
            ss << block.id << ": " << block.text;
            std::string combinedText = ss.str();

            DrawTextA(hdc, combinedText.c_str(), -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER); // 绘制文本
            // 绘制分割线
            MoveToEx(hdc, block.rect.left, block.rect.bottom, NULL);
            LineTo(hdc, block.rect.right, block.rect.bottom);
        }

        EndPaint(hwnd, &ps);
        break;
    }
    case WM_LBUTTONDOWN: // 监听点击事件
    {

        POINT pt = {LOWORD(lParam), HIWORD(lParam)};
        for (size_t i = 0; i < blocks.size(); ++i)
        {
            if (PtInRect(&blocks[i].rect, pt))
            {
                size_t len = strlen(blocks[i].text.c_str()) + 1;
                HGLOBAL hClipboardData = GlobalAlloc(GMEM_DDESHARE, len);
                if (hClipboardData)
                {
                    char *pClipboardData = (char *)GlobalLock(hClipboardData);
                    if (pClipboardData)
                    {
                        memcpy(pClipboardData, blocks[i].text.c_str(), len);
                        GlobalUnlock(hClipboardData);

                        if (OpenClipboard(hwnd))
                        {
                            EmptyClipboard();
                            if (SetClipboardData(CF_TEXT, hClipboardData) == NULL)
                            {
                                // 错误处理: SetClipboardData 失败
                                GlobalFree(hClipboardData);
                            }
                            CloseClipboard();
                        }
                        else
                        {
                            // 错误处理: OpenClipboard 失败
                            GlobalFree(hClipboardData);
                        }
                    }
                    else
                    {
                        // 错误处理: GlobalLock 失败
                        GlobalFree(hClipboardData);
                    }
                }
            }
        }
        // 将窗口最小化,只在所有块处理完后进行
        ShowWindow(hwnd, SW_MINIMIZE);
        isMinimized = !isMinimized;
        clipboard = false;
        break;
    }
    case WM_RBUTTONDOWN: // 右键点击事件
    {
        POINT pt = {LOWORD(lParam), HIWORD(lParam)};
        bool found = false;

        for (size_t i = 0; i < blocks.size(); ++i)
        {
            if (PtInRect(&blocks[i].rect, pt))
            {
                //std::wstring wtext(blocks[i].text.begin(), blocks[i].text.end());
                std::string message = "Clicked on block: " + blocks[i].text;
                MessageBoxA(hwnd, message.c_str(), "Info", MB_OK);
                break;
            }
        }
    }
    case WM_USER + 1: // 托盘图标的消息处理
        switch (lParam)
        {
        case WM_LBUTTONDOWN:
            if (isMinimized)
            {
                ShowWindow(hwnd, SW_RESTORE);                                                           // 单击托盘图标恢复窗口
                SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW); // 恢复任务栏图标
                isMinimized = false;
            }
            else
            {
                ShowWindow(hwnd, SW_HIDE);                                                             // 隐藏窗口
                SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW); // 隐藏任务栏图标
                isMinimized = true;
            }
            break;
        }
        break;
    case WM_CLOSE:
        DestroyWindow(hwnd); // 销毁窗口并发送 WM_DESTROY 消息
        break;
    case WM_DESTROY:
    {
        RemoveClipboardFormatListener(hwnd); // 移除剪贴板格式监听
        PostQuitMessage(0);                  // 发出 WM_QUIT 消息,结束消息循环
        break;
    }
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam); // 对不感兴趣的消息进行缺省处理
    }
    return 0;
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
{
    HWND blackHwnd;
    blackHwnd = FindWindow(L"ConsoleWindowClass", NULL); // 处理顶级窗口的类名和窗口名称匹配指定的字符串,不搜索子窗口,将显示的黑框进行隐藏。
    if (blackHwnd)
    {
        ShowWindow(blackHwnd, SW_HIDE); // 设置指定窗口的显示状态
    }

    WNDCLASS wndcls = {0};                                      // 创建一个窗体类
    wndcls.cbClsExtra = 0;                                      // 类的额外内存,默认为 0 即可
    wndcls.cbWndExtra = 0;                                      // 窗口的额外内存,默认为 0 即可
    wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // 获取画刷句柄
    wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);               // 设置光标
    wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);             // 设置窗体左上角的图标
    wndcls.hInstance = hInstance;                               // 设置窗体所属的应用程序实例
    wndcls.lpfnWndProc = WindowProc;                            // 设置窗体的回调函数
    wndcls.lpszClassName = L"test";                             // 设置窗体的类名
    wndcls.lpszMenuName = NULL;                                 // 设置窗体的菜单,没有,填 NULL
    wndcls.style = CS_HREDRAW | CS_VREDRAW;                     // 设置窗体风格为水平重画和垂直重画

    if (!RegisterClass(&wndcls))
    { // 向操作系统注册窗体
        MessageBox(NULL, L"窗口类注册失败!", L"错误", MB_ICONERROR);
        return 1;
    }

    // 设置窗口的宽度和高度
    int windowWidth = 400;
    int windowHeight = 600;
    // 获取屏幕的宽度和高度
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);

    // 计算窗口的左上角坐标,使其位于屏幕的中心
    int posX = (screenWidth - windowWidth) / 2;
    int posY = (screenHeight - windowHeight) / 2;

    HWND hwnd = CreateWindow(L"test", L"我的编辑框",
                             WS_OVERLAPPEDWINDOW, posX, posY, windowWidth, windowHeight, // 宽度 高度
                             NULL, NULL, hInstance, NULL);

    if (!RegisterHotKey(hwnd, HOTKEY_ID, MOD_CONTROL | MOD_NOREPEAT, 0))
    {
        MessageBox(hwnd, L"Failed to register hotkey", L"Error", MB_OK);
        return 1;
    }

    if (!hwnd)
    { // 检查窗口创建是否成功
        MessageBox(NULL, L"窗口创建失败!", L"错误", MB_ICONERROR);
        return 1;
    }

    UpdateWindow(hwnd); // 更新窗体
    isMinimized = true; // 窗口最小化状态
    // SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW); // 隐藏任务栏图标
    // ShowWindow(hwnd, SW_MINIMIZE); // 最小化窗口

    nid.cbSize = sizeof(NOTIFYICONDATA);
    nid.hWnd = hwnd;
    nid.uID = 1;
    nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    nid.uCallbackMessage = WM_USER + 1; // 自定义托盘消息
    nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wcscpy_s(nid.szTip, L"我的应用程序");
    Shell_NotifyIcon(NIM_ADD, &nid);

    MSG msg;
    // 消息循环
    while (GetMessage(&msg, NULL, 0, 0))
    {                           // 如果消息不是 WM_QUIT, 返回非零值;如果消息是 WM_QUIT,返回零
        TranslateMessage(&msg); // 翻译消息
        DispatchMessage(&msg);  // 派发消息
    }
    Shell_NotifyIcon(NIM_DELETE, &nid); // 删除托盘图标
    UnregisterHotKey(hwnd, HOTKEY_ID);
    return (int)msg.wParam;
}

更新:

        1.为每一行数据添加了序号

        2.右键点击弹出消息框显示粘贴的内容详情

task

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe build active file",
            "command": "D:\\tools\\mingw64\\bin\\g++.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe",
                "-lgdi32",
                "-luser32",
                "-municode",
                "-DUNICODE",
                "-D_UNICODE"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "Task generated by Debugger.",
            "presentation": { 
                "panel": "new" // 默认为“shared”表示共享,改成new之后每个进程创建新的端口
            }
        }
    ],
    "version": "2.0.0"
}

launch

{
    "configurations": [
        {
            "name": "C/C++: g++.exe build and debug active file",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "D:\\tools\\mingw64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "Set Disassembly Flavor to Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: g++.exe build active file"
        }
    ],
    "version": "2.0.0"
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值