项目介绍
全局划词搜索,可实现PC端在任意界面(almost)选中文字后,使用快捷键快速搜索该文字,需配合Windows批处理文件使用。
软件架构
Spring Boot
软件思路
首先明确一下我的需求,当我在任意界面浏览的时候,选中一些文字,此时使用快捷键(假设这个快捷键是Ctrl+Shift+Q
)便可立即百度搜索这些字。
首先介绍Java端,Java程序中只有一个Controller,用于接收请求,收到请求后它会从系统剪切板中取出内容,并拼接成一条cmd命令,该命令大致意思时启动浏览器去访问拼接好的搜索链接(暂时只支持百度,有空了再添几种),这样就实现了查询的功能。
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
//从系统剪切板中获取数据
Transferable content = clipboard.getContents(null);
//判断是否为文本类型
if (content.isDataFlavorSupported(DataFlavor.stringFlavor)) {
//从数据中获取文本值
String text = (String) content.getTransferData(DataFlavor.stringFlavor);
if (text == null) {
return;
}
//拼接一条cmd命令
String url = "rundll32 url.dll,FileProtocolHandler https://www.baidu.com/s?wd=";
//执行cmd命令
Runtime.getRuntime().exec(url+text);
}
那么如何保证剪切板中取出的内容就是你浏览时选中的文字呢?并且要怎么出发这个请求?我用的是批处理文件(search.bat
),该文件中的命令就是发送一个请求(curl localhost:18088
),然后,给这个批处理文件新建一个快捷方式放在桌面,鼠标右键>属性,给它设置一个快捷键,就是刚才的Ctrl+Shift+Q
,并将运行方式修改为最小化(这样在运行的时候不会弹出窗口,交互更友好),应用。
此时,当选中文字并按下该快捷键的时候,系统就会通过cmd命令发送请求到我们的Controller,然而,我们选中的文字还是没有复制啊!!!如果你不怕麻烦,可以先Ctrl+C
复制了选中的文字后再Ctrl+Shift+Q
,但是这样显然不够优雅。
因此我又想到了一个办法,让Java程序模拟Ctrl+C
的操作,即请求到达Controller后,Java程序先模拟Ctrl+C
,这样你选中的文字就会被复制,之后走“取”、“查”的操作,嗯,看似很美好,美滋滋。
Robot robot = new Robot();
//模拟Ctrl+C,复制文字
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.delay(100);//必不可少
然而实地应用之后发现有问题。当你选中文字并按下快捷键后,系统启动了一个cmd窗口,虽然他是最小化运行的,小到你甚至不会发现有这么一个窗口,但是你选中文字的窗口还是被挤到了后台,此时就算Ctrl+C
了,也复制不到这些文字,冥思苦想,又想出一个骚操作,我们在Ctrl+C之前先执行Alt+Tab
(切换到上个窗口),这样不就行了!果然,复制到了选中的文字,美滋滋。
Robot robot = new Robot();
//模拟Alt+Tab,切换回上一个的窗口,也就是有选中文字的窗口
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_ALT);
robot.delay(100);//必不可少
//模拟Ctrl+C,复制文字
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.delay(100);//必不可少
本以为大功告成,结果使用了不到两分钟,又出现了致命的BUG。就是当你选中文字并按下快捷键后,如果抬手比较慢或是根本没抬手,这是请求到达Controller,立即就执行Alt+Tab
,此时加上按下去的按键,直接导致按键冲突了,所以接下去的Ctrl+C
就又复制不到你想要的东西了。这个BUG让我困惑了好久,直到下班也没解决。我想的就是在代码里加个“while
”循环,判断用户是否按下了按键,直到监听不到有按键被按下,才执行后续操作,理想很丰满,然而实施起来并不简单,因为我对Java C/S架构知之甚少,键盘监听事件也不会用,而且好像这个事件还必须绑定到一个JFrame
上(如果这里说错了,请大神指出,蟹蟹),我不可能为了实现我这简单的功能,再建一个JFrame
,然后再。。。。不不不,这TM扯到哪儿去了。这条路行不通。
当然,还有一个简单但是却不完美的解决方案,就是在进入Controller后先Thread.sleep(1000)
,让程序先等一会儿,给用户一个抬手的机会,但是用户:我TM就是不抬手了你能咋地?
,那就GG了,而且等待的操作也会导致用户体验下降,造成反应迟钝的感觉,不行不行,这完全不符合我追求完美的精神,太不优雅了。
然而,最终还是被我想到了解决办法。我们在Alt+Tab
之前,再模拟一个事件,就是Ctrl
、Shift
、Alt
的抬起事件(因为一般的快捷键都是包含这三个的),这样就算用户手指还按在键盘上,但是实际这几个键已经不起作用了,之后就该干啥干啥,美滋滋。
Robot robot = new Robot();
//模拟三大快捷键的抬起事件,以防止按键冲突
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_SHIFT);
robot.keyRelease(KeyEvent.VK_ALT);
robot.delay(100);//必不可少
//模拟Alt+Tab,切换回上一个的窗口,也就是有选中文字的窗口
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_ALT);
robot.delay(100);//必不可少
//模拟Ctrl+C,复制文字
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_C);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.delay(100);//必不可少
至此算是基本实现了我的需求,也许有更简单的办法可以实现这个看似非常简单的功能,但我作为一个菜鸟java程序员,暂时只能曲线救国的来实现该需求了。
使用说明
- 建议打jar包,并将jar包和“file”文件夹中的两个批处理文件一起复制到本地
- 给
search.bat
创建一个快捷方式并按照上面的描述进行修改。 switch.bat
是负责开启和关闭程序的脚本,如果jar包没运行,双击后会在后台启动jar包,如果已经运行了,可根据提示输入相关字符将其关闭。
search.bat
的快捷方式只能放在桌面,否则设置了快捷键后是不会生效的,这个是什么原因要@微软了。如果你有强迫症,也可以把它放到开始菜单里,具体操作如下:打开开始菜单,随便找个程序,右键>更多>打开文件位置,此时会打开一个文件夹(不是每个软件都有“打开文件位置”的选项,可以多试几个),之后将刚才的快捷方式放到这里并设置好快捷键,理论上放在这里快捷键也是可以生效的,如果有其他高招,欢迎交流,谢谢。
参与贡献
项目源码
资源分享
该项目只是写着玩儿,要达到日用级别还不太靠谱,如果真有这种需求,推荐一款软件,搜索易
最后声明
文章就不配图了,图片不好居中,看起来十分不优雅。哈哈哈哈嗝。。。