java监听全局组合键

1. jintellitype

  • pom
    <!-- 不能注册多个组合键比如alt+abc -->
    <!-- https://mvnrepository.com/artifact/com.melloware/jintellitype -->
    <dependency>
    	<groupId>com.melloware</groupId>
    	<artifactId>jintellitype</artifactId>
    	<version>1.4.1</version>
    </dependency>
    
  • 代码
    package com.hotkey.app;
    
    import cn.hutool.core.date.DateUtil;
    import com.melloware.jintellitype.JIntellitype;
    
    public class IntelApplication {
    	public static void main(String[] args) {
    
    		// 添加全局热键
    		JIntellitype instance = JIntellitype.getInstance();
    		instance.registerHotKey(0, JIntellitype.MOD_ALT + JIntellitype.MOD_SHIFT, 'B');
    		instance.registerHotKey(2, 20, 'B');
    		instance.registerHotKey(1, "CTRL+SHIFT+X+V");
    		instance.registerHotKey(3, "CTRL+SHIFT+ALT+WIN+DELETE+B");
    
    		// 添加热键监听器
    		instance.addHotKeyListener(hotkey -> {
    			System.out.println(DateUtil.now() + " Hotkey pressed: " + hotkey);
    			// 在这里处理你的逻辑
    		});
    
    	}
    }
    
  • 缺点: 对于ctrl a b 按ctrl b也可以触发

2. jkeymaster

  • pom
    <!-- https://mvnrepository.com/artifact/com.github.tulskiy/jkeymaster -->
    <dependency>
    	<groupId>com.github.tulskiy</groupId>
    	<artifactId>jkeymaster</artifactId>
    	<version>1.3</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
    <dependency>
    	<groupId>net.java.dev.jna</groupId>
    	<artifactId>jna</artifactId>
    	<version>5.12.1</version>
    </dependency>
    
  • 代码
    import com.tulskiy.keymaster.common.Provider;
    
    import javax.swing.*;
    import java.awt.event.InputEvent;
    import java.awt.event.KeyEvent;
    
    public class KeyApplication {
    
    	public static void main(String[] args) {
    		Provider provider = Provider.getCurrentProvider(true);
    
    		provider.register(
    				KeyStroke.getKeyStroke(KeyEvent.CTRL_MASK,
    						InputEvent.ALT_MASK),
    				x -> System.err.println(x));
    	}
    }
    
  • 缺点: 对于+ = [ ]特殊按键识别不到; 不能注册类似ctrl a b会报错

3. jnativehook(推荐)

  • pom
    <!-- https://mvnrepository.com/artifact/com.1stleg/jnativehook -->
    <dependency>
    	<groupId>com.1stleg</groupId>
    	<artifactId>jnativehook</artifactId>
    	<version>2.1.0</version>
    </dependency>
    
  • 代码: https://gitee.com/codorld/hotkey-app
  • 补充
    • 代码中防止程序再次启动使用的方法是端口占用, 但是测试过程中经常遇到各种问题, 导致启动两次, 可以使用文件锁来实现, 如果可以尽量使用绝对路径
      	/**
       * 通过.hotkey.lock的锁来判断是否有程序启动过
       * 去掉RandomAccessFile的放入try警告, 放进去执行完会自动释放
       *
       * @return true启动过, 不可再次启动, 反之false
       */
      @SuppressWarnings("all")
      private static boolean isAppAlreadyRunning() {
      	try {
      		File lockFile = new File(System.getenv("APPDATA") + "\\hotkey\\.hotkey.lock");
      		if (!lockFile.getParentFile().exists()) {
      			lockFile.getParentFile().mkdirs();
      		}
      		RandomAccessFile file = new RandomAccessFile(lockFile, "rw");
      		FileChannel channel = file.getChannel();
      		FileLock lock = channel.tryLock();
      		return lock == null;  // 如果锁获取失败,说明已经有实例在运行
      	} catch (Exception e) {
      		ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
      		e.printStackTrace(new PrintStream(baoStream));
      		log.error(baoStream.toString());
      		return false;  // 处理异常情况,也可以选择抛出异常
      	}
      }
      
    • 代码中保存单次控制台日志的方法, 在任务计划中行不通, 通过批处理会有命令行弹窗, 体验不好
      • 可以考虑vsb文件, 无窗口方式运行
      • 或者将堆栈信息写入日志文件
        ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
        e.printStackTrace(new PrintStream(baoStream));
        log.error(baoStream.toString());
        
posted @ 2023-12-11 09:27  Codorld  阅读(165)  评论(0编辑  收藏  举报