项目介绍

  全局划词搜索,可实现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之前,再模拟一个事件,就是CtrlShiftAlt的抬起事件(因为一般的快捷键都是包含这三个的),这样就算用户手指还按在键盘上,但是实际这几个键已经不起作用了,之后就该干啥干啥,美滋滋。

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程序员,暂时只能曲线救国的来实现该需求了。

使用说明

  1. 建议打jar包,并将jar包和“file”文件夹中的两个批处理文件一起复制到本地
  2. search.bat创建一个快捷方式并按照上面的描述进行修改。
  3. switch.bat是负责开启和关闭程序的脚本,如果jar包没运行,双击后会在后台启动jar包,如果已经运行了,可根据提示输入相关字符将其关闭。

search.bat的快捷方式只能放在桌面,否则设置了快捷键后是不会生效的,这个是什么原因要@微软了。如果你有强迫症,也可以把它放到开始菜单里,具体操作如下:打开开始菜单,随便找个程序,右键>更多>打开文件位置,此时会打开一个文件夹(不是每个软件都有“打开文件位置”的选项,可以多试几个),之后将刚才的快捷方式放到这里并设置好快捷键,理论上放在这里快捷键也是可以生效的,如果有其他高招,欢迎交流,谢谢。

参与贡献

  炒饭

项目源码

  quick_search

资源分享

  该项目只是写着玩儿,要达到日用级别还不太靠谱,如果真有这种需求,推荐一款软件,搜索易

最后声明

  文章就不配图了,图片不好居中,看起来十分不优雅。哈哈哈哈嗝。。。