Windows注册鼠标钩子,获取用户选中的文本
注册鼠标钩子
// 注册鼠标钩子
HHOOK hMouseHook;
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), 0);// 取消鼠标钩子
UnhookWindowsHookEx(hMouseHook);
hMouseHook = nullptr;
上述代码中MouseProc方法用于处理系统的鼠标消息
处理鼠标消息
LRESULT MouseHook::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{static QPoint pos;static qint64 lastTriggerTime = 0;if (nCode >= 0) {if (wParam == WM_LBUTTONDOWN) {pos = QCursor::pos(); }else if (wParam == WM_LBUTTONUP) {if (pos != QCursor::pos()) {timer->start(280); //拖拽}qint64 currentTime = QDateTime::currentMSecsSinceEpoch();if (currentTime - lastTriggerTime <= 500) {timer->start(280); //双击}lastTriggerTime = currentTime;}}return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
这段代码中,我们使用一个QTimer来处理双击或拖拽选中文本的操作。
文本选中后的处理方法
void MouseHook::processMouseUp()
{auto textGetter = new TextGetter(this);connect(textGetter, &TextGetter::resultReady, this, &MouseHook::onTextReady, Qt::ConnectionType::QueuedConnection);textGetter->start();
}
TextGetter是一个继承自QThread的类,我们将在一个新线程中去获取用户选中的文本。
获取选中文本的第一种情况
QString TextGetter::getSelectedTextByUIAutomation() {try {auto hr = CoInitialize(NULL);if (FAILED(hr)){CoUninitialize();return "";}CComPtr<IUIAutomation> automation;hr = CoCreateInstance(CLSID_CUIAutomation, nullptr, CLSCTX_INPROC_SERVER, IID_IUIAutomation,(void**)(&automation));if (FAILED(hr)){CoUninitialize();return "";}CComPtr<IUIAutomationElement> focusedElement;hr = automation->GetFocusedElement(&focusedElement);if (FAILED(hr) || !focusedElement){CoUninitialize();return "";}CComPtr<IUIAutomationTextPattern> textPattern;hr = focusedElement->GetCurrentPatternAs(UIA_TextPatternId, IID_PPV_ARGS(&textPattern));if (FAILED(hr) || !textPattern){CoUninitialize();return "";}CComPtr<IUIAutomationTextRangeArray> selection;hr = textPattern->GetSelection(&selection);if (FAILED(hr) || !selection){CoUninitialize();return "";}CComPtr<IUIAutomationTextRange> range;hr = selection->GetElement(0, &range);if (FAILED(hr) || !range){ CoUninitialize();return "";}CComBSTR text;range->GetText(-1, &text);std::wstring ws(text, SysStringLen(text));CoUninitialize();return QString::fromStdWString(ws);}catch (std::exception& e) {return "";}
}
这段代码使用 Microsoft UI Automation (UIA) API 从当前具有焦点的 UI 元素中获取选中文本的方法。但有的时候这种方法获取不到想要的文本(老式窗口中的文本)
获取选中文本的第二种情况
当第一种情况获取到的文本是空时,就要尝试第二种情况
auto hwnd = getCurrentHwnd();
if (!hwnd) {return "";
}
auto cache = cacheClipboard();
sendCtrlC();
str = getClipboardText();
if (str.isEmpty()) {CloseClipboard();return "";
}
restoreClipboard(cache);
CloseClipboard();
这种情况,先获取系统当前聚焦的窗口,然后缓存当前剪切板,然后发送Ctrl+C复制此窗口选中的文本,然后获取剪切板内的文本,然后把之前缓存的内容存入剪切板。
下面我们看看这些实现代码:
获取系统当前聚焦的窗口
HWND TextGetter::getCurrentHwnd()
{HWND hwnd = GetForegroundWindow();DWORD threadId = GetWindowThreadProcessId(hwnd, NULL);AttachThreadInput(GetCurrentThreadId(), threadId, TRUE);hwnd = GetFocus();AttachThreadInput(GetCurrentThreadId(), threadId, FALSE);POINT pt;GetCursorPos(&pt);RECT rect;GetWindowRect(hwnd, &rect);if (pt.x<rect.left || pt.y<rect.top || pt.x>rect.right || pt.y>rect.bottom) {return nullptr;}return hwnd;
}
如果聚焦的窗口与鼠标所在位置的窗口不是一个窗口,那么我们取消任务。
缓存剪切板的内容
ClipboardData TextGetter::cacheClipboard()
{OpenClipboard(nullptr);ClipboardData cache;UINT format = 0;while ((format = EnumClipboardFormats(format)) != 0) {HANDLE hData = GetClipboardData(format);if (hData) {SIZE_T size = GlobalSize(hData);HGLOBAL hCopy = GlobalAlloc(GMEM_MOVEABLE, size);if (hCopy) {void* pDest = GlobalLock(hCopy);void* pSource = GlobalLock(hData);if (pDest && pSource) {memcpy(pDest, pSource, size);}GlobalUnlock(hData);GlobalUnlock(hCopy);cache.push_back({ format, hCopy });}}}EmptyClipboard();CloseClipboard();return cache;
}
发送Ctrl+C按键消息
void TextGetter::sendCtrlC()
{INPUT inputs[4] = { 0 };inputs[0].type = INPUT_KEYBOARD;inputs[0].ki.wVk = VK_CONTROL;inputs[1].type = INPUT_KEYBOARD;inputs[1].ki.wVk = 'C';inputs[2].type = INPUT_KEYBOARD;inputs[2].ki.wVk = 'C';inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;inputs[3].type = INPUT_KEYBOARD;inputs[3].ki.wVk = VK_CONTROL;inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));QThread::msleep(360);
}
按键发送成功后需要等待360毫秒
获取剪切板的内容
QString TextGetter::getClipboardText()
{OpenClipboard(nullptr);if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) {CloseClipboard();return "";}HANDLE hData = GetClipboardData(CF_UNICODETEXT);if (hData == nullptr) {CloseClipboard();return "";}LPCWSTR pText = static_cast<LPCWSTR>(GlobalLock(hData));if (pText == nullptr) {CloseClipboard();return "";}QString result = QString::fromWCharArray(pText);GlobalUnlock(hData);CloseClipboard();return result;
}
不要怀疑发送按键Ctrl+C这个方案是否可行,有道词典就是这么干的。
相关文章:
Windows注册鼠标钩子,获取用户选中的文本
注册鼠标钩子 // 注册鼠标钩子 HHOOK hMouseHook; hMouseHook SetWindowsHookEx(WH_MOUSE_LL, MouseProc, GetModuleHandle(NULL), 0);// 取消鼠标钩子 UnhookWindowsHookEx(hMouseHook); hMouseHook nullptr; 上述代码中MouseProc方法用于处理系统的鼠标消息 处理鼠标消息…...
UE5 蓝图里的反射
蓝图支持使用名字调用函数 使用SetTimerByFunctionName节点即可,该节点是指延后多少时间调用函数,注意时间不能是0也不能是负数,否者不会执行...
私有化视频会议系统,业务沟通协作安全不断线
BeeWorks Meet视频会议平台具备丰富而强大的功能,能够满足企业多样化的业务场景需求。其会议管理功能,让企业能够轻松安排和管理各类会议。 从创建会议、设置会议时间、邀请参会人员到会议提醒,一应俱全,确保会议的顺利进行。多人…...
大数据学习(100)-kafka详解
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一…...
unittest测试模块:Python 标准库中的单元测试利器
在当今的软件开发中,测试的必要性不言而喻。为了确保代码的质量和稳定性,开发者需要一种高效的方式去编写和运行单元测试。Python 提供了一个强大的工具——unittest。这是一个标准库模块,专为编写和运行测试而设计,帮助开发者减少…...
java后端对时间进行格式处理
时间格式处理 通过java后端,使用jackson库的注解JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")进行格式化 package com.weiyu.pojo;import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; import lombok.Data; import …...
Spring的简单介绍
Spring的简单介绍 Spring 是一个开源的 Java 企业级应用开发框架,旨在简化企业应用的开发过程。它通过提供全面的基础设施支持,帮助开发人员构建可靠的、高效的、可扩展的企业级应用程序。Spring 提供了多种功能模块,支持开发不同类型的应用…...
Python基础知识点(函数2)
#需求 打印stu_info def show_info(name,age): print(f"姓名:{name},年龄:{age}") #1.必要参数 在调用函数的时候必须传值 show_info("tom",3) #注意!对于形参,除了个数要匹配,顺序也要匹配 …...
MySQL的左连接、右连接、内连接、外连接
一、前言 MySQL中的左连接、右连接、内连接和全外连接是用于多表关联查询的核心操作。 二、内连接(INNER JOIN) 定义:返回两个表中完全匹配的行,即只保留两个表连接字段值相等的行。示例场景:查询所有有选课记录的学…...
Springboot JPA ShardingSphere 根据年分表
Spring Boot集成JPA与ShardingSphere实现按年分表,需重点关注分片算法选择、时间字段映射及动态表管理。以下是实现方案: 一、依赖配置 1. 核心依赖引入 <!-- ShardingSphere JDBC --> <dependency><groupId>org.apache.shardi…...
巧记英语四级单词 Unit1-3【晓艳老师版】
light 光,轻的、 grant v.准予,承认 gr官人,ant蚂蚁,外面下着大雨,官人让蚂蚁进来了grind v.摩擦,磨碎 官人在里面的 磨刀,准备找法海给白娘子报仇slight v.稍微的,有点的 light 光…...
Flink 任务调度机制
一、Task 任务调度执行流程 一、Graph 的概念 Flink 中的执行图可以分为四层:StreamGraph -> JobGraph -> ExecutionGraph -> 物理执行图。 StreamGraph:执行用户代码中的 env.execute() 方法后,根据用户通过 Stream API 编写的代码生成的最初的图。用来表示程序的…...
设计模式之享元模式
1. 概念 享元模式(Flyweight Pattern), 运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。 在享元模式中可以共享的相同内容称为内部状态(Intrinsic State)&…...
设计模式 - 策略模式Strategy
设计思想: 策略模式的就是定义一系列算法,将他们一个个封装起来,并且使它们可以相互替换,通常我们的代码中出现大量的if...else...或者switch语句时,我们都可以使用策略模式来优化代码 典型场景: 支付系…...
23种设计模式-行为型模式-策略
文章目录 简介场景解决代码关键实现细节 总结 简介 策略是一种行为设计模式,它能让你定义一系列算法,并将每种算法分别放入独立的类中,以使算法对象能够被替换。 场景 你在开发一款导航应用,类似高德。你要实现自动路线规划的功…...
Ubuntu16.04配置远程连接
配置静态IP Ubuntu16.04 修改超管账户默认密码 # 修改root账户默认密码 sudo passwd Ubuntu16.04安装SSH # 安装ssh服务: sudo apt-get install ssh# 启动SSH服务: sudo /etc/init.d/ssh start # 开机自启 sudo systemctl enable ssh# 如无法连接&…...
window部署虚拟机VirtualBox来部署flink
window通过Cygwin部署flink-1.15.0失败 按理来说Cygwin可以在window模拟unix环境来部署运行flink, 但是在flink 不知从哪个版本开始,flink启动时会在window时创建临时文件夹,传递的文件夹名称参数中有冒号,导致文件夹创建失败&a…...
mac 卸载流氓软件安全助手
之前个人电脑在公司使用过一段时间,为了使用网线联网安装了公司指定的 联软上网助手,谁知安装容易卸载难,后来找运维来卸载,输入管理员密码后,也无反应,最后不了了之了,这个毒瘤软件长期在后台驻…...
java基础使用- 泛型
泛型 泛型作用泛型语法(1) 泛型类/接口(2) 泛型方法 类型参数命名习惯类型通配符(Wildcards)(1) 无界通配符 <?>表示“未知类型”(2) 上界通配符 <? extends T>表示“T 或 T 的子类”。(3) 下界通配符 <? super T>表示“T 或 T 的父…...
Appium的学习总结-Inspector参数设置和界面使用(5)
环境搭建好后,怎么使用呢? 环境这里使用的是: Appium的Server端GUI 22版本 Inspector需要单独下载安装,GUI里并没有集成。 (使用Appium v1.22.0,查看元素信息需要另外安装下载Appium Inspector) 操作&…...
多孔介质电化学:原理、应用与展望
引言 多孔介质广泛存在于自然界与人工材料体系中,从土壤、岩石到电池电极、催化剂载体等。多孔介质电化学作为一门交叉学科,融合了电化学与多孔介质理论,聚焦于电流在充满电解液的多孔介质内的传输规律以及电化学反应在复杂多孔结构中的发生…...
使用Prometheus监控systemd服务并可视化
实训背景 你是一家企业的运维工程师,需将服务器的systemd服务监控集成到Prometheus,并通过Grafana展示实时数据。需求如下: 数据采集:监控所有systemd服务的状态(运行/停止)、资源占用(CPU、内…...
网络游戏服务器如何构建全方位防御体系?DDoS与CC攻击实战防护指南
一、DDoS与CC攻击:游戏服务器的两大“隐形杀手” DDoS攻击:通过僵尸网络发起海量流量冲击,常见形式包括SYN Flood(占满连接队列)、UDP Flood(耗尽带宽)、DNS放大攻击(小查询引发大流…...
geoserver搭建Docker一键直接安装并上传tif影像预览
geoserver搭建Docker一键直接安装 文章目录 geoserver搭建Docker一键直接安装前言一、Docker拉取Geoserver二、运行后使用geoserver进行数据管理进入geoserver调整语言登录geoserver上传一个tif影像建立工作空间并上传自己的tif数据建立图层预览 总结 前言 使用docker安装geos…...
ragflow本地部署(WSL下Ubuntu)
本地docker及 docker-compose版本 安装参考: 实践笔记-docker安装及配置镜像源实践笔记-docker-compose安装 1.下载源码 git clone https://github.com/infiniflow/ragflow.git2.运行docker-compose拉取镜像 cd ragflow/docker docker-compose up -d3.启动报错…...
面试题ing
1、js中set和map的作用和区别? 在 JavaScript 中,Set 和 Map 是两种非常重要的集合类型 1、Set 是一种集合数据结构,用于存储唯一值。它类似于数组,但成员的值都是唯一的,没有重复的值。Set 中的值只能是唯一的,任何…...
我的NISP二级之路-02
目录 一.数据库 二.TCP/IP协议 分层结构 三.STRIDE模型 四.检查评估与自评估 检查评估 自评估 五.信息安全应急响应过程 六.系统工程 七.SSE-CMM 八.CC标准 九.九项重点工作 记背: 一.数据库 关于数据库恢复技术,下列说法不正确的是:…...
私有云平台总体建设方案
一、总体规划 二、项目建设...
前端使用正则表达式提取经纬度 度分秒值
经纬度:1240′0.0″,我想提取度分秒 const regex /(\d\.\d)\s*(\d\.\d)′\s*(\d\.\d)″/; const latMatches record.latDegreeMinuteSecond.match(regex); if (latMatches) {record.latDegree latMatches[1]; // 提取度record.latMinute latMatches[…...
如何在 Windows 11 上查找计算机的 IP 地址?
原文:如何在 Windows 11 上查找计算机的 IP 地址? | w3cschool笔记 在开始之前,我们先来了解一下什么是 IP 地址: 假设你住在一栋公寓楼里,快递员需要把包裹送到你家。为了确保快递能准确送到,你需要提供…...
JavaEE vs JavaSE:Java开发的两大世界深度解析
JavaEE vs JavaSE:Java开发的两大世界深度解析 🌐☕ 前言:Java世界的双子星座 作为一名Java开发者,你是否曾经困惑过JavaSE和JavaEE的区别?是否在选择学习路径时感到迷茫?别担心!今天我们将彻…...
[环境配置] 2. 依赖库安装
依赖库安装 本文档详细介绍深度学习项目所需的核心依赖库安装过程,包括 CUDA、PyTorch 等组件的安装和配置。 CUDA和cuDNN安装 CUDA安装 检查显卡是否支持CUDA: 访问NVIDIA官网查看支持列表使用命令 nvidia-smi 查看显卡信息 下载安装CUDA Toolkit&a…...
No module named ‘keras.api._v2‘
No module named keras.api._v2 解解方法,同: No module named ‘keras.engine‘-CSDN博客...
线性方程组的解法
文章目录 线性方程组的解法认识一些基本的矩阵函数MATLAB 实现机电工程学院教学函数构造1.高斯消元法2.列主元消去法3. L U LU LU分解法 线性方程组的解法 看到以下线性方程组的一般形式:设有以下的 n n n阶线性方程组: A x b \mathbf{Ax}\mathbf{b} A…...
OpenHarmony-5.0.0-Risc-V架构搭建DeepSeek-R1
OpenHarmony-5.0.0-Risc-V架构搭建DeepSeek-R1 参考laval社区的文章:OpenHarmony带你玩转DeepSeekR1大模型 文章目录 OpenHarmony-5.0.0-Risc-V架构搭建DeepSeek-R1前言一、前期准备二、获取源码1.错误示范2.下载 三、编译llama.cpp1.生成makefile2.编译 四、模型文…...
Elixir语言的函数定义
Elixir语言的函数定义 Elixir是一种基于Erlang虚拟机(BEAM)的函数式编程语言,因其并发特性及可扩展性而受到广泛欢迎。在Elixir中,函数是程序的基本构建块,了解如何定义和使用函数对于掌握这门语言至关重要。本文将深…...
Spring MVC 数据绑定教程
一、数据绑定概述 将HTTP请求中的表单数据自动映射到Controller方法的参数中,支持多种数据类型绑定。 二、自动绑定数据类型 2.1 基本数据类型绑定 支持类型 基本类型:int, double 等包装类:Integer, Double 等String 类型 实现步骤 创…...
可发1区的超级创新思路(python 实现):基于时空解耦和对比学习的可解释性模型
首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 目录 首先声明,该模型为原创!原创!原创!且该思路还未有成果发表,感兴趣的小伙伴可以借鉴! 一、应用领域 二、模型解析 1.1 创新点深度解读 (1) 双路空间解耦架构(双路编码器…...
一个简单的php加密的理解
前言 原帖子 https://www.52pojie.cn/thread-1991616-1-1.html 一段简单的 php 代码加密,大佬使用了一段 python 代码给解密出来了,但是我没太理解整个逻辑 于是在本地跑了一遍,尝试理解整个解密流程,这里记录下整个学习过程 …...
基于微信小程序的高校寝室快修小程序研究
标题:基于微信小程序的高校寝室快修小程序研究 内容:1.摘要 随着高校规模的不断扩大,学生寝室数量增多,寝室设施维修需求日益增长。传统的维修报修方式效率低下,易出现信息传递不及时等问题。本文旨在研究基于微信小程序的高校寝室快修小程序…...
windows11在连接第二屏幕之后没有声音问题
博主在使用HDMI线连接第二个屏幕之后发现没有声音了。经过翻阅资料总结以下几个步骤。 1、拔开HDMI线,观察是否有声音,如果有声音就是HDMI线插上之后的声音输出设备选择问题。 观察下图: 声音输出设备:1、电脑麦克风࿰…...
手撕Tomcat
后端开发进阶:Web APP -> Web 服务器 Jerrymouse Server设计目标如下: 1、支持Servlet 6的大部分功能: 支持Servlet组件; 支持Filter组件; 支持Listener组件; 支持Sesssion(仅限Cookie模式&a…...
oracle 快速创建表结构
在 Oracle 中快速创建表结构(仅复制表结构,不复制数据)可以通过以下方法实现,适用于需要快速复制表定义或生成空表的场景 1. 使用 CREATE TABLE AS SELECT (CTAS) 方法 -- 复制源表的全部列和数据类型,但不复制数据 C…...
InnoDB存储引擎的三大特性
InnoDB存储引擎的三大特性 Buffer Pool 原理:Buffer Poo 是InnoDB存储引擎用于缓存数据页和索引页的内存区域。他提高了数据库的读写性能,因为数据也和索引页在内存中读写比磁盘上快得多。需要访问数据时,InnoDB会在Buffer Pool 中查找&…...
算法初识-时间复杂度空间复杂度
注:观看Adbul Bari算法视频 算法概念 算法:先验分析,不依托于硬件,无语言限制,逻辑。 程序:后验测试,依托硬件,语言限制,实现。 特点: 输入-0或多个输出-至…...
MySQL8.0.40编译安装(Mysql8.0.40 Compilation and Installation)
MySQL8.0.40编译安装 近期MySQL发布了8.0.40版本,与之前的版本相比,部分依赖包发生了变化,因此重新编译一版,也便于大家参考。 1. 下载源码 选择对应的版本、选择源码、操作系统 如果没有登录或者没有MySQL官网账号࿰…...
一个简单的跨平台Python GUI自动化 AutoPy
象一下,你坐在电脑前,手指轻轻一点,鼠标自己动了起来,键盘仿佛被无形的手操控,屏幕上的任务自动完成——这一切不需要你费力,只靠几行代码就能实现。这就是AutoPy的魅力,一个简单却强大的跨平台…...
C++中常见函数
目录 stringstream ss(line); 为什么使用 stringstream while(ss>>num){} arr.push_back(num); numeric_limits ::min() pair result throw invalid_argument(""); vector arr;和int arr[];有什么区别? 数据结构的本质 内存管理 功能与易用…...
C++: 类型转换
C: 类型转换 (一)C语言中的类型转换volatile关键字 修饰const变量 (二)C四种强制类型转换1. static_cast2. reinterpret_cast3. const_cast4. dynamic_cast总结 (三)RTTI (一)C语言中的类型转换 在C语言中…...
Linux驱动开发进阶(五)- 系统调用
文章目录 1、前言2、阻塞与非阻塞IO2.1、阻塞方式2.2、非阻塞方式2.3、小结 3、异步IO3.1、poll3.2、select3.3、epoll3.4、poll和epoll示例比较3.5、异步通知 4、unlocked_ioctl5、sysfs_notify 1、前言 学习参考书籍以及本文涉及的示例程序:李山文的《Linux驱动开…...