Java 標準 API 不支援系統層級的全域熱鍵(Global Hotkey),即應用程式未取得焦點時仍能攔截鍵盤組合鍵。JIntellitype 是基於 JNA (Java Native Access) 封裝 Windows API (RegisterHotKey/UnregisterHotKey) 的輕量級函式庫,可讓 Java 程式在 Windows 系統上註冊全域熱鍵。本文詳細說明整合步驟與完整程式碼範例。
<dependency>
<groupId>com.github.kwhat</groupId>
<artifactId>jintellitype</artifactId>
<version>1.3.9</version>
</dependency>
JIntellitype.dll (32/64 位元) 至臨時目錄並載入,無需手動配置| 方法 | 說明 |
|---|---|
registerHotKey(int id, int modifiers, int keyCode) | 註冊熱鍵,id 為唯一識別碼 |
unregisterHotKey(int id) | 註銷指定熱鍵 |
cleanUp() | 清理所有熱鍵並釋放原生資源 |
addHotKeyListener(HintListener) | 添加熱鍵觸發監聽器 |
修飾鍵常數:MOD_CTRL (1)、MOD_ALT (2)、MOD_SHIFT (4)、MOD_WIN (8),可組合使用 (如 Ctrl+Alt = 3)
虛擬鍵碼:使用 java.awt.event.KeyEvent 常數 (如 VK_F1、VK_A、VK_1)
import com.github.kwhat.jintellitype.HotkeyListener;
import com.github.kwhat.jintellitype.JIntellitype;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
public class GlobalHotkeyDemo extends JFrame {
// 熱鍵 ID 定義
private static final int HOTKEY_SHOW_HIDE = 1001;
private static final int HOTKEY_SCREENSHOT = 1002;
private static final int HOTKEY_QUICK_SEARCH = 1003;
private JTextArea logArea;
private boolean windowVisible = true;
public GlobalHotkeyDemo() {
setTitle("JIntellitype 全域熱鍵示範");
setSize(500, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// UI 初始化
logArea = new JTextArea();
logArea.setEditable(false);
logArea.setFont(new Font("Monospaced", Font.PLAIN, 13));
add(new JScrollPane(logArea), BorderLayout.CENTER);
JPanel hintPanel = new JPanel();
hintPanel.add(new JLabel("熱鍵: Ctrl+Alt+S=顯示/隱藏 | Ctrl+Alt+P=截圖 | Ctrl+Alt+F=快速搜尋"));
add(hintPanel, BorderLayout.SOUTH);
// 註冊全域熱鍵
registerHotkeys();
// 添加熱鍵監聽器
JIntellitype.getInstance().addHotKeyListener(new HotkeyListener() {
@Override
public void onHotKey(int id) {
SwingUtilities.invokeLater(() -> handleHotkey(id));
}
});
setVisible(true);
}
private void registerHotkeys() {
JIntellitype instance = JIntellitype.getInstance();
// Ctrl + Alt + S : 顯示/隱藏視窗
instance.registerHotKey(HOTKEY_SHOW_HIDE,
JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT, KeyEvent.VK_S);
// Ctrl + Alt + P : 螢幕截圖
instance.registerHotKey(HOTKEY_SCREENSHOT,
JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT, KeyEvent.VK_P);
// Ctrl + Alt + F : 快速搜尋 (模擬)
instance.registerHotKey(HOTKEY_QUICK_SEARCH,
JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT, KeyEvent.VK_F);
log("已註冊 3 組全域熱鍵");
}
private void handleHotkey(int id) {
switch (id) {
case HOTKEY_SHOW_HIDE:
windowVisible = !windowVisible;
setVisible(windowVisible);
if (windowVisible) toFront();
log("熱鍵觸發: 視窗" + (windowVisible ? "顯示" : "隱藏"));
break;
case HOTKEY_SCREENSHOT:
log("熱鍵觸發: 執行螢幕截圖...");
// 這裡可呼叫 Robot 截圖邏輯
takeScreenshot();
break;
case HOTKEY_QUICK_SEARCH:
log("熱鍵觸發: 開啟快速搜尋");
// 彈出搜尋框等邏輯
break;
}
}
private void takeScreenshot() {
// 簡易截圖示範
try {
Robot robot = new Robot();
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle rect = new Rectangle(size);
BufferedImage img = robot.createScreenCapture(rect);
File file = new File("screenshot_" + System.currentTimeMillis() + ".png");
ImageIO.write(img, "png", file);
log("截圖已儲存: " + file.getAbsolutePath());
} catch (Exception e) {
log("截圖失敗: " + e.getMessage());
}
}
private void log(String msg) {
String timestamp = java.time.LocalTime.now().toString().substring(0, 8);
logArea.append("[" + timestamp + "] " + msg + "\n");
logArea.setCaretPosition(logArea.getDocument().getLength());
}
@Override
public void dispose() {
// 程式結束時務必清理熱鍵
JIntellitype.getInstance().cleanUp();
super.dispose();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(GlobalHotkeyDemo::new);
}
}
registerHotKey 會靜默失敗。建議提供設定介面讓使用者自訂熱鍵jnativehook 或平台原生 APIcleanUp(),否則熱鍵會殘留在系統中