├── .gitignore ├── KeyHelper.jar ├── README.md ├── dom4j └── dom4j-1.6.1.jar ├── res ├── help.png ├── logo.png ├── power_off.png ├── power_on.png └── screenshot.png └── src ├── cc └── hust │ └── keyhelper │ ├── config │ ├── Config.java │ └── KeySetConfig.java │ ├── core │ ├── KeyhelperCore.java │ └── KeyhelperCoreImpl.java │ ├── frame │ ├── KeyTableModel.java │ ├── MainFrame.java │ └── NewKeyDialog.java │ ├── global │ └── win │ │ ├── JIntellitypeHelper.java │ │ ├── KeyCombination.java │ │ └── KeySwitchBean.java │ └── util │ ├── KeyCodeMap.java │ ├── R.java │ └── StringUtil.java └── com └── melloware └── jintellitype ├── HotkeyListener.java ├── IntellitypeListener.java ├── JIntellitype.dll ├── JIntellitype.java ├── JIntellitype64.dll ├── JIntellitypeConstants.java ├── JIntellitypeException.java └── Main.java /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .settings 3 | bin 4 | .project 5 | *.class 6 | error.log 7 | 8 | *config.xml 9 | -------------------------------------------------------------------------------- /KeyHelper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/KeyHelper.jar -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KeyHelper 2 | 3 | 4 | > 基于 Java Swing 的一款键盘改键程序,初衷是用于 Dota 物品和英雄技能改键,**但是实际上可以用于任何需要改键的地方**。 5 | 6 | 7 | 目前使用了 windows 平台上的 jintellitype 库,利用 jni 的方式获得系统的全局按键信息。 8 | 9 | 10 | ## 运行 & 开发 11 | 12 | 1. Runnable jar 13 | 14 | 直接下载 **KeyHelper.jar** 文件,然后双击运行即可,前提是电脑上有 jre 环境,兼容行不知道,建议 1.6 及以上。 15 | 16 | 2. clone 项目运行 17 | 18 | 将项目 clone 下来,然后将 dom4j 加入到 classpath,不知道是用新版本的 dom4j 会不会有问题(或者 dom4j 几年都没有更新了,好久不写 Java 了,当年毕业的时候想着一定要找一个写 Java 的公司工作)。 19 | 20 | 然后运行 cc.hust.keyhelper.frame 包下的 **MainFrame.java 文件**即可启动。 21 | 22 | 23 | ## 截图示例 24 | 25 | ![screenshot](res/screenshot.png) 26 | 27 | 28 | ---- 29 | 30 | Updated at 2017-03-07 by [hustcc](https://github.com/hustcc). 31 | 32 | 今天突然在项目中找到这个代码,是用来 Dota 改键的,好怀念以前打 Dota 的时候。 33 | 34 | 这个项目是四五年前,那个时候刚开始打 Dota(我是后来才打的,错过了打逗她的最好时机),那个时候是 Dota1,当时的改键工具非常多,还集合着一些外挂程序,乱七八糟,所以就自己做了一个,**专注于改键**。 35 | 36 | 今天找出来这个代码之后,修改了 README 文件,修改了代码文件中的一些老网址(几年前的博客,泪汪汪),添加了一些 gitignore,然后就发上来了,当时学了一段时间的 Java 了,代码写的依然不怎么样。 37 | 38 | 39 | -------------------------------------------------------------------------------- /dom4j/dom4j-1.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/dom4j/dom4j-1.6.1.jar -------------------------------------------------------------------------------- /res/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/res/help.png -------------------------------------------------------------------------------- /res/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/res/logo.png -------------------------------------------------------------------------------- /res/power_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/res/power_off.png -------------------------------------------------------------------------------- /res/power_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/res/power_on.png -------------------------------------------------------------------------------- /res/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/res/screenshot.png -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/config/Config.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 HUST. 3 | * Visit https://github.com/hustcc 4 | * All right reserved. 5 | */ 6 | package cc.hust.keyhelper.config; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.File; 10 | import java.io.FileInputStream; 11 | import java.io.FileOutputStream; 12 | import java.io.InputStreamReader; 13 | 14 | import org.dom4j.Document; 15 | import org.dom4j.DocumentHelper; 16 | import org.dom4j.Element; 17 | import org.dom4j.io.OutputFormat; 18 | import org.dom4j.io.SAXReader; 19 | import org.dom4j.io.XMLWriter; 20 | 21 | /** 22 | * @author Xewee.Zhiwei.Wang 23 | * @version 2013-1-29 上午10:38:45 24 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 25 | */ 26 | public class Config { 27 | //========================================= 28 | public String lastKeySet = "";//上次选择的改键方案 29 | public int lastLocationX = 500;//上次窗口位置 30 | public int lastLocationY = 100;//上次窗口位置 31 | 32 | //========================================= 33 | private final static String CONFIG_FILE = "config.xml"; 34 | private static Config instance = new Config(); 35 | private Config() { 36 | loadFromXml(); 37 | } 38 | public static Config instance() { 39 | return instance; 40 | } 41 | private void loadFromXml() { 42 | try { 43 | SAXReader reader = new SAXReader(); 44 | File file = new File(CONFIG_FILE); 45 | Document document = reader.read(new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")));// 读取XML文件 46 | Element xmlRoot = document.getRootElement();// 得到根节点 47 | 48 | lastKeySet = xmlRoot.elementText("lastKeySet"); 49 | lastLocationX = Integer.valueOf(xmlRoot.elementText("lastLocationX")); 50 | lastLocationY = Integer.valueOf(xmlRoot.elementText("lastLocationY")); 51 | } catch (Exception e) { 52 | lastKeySet = "";//上次选择的改键方案 53 | lastLocationX = 500;//上次窗口位置 54 | lastLocationY = 100;//上次窗口位置 55 | } 56 | } 57 | /** 58 | * TODO 保存用户个性化配置,可以采用xml,也可以采用objectStream(推荐xml) 59 | * @author Xewee.Zhiwei.Wang 60 | * @version 2013-1-29 上午10:57:51 61 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 62 | */ 63 | public void saveToXml() { 64 | /** 建立document对象 */ 65 | Document document = DocumentHelper.createDocument(); 66 | /** 建立config根节点 */ 67 | Element configElement = document.addElement("config"); 68 | configElement.addElement("lastKeySet").setText(lastKeySet); 69 | configElement.addElement("lastLocationX").setText(lastLocationX + ""); 70 | configElement.addElement("lastLocationY").setText(lastLocationY + ""); 71 | try{ 72 | /* 将document中的内容写入文件中 */ 73 | OutputFormat format = new OutputFormat(); 74 | format.setEncoding("UTF-8"); 75 | XMLWriter writer = new XMLWriter(new FileOutputStream(new File(CONFIG_FILE)), format); 76 | writer.write(document); 77 | writer.close(); 78 | } catch(Exception ex) { 79 | ex.printStackTrace(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/config/KeySetConfig.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.config; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.FileNotFoundException; 7 | import java.io.FileOutputStream; 8 | import java.io.InputStreamReader; 9 | import java.util.HashMap; 10 | import java.util.Iterator; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import javax.swing.JOptionPane; 15 | 16 | import org.dom4j.Document; 17 | import org.dom4j.DocumentException; 18 | import org.dom4j.DocumentHelper; 19 | import org.dom4j.Element; 20 | import org.dom4j.io.OutputFormat; 21 | import org.dom4j.io.SAXReader; 22 | import org.dom4j.io.XMLWriter; 23 | 24 | public class KeySetConfig { 25 | private final static String KEYSET_CONFIG_FILE = "key-config.xml"; 26 | 27 | private static KeySetConfig instance = new KeySetConfig(); 28 | //dest ---> src 29 | private Map> keySetMap = new HashMap>(); 30 | 31 | /** 32 | * 得到某一个改键方案的改键数据 33 | * 34 | * @author Xewee.Zhiwei.Wang 35 | * @version 2013-1-29 上午10:24:01 36 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 37 | * @param keySetId 38 | * @return 39 | */ 40 | public Map getKeyMap(Object keySetName) { 41 | return keySetMap.get(keySetName) == null ? new HashMap() : keySetMap.get(keySetName); 42 | } 43 | 44 | /** 45 | * 得到所有的改键方案 46 | * 47 | * @author Xewee.Zhiwei.Wang 48 | * @version 2013-1-29 上午10:24:01 49 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 50 | * @param keySetId 51 | * @return 52 | */ 53 | public Object[] getKeySetArray() { 54 | return keySetMap.keySet().toArray(); 55 | } 56 | 57 | /** 58 | * 单例模式得到实例 59 | * 60 | * @return 61 | */ 62 | public static KeySetConfig instance() { 63 | return instance; 64 | } 65 | 66 | /** 67 | * 初始化改键数据,从xml中获得 68 | */ 69 | private KeySetConfig() { 70 | keySetMap = loadFromXml(); 71 | } 72 | 73 | /** 74 | * 从xml中读取改键数据 75 | * 76 | * @author Xewee.Zhiwei.Wang 77 | * @version 2013-1-29 上午10:24:48 78 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 79 | * @return 80 | * @throws DocumentException 81 | */ 82 | @SuppressWarnings("unchecked") 83 | private Map> loadFromXml() { 84 | try { 85 | // 从xml配置中解析改建 86 | HashMap> map = new HashMap>(); 87 | 88 | SAXReader reader = new SAXReader(); 89 | File file = new File(KEYSET_CONFIG_FILE); 90 | Document document = reader.read(new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")));// 读取XML文件 91 | Element xmlRoot = document.getRootElement();// 得到根节点 92 | 93 | List keys = xmlRoot.elements("keys"); 94 | Map keyMap = null; 95 | List keysetList = null; 96 | for (int i = 0; i < keys.size(); i++) { 97 | keyMap = new HashMap(); 98 | keysetList = keys.get(i).elements("key"); 99 | for (int j = 0; j < keysetList.size(); j++) { 100 | keyMap.put(keysetList.get(j).elementText("dest"), keysetList 101 | .get(j).elementText("src")); 102 | } 103 | map.put(keys.get(i).attributeValue("name"), keyMap); 104 | } 105 | return map; 106 | } catch(FileNotFoundException e) { 107 | // 找不到文件,第一次启动 108 | this.saveToXml(); 109 | return new HashMap>(); 110 | } catch (Exception e) { 111 | JOptionPane.showMessageDialog(null, "key-config.xml配置文件解析错误", 112 | "配置错误", JOptionPane.ERROR_MESSAGE); 113 | System.exit(0); 114 | return null; 115 | } 116 | } 117 | 118 | /** 119 | * 保存到xml 120 | * @author Xewee.Zhiwei.Wang 121 | * @version 2013-4-27 上午10:41:56 122 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 123 | */ 124 | public void saveToXml() { 125 | /** 建立document对象 */ 126 | Document document = DocumentHelper.createDocument(); 127 | Element rootElement = document.addElement("keyset"); 128 | Iterator keyIterator = keySetMap.keySet().iterator(); 129 | String keySetName = ""; 130 | Element keysElement = null; 131 | Map keysMap = null; 132 | Iterator keysMapIterator = null; 133 | String keysKey = ""; 134 | Element keyElement; 135 | while(keyIterator.hasNext()) { 136 | keySetName = keyIterator.next(); 137 | keysElement = rootElement.addElement("keys").addAttribute("name", keySetName); 138 | keysMap = this.keySetMap.get(keySetName); 139 | keysMapIterator = keysMap.keySet().iterator(); 140 | while (keysMapIterator.hasNext()) { 141 | keysKey = keysMapIterator.next(); 142 | keyElement = keysElement.addElement("key");//.addAttribute("id", keysKey); 143 | keyElement.addElement("dest").setText(keysKey); 144 | keyElement.addElement("src").setText(keysMap.get(keysKey)); 145 | } 146 | } 147 | try{ 148 | /* 将document中的内容写入文件中 */ 149 | OutputFormat format = new OutputFormat(); 150 | format.setEncoding("UTF-8"); 151 | XMLWriter writer = new XMLWriter(new FileOutputStream(new File(KEYSET_CONFIG_FILE)),format); 152 | writer.write(document); 153 | writer.close(); 154 | } catch(Exception ex) { 155 | ex.printStackTrace(); 156 | } 157 | } 158 | 159 | /** 160 | * 删除一个改键方案 161 | * @author Xewee.Zhiwei.Wang 162 | * @version 2013-4-22 下午4:55:01 163 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 164 | * @param name 165 | */ 166 | public void delKeySet(Object name) { 167 | keySetMap.remove(name); 168 | } 169 | /** 170 | * 是否存在方案 171 | * @author Xewee.Zhiwei.Wang 172 | * @version 2013-4-28 下午4:50:49 173 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 174 | * @param keySetName 175 | * @return 176 | */ 177 | public boolean existKeySet(String keySetName) { 178 | return keySetMap.get(keySetName.trim()) != null; 179 | } 180 | 181 | /** 182 | * 添加一个改键方案 183 | * @author Xewee.Zhiwei.Wang 184 | * @version 2013-4-22 下午4:55:01 185 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 186 | * @param name 187 | */ 188 | public void addKeySet(String name) { 189 | keySetMap.put(name, new HashMap()); 190 | } 191 | /** 192 | * 存在改键 193 | * @author Xewee.Zhiwei.Wang 194 | * @version 2013-4-29 上午9:14:37 195 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 196 | * @param keySetName 197 | * @return 198 | */ 199 | public boolean existKey(Object keySetName, String src, String dest) { 200 | return keySetMap.get(keySetName).get(dest.trim()) != null; 201 | } 202 | 203 | public void addKey(Object keySetName, String src, String dest) { 204 | keySetMap.get(keySetName).put(dest.toUpperCase(), src.toUpperCase()); 205 | } 206 | /** 207 | * 删除改键方案下面的改键 208 | * @author Xewee.Zhiwei.Wang 209 | * @version 2013-4-28 下午3:29:39 210 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 211 | * @param keySetName 212 | * @param dest 213 | */ 214 | public void delKey(Object keySetName, String dest) { 215 | keySetMap.get(keySetName).remove(dest); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/core/KeyhelperCore.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.core; 2 | 3 | public interface KeyhelperCore { 4 | } 5 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/core/KeyhelperCoreImpl.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.core; 2 | 3 | public class KeyhelperCoreImpl implements KeyhelperCore { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/frame/KeyTableModel.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 HUST. 3 | * Visit https://github.com/hustcc 4 | * All right reserved. 5 | */ 6 | package cc.hust.keyhelper.frame; 7 | 8 | import java.util.Map; 9 | 10 | import javax.swing.table.AbstractTableModel; 11 | 12 | /** 13 | * @author Xewee.Zhiwei.Wang 14 | * @version 2013-1-29 上午10:09:15 15 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 16 | */ 17 | public class KeyTableModel extends AbstractTableModel { 18 | private static final long serialVersionUID = 1L; 19 | /** 20 | * 对应某一方案的改键数据 21 | */ 22 | private String[][] data = null; 23 | private String[] columnName = {"原始按键", "改键"}; 24 | /** 25 | * 重新加载数据 26 | * @author Xewee.Zhiwei.Wang 27 | * @version 2013-1-29 上午10:29:06 28 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 29 | * @param keyMap 30 | */ 31 | public void setModelData(Map keyMap) { 32 | data = keyMap2Array(keyMap); 33 | fireTableDataChanged(); 34 | } 35 | 36 | /** 37 | * 使用keymap做构造器 38 | * @param keyMap 39 | */ 40 | public KeyTableModel(Map keyMap) { 41 | data = keyMap2Array(keyMap); 42 | fireTableDataChanged(); 43 | } 44 | 45 | public int getRowCount() { 46 | return data.length; 47 | } 48 | 49 | public int getColumnCount() { 50 | return columnName.length; 51 | } 52 | 53 | public Object getValueAt(int rowIndex, int columnIndex) { 54 | return data[rowIndex][columnIndex]; 55 | } 56 | 57 | public String getColumnName(int column) { 58 | return columnName[column]; 59 | } 60 | 61 | private String[][] keyMap2Array(Map keyMap) { 62 | String[][] data = new String[keyMap.size()][2]; 63 | Object[] objects = keyMap.keySet().toArray(); 64 | for (int i = 0; i < objects.length; i++) { 65 | data[i][0] = keyMap.get(objects[i].toString()); 66 | data[i][1] = objects[i].toString(); 67 | } 68 | return data; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/frame/MainFrame.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.frame; 2 | 3 | import java.awt.Cursor; 4 | import java.awt.EventQueue; 5 | import java.awt.Toolkit; 6 | import java.awt.event.ActionEvent; 7 | import java.awt.event.ActionListener; 8 | import java.awt.event.MouseAdapter; 9 | import java.awt.event.MouseEvent; 10 | import java.awt.event.WindowAdapter; 11 | import java.awt.event.WindowEvent; 12 | import java.io.File; 13 | import java.io.FileNotFoundException; 14 | import java.io.IOException; 15 | import java.io.PrintWriter; 16 | 17 | import javax.swing.ImageIcon; 18 | import javax.swing.JButton; 19 | import javax.swing.JComboBox; 20 | import javax.swing.JFrame; 21 | import javax.swing.JLabel; 22 | import javax.swing.JOptionPane; 23 | import javax.swing.JPanel; 24 | import javax.swing.JScrollPane; 25 | import javax.swing.JTable; 26 | import javax.swing.UIManager; 27 | import javax.swing.border.EmptyBorder; 28 | 29 | import cc.hust.keyhelper.config.Config; 30 | import cc.hust.keyhelper.config.KeySetConfig; 31 | import cc.hust.keyhelper.global.win.JIntellitypeHelper; 32 | import cc.hust.keyhelper.util.R; 33 | import cc.hust.keyhelper.util.StringUtil; 34 | 35 | import com.melloware.jintellitype.JIntellitype; 36 | /** 37 | * 主界面 38 | * @author Xewee.Zhiwei.Wang 39 | * @version 2013-1-29 上午9:59:55 40 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 41 | */ 42 | @SuppressWarnings({ "unchecked", "rawtypes" }) 43 | public class MainFrame extends JFrame implements ActionListener { 44 | /** 45 | * 46 | */ 47 | private static final long serialVersionUID = 1L; 48 | 49 | private JPanel contentPane; 50 | private JTable table;//改键明细的table 51 | private KeyTableModel tableModel; 52 | private JComboBox chooseKeySetCombo;//方案选择下拉框 53 | JButton newKeySetButton;//新建改键方案 54 | JButton newKeyButton;//新建改键 55 | JButton delKeyButton;//删除改键 56 | JButton delKeySetButton;//删除方案 57 | JButton startButton;//开始监听改键(电脑全屏或者war运行中,且不是输入模式) 58 | // JLabel emailLabel; 59 | JLabel helpLabel; 60 | private boolean isListening = false; 61 | /** 62 | * Launch the application. 63 | * @throws FileNotFoundException 64 | */ 65 | public static void main(String[] args) throws FileNotFoundException { 66 | try { 67 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 68 | //UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 69 | } catch(Exception e) {} 70 | try { 71 | if (JIntellitype.checkInstanceAlreadyRunning("JIntellitype Test Application")) { 72 | System.exit(1); 73 | } 74 | if (!JIntellitype.isJIntellitypeSupported()) { 75 | System.exit(1); 76 | } 77 | 78 | EventQueue.invokeLater(new Runnable() { 79 | public void run() { 80 | MainFrame frame = new MainFrame(); 81 | frame.setVisible(true); 82 | } 83 | }); 84 | } catch (Exception e) { 85 | e.printStackTrace(new PrintWriter(new File("error.log"))); 86 | System.exit(1); 87 | } 88 | } 89 | 90 | /** 91 | * Create the frame. 92 | */ 93 | public MainFrame() { 94 | setTitle("KeyHelper - hustcc"); 95 | setResizable(false); 96 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 97 | setBounds(100, 100, 295, 444); 98 | contentPane = new JPanel(); 99 | contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 100 | setContentPane(contentPane); 101 | contentPane.setLayout(null); 102 | 103 | chooseKeySetCombo = new JComboBox(KeySetConfig.instance().getKeySetArray()); 104 | chooseKeySetCombo.setBounds(10, 10, 176, 21); 105 | chooseKeySetCombo.addActionListener(this); 106 | contentPane.add(chooseKeySetCombo); 107 | 108 | newKeySetButton = new JButton("新建方案"); 109 | newKeySetButton.setToolTipText("新建方案"); 110 | newKeySetButton.setBounds(196, 10, 83, 23); 111 | newKeySetButton.addActionListener(this); 112 | contentPane.add(newKeySetButton); 113 | 114 | newKeyButton = new JButton("新增改键"); 115 | newKeyButton.setToolTipText("新增改键"); 116 | newKeyButton.setBounds(10, 41, 83, 23); 117 | newKeyButton.addActionListener(this); 118 | contentPane.add(newKeyButton); 119 | 120 | delKeyButton = new JButton("删除改键"); 121 | delKeyButton.setToolTipText("删除改键"); 122 | delKeyButton.setBounds(103, 41, 83, 23); 123 | delKeyButton.addActionListener(this); 124 | contentPane.add(delKeyButton); 125 | 126 | delKeySetButton = new JButton("删除方案"); 127 | delKeySetButton.setToolTipText("删除方案"); 128 | delKeySetButton.setBounds(196, 41, 83, 23); 129 | delKeySetButton.addActionListener(this); 130 | contentPane.add(delKeySetButton); 131 | 132 | tableModel = new KeyTableModel(KeySetConfig.instance().getKeyMap(chooseKeySetCombo.getSelectedItem())); 133 | table = new JTable(tableModel); 134 | JScrollPane scrollpane = new JScrollPane(table); 135 | scrollpane.setBounds(10, 74, 269, 302); 136 | contentPane.add(scrollpane); 137 | 138 | startButton = new JButton(); 139 | startButton.setIcon(new ImageIcon(R.POWER_OFF_PIC_PATH)); 140 | startButton.setText("Start"); 141 | startButton.setBounds(196, 386, 83, 23); 142 | startButton.setToolTipText("按Alt + Z切换监听状态."); 143 | startButton.addActionListener(this); 144 | contentPane.add(startButton); 145 | 146 | // emailLabel = new JLabel(); 147 | // emailLabel.setIcon(new ImageIcon(R.EMAIL_PIC_PATH)); 148 | // emailLabel.setBounds(10, 386, 160, 23); 149 | // emailLabel.addMouseListener(new MouseAdapter() { 150 | // public void mouseClicked(MouseEvent e) { 151 | // try { 152 | // Runtime.getRuntime().exec("cmd /c start https://github.com/hustcc/KeyHelper"); 153 | // } catch (IOException e1) { 154 | // e1.printStackTrace(); 155 | // } 156 | // } 157 | // public void mouseEntered(MouseEvent e) { 158 | // emailLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); 159 | // } 160 | // }); 161 | // contentPane.add(emailLabel); 162 | 163 | helpLabel = new JLabel(); 164 | helpLabel.setIcon(new ImageIcon(R.HELP_PIC_PATH)); 165 | helpLabel.setBounds(173, 386, 20, 23); 166 | helpLabel.addMouseListener(new MouseAdapter() { 167 | public void mouseClicked(MouseEvent e) { 168 | try { 169 | Runtime.getRuntime().exec("cmd /c start https://github.com/hustcc/KeyHelper"); 170 | } catch (IOException e1) { 171 | e1.printStackTrace(); 172 | } 173 | } 174 | public void mouseEntered(MouseEvent e) { 175 | helpLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); 176 | } 177 | }); 178 | contentPane.add(helpLabel); 179 | 180 | addWindowListener(new WindowAdapter() { 181 | public void windowClosing(WindowEvent e) { 182 | System.out.println("windows closing, save data."); 183 | Config.instance().lastKeySet = chooseKeySetCombo.getSelectedItem() != null ? chooseKeySetCombo.getSelectedItem().toString() : ""; 184 | Config.instance().lastLocationX = getLocation().x; 185 | Config.instance().lastLocationY = getLocation().y; 186 | Config.instance().saveToXml(); 187 | KeySetConfig.instance().saveToXml(); 188 | JIntellitype.getInstance().cleanUp(); 189 | super.windowClosing(e); 190 | } 191 | }); 192 | JIntellitypeHelper.instance(this).initJIntellitype(); 193 | //个性化配置 194 | chooseKeySetCombo.setSelectedItem(Config.instance().lastKeySet); 195 | chooseKeySetCombo.setToolTipText(String.valueOf(chooseKeySetCombo.getSelectedItem())); 196 | setLocation(Config.instance().lastLocationX, Config.instance().lastLocationY); 197 | setIconImage(Toolkit.getDefaultToolkit().createImage(R.LOGO_PIC_PATH)); 198 | } 199 | 200 | public void actionPerformed(ActionEvent e) { 201 | Object srcObject = e.getSource(); 202 | if (srcObject == newKeySetButton) { 203 | String keySet = JOptionPane.showInputDialog("请输入改键方案的名称:"); 204 | if(keySet != null) { 205 | if (StringUtil.isBlank(keySet)) { 206 | JOptionPane.showMessageDialog(this, "改键方案的名称不能为空,请重试!", "提示", JOptionPane.WARNING_MESSAGE); 207 | return; 208 | } 209 | if (KeySetConfig.instance().existKeySet(keySet)) { 210 | JOptionPane.showMessageDialog(this, "改键方案的名称已经【" + keySet + "】存在,请重试!", "提示", JOptionPane.WARNING_MESSAGE); 211 | return; 212 | } 213 | KeySetConfig.instance().addKeySet(keySet); 214 | chooseKeySetCombo.addItem(keySet); 215 | chooseKeySetCombo.setSelectedItem(keySet); 216 | } 217 | } 218 | else if (srcObject == newKeyButton) { 219 | if (chooseKeySetCombo.getSelectedItem() == null) { 220 | JOptionPane.showMessageDialog(this, "不存在改键方案,请先添加改键方案!", "WARNING", JOptionPane.WARNING_MESSAGE); 221 | return; 222 | } 223 | new NewKeyDialog(this).setVisible(true); 224 | } 225 | else if (srcObject == delKeyButton) { 226 | int row = table.getSelectedRow(); 227 | //合法的选择 228 | if (row >= 0) { 229 | int result = JOptionPane.showConfirmDialog(this, "确定删除改键 【" +table.getValueAt(row, 0) + "=>" + table.getValueAt(row, 1) +"】 ?","提示",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE); 230 | if (result == JOptionPane.YES_OPTION){ 231 | //取消监听 232 | if (isListening) { 233 | JIntellitypeHelper.instance(this).unregiste(table.getValueAt(row, 1).toString()); 234 | } 235 | //删除内存数据 236 | KeySetConfig.instance().delKey(chooseKeySetCombo.getSelectedItem(), table.getValueAt(row, 1).toString()); 237 | //重绘表格 238 | tableModel.setModelData(KeySetConfig.instance().getKeyMap(chooseKeySetCombo.getSelectedItem())); 239 | } 240 | } 241 | else { 242 | JOptionPane.showMessageDialog(this, "请选择要删除的改键", "提示", JOptionPane.INFORMATION_MESSAGE); 243 | } 244 | 245 | } 246 | else if (srcObject == delKeySetButton) { 247 | String selectedtItem = String.valueOf(chooseKeySetCombo.getSelectedItem()); 248 | //确定是否删除当前下拉列表的选项 249 | int result = JOptionPane.showConfirmDialog(this, "确定删除改键方案 【"+selectedtItem+"】 ?","提示",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE); 250 | if (result == JOptionPane.YES_OPTION){ 251 | KeySetConfig.instance().delKeySet(chooseKeySetCombo.getSelectedItem()); 252 | chooseKeySetCombo.removeItem(chooseKeySetCombo.getSelectedItem()); 253 | } 254 | } 255 | else if (srcObject == startButton) { 256 | //正在监听,取消监听 257 | if (isListening) { 258 | startButton.setIcon(new ImageIcon(R.POWER_OFF_PIC_PATH)); 259 | startButton.setText("Start"); 260 | isListening = false; 261 | JIntellitypeHelper.instance(this).unregisteAll(); 262 | } 263 | //开始监听 264 | else { 265 | startButton.setIcon(new ImageIcon(R.POWER_ON_PIC_PATH)); 266 | startButton.setText("Stop"); 267 | isListening = true; 268 | JIntellitypeHelper.instance(this).registe(KeySetConfig.instance().getKeyMap(chooseKeySetCombo.getSelectedItem())); 269 | } 270 | } 271 | else if (srcObject == chooseKeySetCombo) { 272 | chooseKeySetCombo.setToolTipText(String.valueOf(chooseKeySetCombo.getSelectedItem())); 273 | tableModel.setModelData(KeySetConfig.instance().getKeyMap(chooseKeySetCombo.getSelectedItem())); 274 | //如果正在运行,更换监听 275 | if (isListening) { 276 | JIntellitypeHelper.instance(this).unregisteAll(); 277 | JIntellitypeHelper.instance(this).registe(KeySetConfig.instance().getKeyMap(chooseKeySetCombo.getSelectedItem())); 278 | } 279 | } 280 | } 281 | 282 | public synchronized boolean isListening() { 283 | return isListening; 284 | } 285 | public void setListening(boolean isListening) { 286 | this.isListening = isListening; 287 | } 288 | public JButton getStartButton() { 289 | return startButton; 290 | } 291 | public void setStartButton(JButton startButton) { 292 | this.startButton = startButton; 293 | } 294 | 295 | public KeyTableModel getTableModel() { 296 | return tableModel; 297 | } 298 | 299 | public void setTableModel(KeyTableModel tableModel) { 300 | this.tableModel = tableModel; 301 | } 302 | 303 | public JComboBox getChooseKeySetCombo() { 304 | return chooseKeySetCombo; 305 | } 306 | 307 | public void setChooseKeySetCombo(JComboBox chooseKeySetCombo) { 308 | this.chooseKeySetCombo = chooseKeySetCombo; 309 | } 310 | 311 | } 312 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/frame/NewKeyDialog.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Xewee.Zhiwei.Wang 3 | * @version 2013-4-28 下午5:06:50 4 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 5 | */ 6 | package cc.hust.keyhelper.frame; 7 | 8 | import java.awt.Color; 9 | import java.awt.Cursor; 10 | import java.awt.Dimension; 11 | import java.awt.Toolkit; 12 | import java.awt.event.ActionEvent; 13 | import java.awt.event.ActionListener; 14 | import java.awt.event.FocusEvent; 15 | import java.awt.event.FocusListener; 16 | import java.awt.event.KeyEvent; 17 | import java.awt.event.KeyListener; 18 | import java.awt.event.MouseAdapter; 19 | import java.awt.event.MouseEvent; 20 | import java.io.IOException; 21 | 22 | import javax.swing.ImageIcon; 23 | import javax.swing.JButton; 24 | import javax.swing.JCheckBox; 25 | import javax.swing.JComponent; 26 | import javax.swing.JDialog; 27 | import javax.swing.JLabel; 28 | import javax.swing.JOptionPane; 29 | import javax.swing.JTextField; 30 | 31 | import cc.hust.keyhelper.config.KeySetConfig; 32 | import cc.hust.keyhelper.global.win.JIntellitypeHelper; 33 | import cc.hust.keyhelper.global.win.KeyCombination; 34 | import cc.hust.keyhelper.util.KeyCodeMap; 35 | import cc.hust.keyhelper.util.R; 36 | import cc.hust.keyhelper.util.StringUtil; 37 | 38 | /** 39 | * 40 | * @author Xewee.Zhiwei.Wang 41 | * @version 2013-4-28 下午5:06:50 42 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 43 | */ 44 | public class NewKeyDialog extends JDialog implements ActionListener, KeyListener, FocusListener { 45 | private static final long serialVersionUID = 1L; 46 | private MainFrame parent; 47 | private JTextField srcTextField; 48 | private JTextField destTextField; 49 | private JButton okButton; 50 | private JButton cancelButton; 51 | private JCheckBox handCheckBox; 52 | private JLabel helpLabel; 53 | 54 | public NewKeyDialog(MainFrame parent) { 55 | this.parent = parent; 56 | 57 | setResizable(false); 58 | setModal(true); 59 | setTitle("添加改键"); 60 | getContentPane().setLayout(null); 61 | setSize(340, 140); 62 | setLocation(parent.getLocation().x + parent.getWidth() / 2, parent.getLocation().y + parent.getHeight() / 2); 63 | Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 64 | setLocation( (screenSize.width - getSize().width) / 2, (screenSize.height - getSize().height) / 2); 65 | 66 | JLabel noticeLabel = new JLabel("注:原键=>改键 意为 按下改键触发原键"); 67 | noticeLabel.setForeground(Color.RED); 68 | noticeLabel.setBounds(10, 10, 314, 15); 69 | getContentPane().add(noticeLabel); 70 | 71 | JLabel srcKeyLabel = new JLabel("原键:"); 72 | srcKeyLabel.setBounds(10, 39, 36, 15); 73 | getContentPane().add(srcKeyLabel); 74 | 75 | srcTextField = new JTextField(); 76 | srcTextField.setBounds(49, 36, 91, 21); 77 | getContentPane().add(srcTextField); 78 | srcTextField.setColumns(10); 79 | srcTextField.setToolTipText("原始键 - 可以为组合键"); 80 | srcTextField.addKeyListener(this); 81 | srcTextField.addFocusListener(this); 82 | srcTextField.requestFocus(); 83 | 84 | JLabel toLabel = new JLabel(" ==>"); 85 | toLabel.setBounds(150, 39, 27, 15); 86 | getContentPane().add(toLabel); 87 | 88 | JLabel destKeyLabel = new JLabel("改键:"); 89 | destKeyLabel.setBounds(187, 39, 36, 15); 90 | getContentPane().add(destKeyLabel); 91 | 92 | destTextField = new JTextField(); 93 | destTextField.setBounds(233, 36, 91, 21); 94 | getContentPane().add(destTextField); 95 | destTextField.setToolTipText("改键 - 可以为组合键"); 96 | destTextField.setColumns(10); 97 | destTextField.addKeyListener(this); 98 | destTextField.addFocusListener(this); 99 | 100 | 101 | cancelButton = new JButton("取消"); 102 | cancelButton.setBounds(258, 79, 66, 23); 103 | cancelButton.addActionListener(this); 104 | getContentPane().add(cancelButton); 105 | 106 | okButton = new JButton("确定"); 107 | okButton.setBounds(187, 79, 66, 23); 108 | okButton.addActionListener(this); 109 | getContentPane().add(okButton); 110 | 111 | handCheckBox = new JCheckBox("手动模式"); 112 | handCheckBox.setToolTipText("勾选后手动配置按键"); 113 | handCheckBox.setBounds(10, 79, 97, 23); 114 | handCheckBox.addActionListener(this); 115 | getContentPane().add(handCheckBox); 116 | 117 | helpLabel = new JLabel(""); 118 | helpLabel.setBounds(113, 79, 27, 23); 119 | getContentPane().add(helpLabel); 120 | helpLabel.setIcon(new ImageIcon(R.HELP_PIC_PATH)); 121 | helpLabel.addMouseListener(new MouseAdapter() { 122 | public void mouseClicked(MouseEvent e) { 123 | try { 124 | Runtime.getRuntime().exec("cmd /c start https://github.com/hustcc/KeyHelper"); 125 | } catch (IOException e1) { 126 | e1.printStackTrace(); 127 | } 128 | } 129 | public void mouseEntered(MouseEvent e) { 130 | helpLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); 131 | } 132 | }); 133 | 134 | setIconImage(Toolkit.getDefaultToolkit().createImage(R.LOGO_PIC_PATH)); 135 | } 136 | public void actionPerformed(ActionEvent e) { 137 | Object source = e.getSource(); 138 | if (source == okButton) { 139 | if (StringUtil.isBlank(srcTextField.getText())) { 140 | JOptionPane.showMessageDialog(this, "原键不能为空,请设置后再试!", "WARNING", JOptionPane.WARNING_MESSAGE); 141 | srcTextField.requestFocus(); 142 | return; 143 | } 144 | else if (StringUtil.isBlank(destTextField.getText())) { 145 | JOptionPane.showMessageDialog(this, "改键不能为空,请设置后再试!", "WARNING", JOptionPane.WARNING_MESSAGE); 146 | destTextField.requestFocus(); 147 | return; 148 | } 149 | else if (KeySetConfig.instance().existKey(parent.getChooseKeySetCombo().getSelectedItem(), srcTextField.getText(), destTextField.getText())) { 150 | JOptionPane.showMessageDialog(this, "改键方案中已经存在映射到【" + destTextField.getText() + "】的改键,请重新设置!", "WARNING", JOptionPane.WARNING_MESSAGE); 151 | destTextField.requestFocus(); 152 | return; 153 | } 154 | String[] keys = KeyCombination.splitKeyCombination(srcTextField.getText()); 155 | for (int i = 0; i < keys.length; i++) { 156 | if (KeyCodeMap.getJavaKeyCode(keys[i]) == null) { 157 | JOptionPane.showMessageDialog(this, "按键是一个不存在的按键获组合按键!", "WARNING", JOptionPane.WARNING_MESSAGE); 158 | srcTextField.requestFocus(); 159 | srcTextField.selectAll(); 160 | return; 161 | } 162 | } 163 | 164 | keys = KeyCombination.splitKeyCombination(destTextField.getText()); 165 | for (int i = 0; i < keys.length; i++) { 166 | if (KeyCodeMap.getJavaKeyCode(keys[i]) == null) { 167 | JOptionPane.showMessageDialog(this, "改键是一个不存在的按键获组合按键!", "WARNING", JOptionPane.WARNING_MESSAGE); 168 | destTextField.requestFocus(); 169 | destTextField.selectAll(); 170 | return; 171 | } 172 | } 173 | 174 | // if (KeyCodeMap.getJavaKeyCode(destTextField.getText()) == null) { 175 | // JOptionPane.showMessageDialog(this, "改键是一个不存在的按键", "WARNING", JOptionPane.WARNING_MESSAGE); 176 | // destTextField.requestFocus(); 177 | // destTextField.selectAll(); 178 | // return; 179 | // } 180 | //加到内存中 181 | KeySetConfig.instance().addKey(parent.getChooseKeySetCombo().getSelectedItem(), srcTextField.getText(), destTextField.getText()); 182 | //显示在table中 183 | parent.getTableModel().setModelData(KeySetConfig.instance().getKeyMap(parent.getChooseKeySetCombo().getSelectedItem())); 184 | //如果正在监听,监听这个键 185 | if (parent.isListening()) { 186 | JIntellitypeHelper.instance(parent).registe(srcTextField.getText(), destTextField.getText()); 187 | } 188 | //关闭添加按键的窗口 189 | this.setVisible(false); 190 | this.dispose(); 191 | } 192 | else if (source == cancelButton) { 193 | this.setVisible(false); 194 | this.dispose(); 195 | } 196 | else if (source == handCheckBox) { 197 | if (handCheckBox.isSelected()) { 198 | srcTextField.removeKeyListener(this); 199 | destTextField.removeKeyListener(this); 200 | } 201 | else { 202 | srcTextField.addKeyListener(this); 203 | destTextField.addKeyListener(this); 204 | } 205 | } 206 | } 207 | public void keyPressed(KeyEvent e) { 208 | if (KeyCodeMap.isShieldKeyCode(e.getKeyCode())){//屏蔽键,如Tab、ESC键 209 | ((JTextField)e.getSource()).setText(KeyCombination.getKeyCombination(e, true)); 210 | e.consume();//注销键盘事件 211 | } 212 | else { 213 | ((JTextField)e.getSource()).setText(KeyCombination.getKeyCombination(e, true)); 214 | } 215 | } 216 | public void keyReleased(KeyEvent e) { 217 | //按下Print Screen鍵不触发 keyPressed方法,只調用keyReleased 218 | if(e.getKeyCode() == KeyEvent.VK_PRINTSCREEN){ 219 | ((JTextField)e.getSource()).setText(KeyCombination.getKeyCombination(e, e.getSource() != destTextField)); 220 | } 221 | } 222 | public void keyTyped(KeyEvent e) { 223 | 224 | } 225 | public void focusGained(FocusEvent e) { 226 | if (handCheckBox.isSelected()) { 227 | ((JTextField)e.getSource()).getInputMap().setParent(new JTextField().getInputMap(JComponent.WHEN_FOCUSED));//屏蔽JTextField默认的键盘事件 228 | ((JTextField)e.getSource()).enableInputMethods (true);//关闭控件输入法的方法 229 | ((JTextField)e.getSource()).setFocusTraversalKeysEnabled(true); 230 | } 231 | else { 232 | ((JTextField)e.getSource()).getInputMap().setParent(null);//屏蔽JTextField默认的键盘事件 233 | ((JTextField)e.getSource()).enableInputMethods (false);//关闭控件输入法的方法 234 | ((JTextField)e.getSource()).setFocusTraversalKeysEnabled(false); 235 | } 236 | } 237 | public void focusLost(FocusEvent e) { 238 | 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/global/win/JIntellitypeHelper.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.global.win; 2 | 3 | import java.awt.AWTException; 4 | import java.awt.Robot; 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | import java.util.Map; 8 | 9 | import cc.hust.keyhelper.config.KeySetConfig; 10 | import cc.hust.keyhelper.frame.MainFrame; 11 | import cc.hust.keyhelper.util.KeyCodeMap; 12 | 13 | import com.melloware.jintellitype.HotkeyListener; 14 | import com.melloware.jintellitype.IntellitypeListener; 15 | import com.melloware.jintellitype.JIntellitype; 16 | 17 | /** 18 | * 监听管理类 19 | * @author Xewee.Zhiwei.Wang 20 | * @version 2013-1-29 上午11:10:12 21 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 22 | */ 23 | public class JIntellitypeHelper implements HotkeyListener, IntellitypeListener { 24 | public static int HOT_KEY_START = 0; 25 | private static int IDENTIFIER = 1; 26 | private Robot robot; 27 | private MainFrame parent; 28 | private static JIntellitypeHelper instance; 29 | 30 | private Map registedKey = new HashMap(); 31 | 32 | private JIntellitypeHelper(MainFrame parent) { 33 | this.parent = parent; 34 | } 35 | /** 36 | * 退出程序,清除资源 37 | * @author Xewee.Zhiwei.Wang 38 | * @version 2013-1-29 下午1:26:52 39 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 40 | */ 41 | public void cleanUp() { 42 | JIntellitype.getInstance().cleanUp(); 43 | } 44 | /** 45 | * 启动程序,初始化监控 46 | * @author Xewee.Zhiwei.Wang 47 | * @version 2013-1-29 下午1:27:05 48 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 49 | */ 50 | public void initJIntellitype() { 51 | try { 52 | JIntellitype.getInstance().addHotKeyListener(this); 53 | JIntellitype.getInstance().addIntellitypeListener(this); 54 | robot = new Robot(); 55 | System.out.println("initial JIntellitype SUCCESS."); 56 | //注册监听切换按钮Alt + Z 57 | JIntellitype.getInstance().registerHotKey(HOT_KEY_START, JIntellitype.MOD_ALT, 'Z'); 58 | } catch (RuntimeException e) { 59 | System.out.println("initial JIntellitype ERROR."); 60 | } catch (AWTException e) { 61 | System.out.println("initial JIntellitype ERROR."); 62 | } 63 | } 64 | /** 65 | * 注册监听的按键 66 | * @author Xewee.Zhiwei.Wang 67 | * @version 2013-1-29 下午1:37:43 68 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 69 | * @param keyMap 70 | */ 71 | public void registe(Map keyMap) { 72 | registedKey.clear(); 73 | //注册配置文件中的改键 74 | Iterator keyIterator = keyMap.keySet().iterator(); 75 | KeySwitchBean bean = null; 76 | while (keyIterator.hasNext()) { 77 | bean = new KeySwitchBean(); 78 | bean.destKey = keyIterator.next(); 79 | bean.srcKey = keyMap.get(bean.destKey); 80 | 81 | registedKey.put(IDENTIFIER, bean); 82 | JIntellitype.getInstance().registerHotKey(IDENTIFIER ++, bean.destKey); 83 | } 84 | System.out.println("JIntellitype registe."); 85 | } 86 | /** 87 | * 注册单个按键 88 | * @author Xewee.Zhiwei.Wang 89 | * @version 2013-4-29 上午9:23:47 90 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 91 | * @param src 92 | * @param dest 93 | */ 94 | public void registe(String src, String dest) { 95 | KeySwitchBean bean = new KeySwitchBean(src, dest); 96 | registedKey.put(KeyCodeMap.getJavaKeyCode(bean.destKey), bean); 97 | JIntellitype.getInstance().registerHotKey(KeyCodeMap.getJavaKeyCode(bean.destKey), bean.destKey); 98 | } 99 | /** 100 | * 取消按键注册 101 | * @author Xewee.Zhiwei.Wang 102 | * @version 2013-1-29 下午1:37:54 103 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 104 | */ 105 | public void unregisteAll() { 106 | if (registedKey != null) { 107 | Iterator keyIterator = registedKey.keySet().iterator(); 108 | while (keyIterator.hasNext()) { 109 | JIntellitype.getInstance().unregisterHotKey(keyIterator.next()); 110 | } 111 | } 112 | System.out.println("JIntellitype unregiste."); 113 | } 114 | /** 115 | * 取消监听按键 116 | * @author Xewee.Zhiwei.Wang 117 | * @version 2013-4-28 下午4:35:30 118 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 119 | */ 120 | public void unregiste(String key) { 121 | if (registedKey != null) { 122 | JIntellitype.getInstance().unregisterHotKey(KeyCodeMap.getJavaKeyCode(key)); 123 | registedKey.remove(KeyCodeMap.getJavaKeyCode(key)); 124 | } 125 | System.out.println("JIntellitype unregiste " + key + "."); 126 | } 127 | 128 | /** 129 | * 获取已经存在的instance 130 | * @author Xewee.Zhiwei.Wang 131 | * @version 2013-1-29 上午11:22:01 132 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 133 | * @return 134 | */ 135 | public static JIntellitypeHelper instance(MainFrame parent) { 136 | if (instance == null) { 137 | instance = new JIntellitypeHelper(parent); 138 | } 139 | return instance; 140 | } 141 | public void onHotKey(int aIdentifier) { 142 | if (aIdentifier == HOT_KEY_START) { 143 | parent.getStartButton().doClick(); 144 | KeySetConfig.instance().saveToXml(); 145 | return ; 146 | } 147 | 148 | KeySwitchBean bean = registedKey.get(aIdentifier); 149 | System.out.println(bean); 150 | //先取消注册,再触发原来的按键,然后注册监听,防止监听死循环 151 | JIntellitype.getInstance().unregisterHotKey(aIdentifier); 152 | //TODO 如果是全屏,并且鼠标状态不是输入状态,改键 153 | if (true) { 154 | // robot.keyPress(KeyCodeMap.getJavaKeyCode(bean.srcKey)); 155 | // robot.delay(5); 156 | // robot.keyRelease(KeyCodeMap.getJavaKeyCode(bean.srcKey)); 157 | String[] keys = KeyCombination.splitKeyCombination(bean.srcKey); 158 | for (int i = 0; i < keys.length; i++) { 159 | robot.keyPress(KeyCodeMap.getJavaKeyCode(keys[i])); 160 | } 161 | 162 | robot.delay(5);//睡眠指定的时间 163 | for (int i = 0; i < keys.length; i++) { 164 | robot.keyRelease(KeyCodeMap.getJavaKeyCode(keys[i])); 165 | } 166 | } 167 | // else { 168 | // //否则,触发原来的按键 169 | // robot.keyPress(KeyCodeMap.getJavaKeyCode(bean.destKey)); 170 | // robot.delay(5); 171 | // robot.keyRelease(KeyCodeMap.getJavaKeyCode(bean.destKey)); 172 | // } 173 | //重新注册 174 | JIntellitype.getInstance().registerHotKey(aIdentifier, bean.destKey); 175 | } 176 | public void onIntellitype(int aCommand) { 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/global/win/KeyCombination.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.global.win; 2 | 3 | /** 4 | * get Key Combination by using modifiers 5 | * split Key Combination to single key 6 | * @author Michael.Jiahui.Mai 7 | * @version 2013-04-08 19:29:23 8 | * @Contract kafaimak@yahoo.cn or https://github.com/hustcc 9 | */ 10 | 11 | import java.awt.event.InputEvent; 12 | import java.awt.event.KeyEvent; 13 | 14 | import cc.hust.keyhelper.util.KeyCodeMap; 15 | 16 | public class KeyCombination { 17 | // 得到组合键字符串,用于表格对组合键的显示 18 | public static String getKeyCombination(KeyEvent e, boolean combination) { 19 | String presskey = KeyCodeMap.getKey(e.getKeyCode()); 20 | int mod = e.getModifiersEx(); 21 | if (! combination) { 22 | return presskey; 23 | } 24 | if ((mod & InputEvent.ALT_GRAPH_DOWN_MASK) != 0 25 | && e.getKeyCode() != KeyEvent.VK_ALT_GRAPH) { 26 | presskey = "SHIFT+" + presskey; 27 | } 28 | if ((mod & InputEvent.META_DOWN_MASK) != 0 29 | && e.getKeyCode() != KeyEvent.VK_META) { 30 | presskey = "SHIFT+" + presskey; 31 | } 32 | if ((mod & InputEvent.SHIFT_DOWN_MASK) != 0 33 | && e.getKeyCode() != KeyEvent.VK_SHIFT) { 34 | presskey = "SHIFT+" + presskey; 35 | } 36 | if ((mod & InputEvent.ALT_DOWN_MASK) != 0 37 | && e.getKeyCode() != KeyEvent.VK_ALT) { 38 | presskey = "ALT+" + presskey; 39 | } 40 | if ((mod & InputEvent.CTRL_DOWN_MASK) != 0 41 | && e.getKeyCode() != KeyEvent.VK_CONTROL) { 42 | presskey = "CTRL+" + presskey; 43 | } 44 | return presskey; 45 | } 46 | // 得到组合键的各个单键 47 | public static String[] splitKeyCombination(String keyCombination) { 48 | return keyCombination.split("\\+"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/global/win/KeySwitchBean.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.global.win; 2 | 3 | public class KeySwitchBean { 4 | public String srcKey; 5 | public String destKey; 6 | public KeySwitchBean() { 7 | this("", ""); 8 | } 9 | public KeySwitchBean(String srcKey, String destKey) { 10 | this.srcKey = srcKey; 11 | this.destKey = destKey; 12 | } 13 | public String toString() { 14 | return this.srcKey + "=>" + this.destKey; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/util/KeyCodeMap.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.util; 2 | 3 | /******************Michael**********************/ 4 | /******************Start************************/ 5 | 6 | /** 7 | * @author Michael.Jiahui.Mai 8 | * @version 2013-04-05 22:20:39 9 | * @Contract kafaimak@yahoo.cn or https://github.com/hustcc 10 | */ 11 | 12 | /** 13 | * 输入文本框编辑器时,Enter键要按Ctrl+Enter才能输入 14 | * 15 | */ 16 | 17 | import java.awt.event.KeyEvent; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | 22 | public class KeyCodeMap { 23 | static Map keycode2str = new HashMap();//键值对应的字符串 24 | static Map str2keycode = new HashMap();//字符串对应的键值 25 | static Map ShieldKeyCodeMap = new HashMap(); 26 | //java键盘键值 27 | static Integer[] javaKeyCode = { 28 | // 字母26 29 | KeyEvent.VK_A, 30 | KeyEvent.VK_B, 31 | KeyEvent.VK_C, 32 | KeyEvent.VK_D, 33 | KeyEvent.VK_E, 34 | KeyEvent.VK_F, 35 | KeyEvent.VK_G, 36 | KeyEvent.VK_H, 37 | KeyEvent.VK_I, 38 | KeyEvent.VK_J, 39 | KeyEvent.VK_K, 40 | KeyEvent.VK_L, 41 | KeyEvent.VK_M, 42 | KeyEvent.VK_N, 43 | KeyEvent.VK_O, 44 | KeyEvent.VK_P, 45 | KeyEvent.VK_Q, 46 | KeyEvent.VK_R, 47 | KeyEvent.VK_S, 48 | KeyEvent.VK_T, 49 | KeyEvent.VK_U, 50 | KeyEvent.VK_V, 51 | KeyEvent.VK_W, 52 | KeyEvent.VK_X, 53 | KeyEvent.VK_Y, 54 | KeyEvent.VK_Z, 55 | // 数字21 56 | KeyEvent.VK_0, 57 | KeyEvent.VK_1, 58 | KeyEvent.VK_2, 59 | KeyEvent.VK_3, 60 | KeyEvent.VK_4, 61 | KeyEvent.VK_5, 62 | KeyEvent.VK_6, 63 | KeyEvent.VK_7, 64 | KeyEvent.VK_8, 65 | KeyEvent.VK_9, 66 | KeyEvent.VK_NUMPAD0, 67 | KeyEvent.VK_NUMPAD1, 68 | KeyEvent.VK_NUMPAD2, 69 | KeyEvent.VK_NUMPAD3, 70 | KeyEvent.VK_NUMPAD4, 71 | KeyEvent.VK_NUMPAD5, 72 | KeyEvent.VK_NUMPAD6, 73 | KeyEvent.VK_NUMPAD7, 74 | KeyEvent.VK_NUMPAD8, 75 | KeyEvent.VK_NUMPAD9, 76 | KeyEvent.VK_NUM_LOCK, 77 | // 功能键F24 78 | KeyEvent.VK_F1, 79 | KeyEvent.VK_F2, 80 | KeyEvent.VK_F3, 81 | KeyEvent.VK_F4, 82 | KeyEvent.VK_F5, 83 | KeyEvent.VK_F6, 84 | KeyEvent.VK_F7, 85 | KeyEvent.VK_F8, 86 | KeyEvent.VK_F9, 87 | KeyEvent.VK_F10, 88 | KeyEvent.VK_F11, 89 | KeyEvent.VK_F12, 90 | KeyEvent.VK_F13, 91 | KeyEvent.VK_F14, 92 | KeyEvent.VK_F15, 93 | KeyEvent.VK_F16, 94 | KeyEvent.VK_F17, 95 | KeyEvent.VK_F18, 96 | KeyEvent.VK_F19, 97 | KeyEvent.VK_F20, 98 | KeyEvent.VK_F21, 99 | KeyEvent.VK_F22, 100 | KeyEvent.VK_F23, 101 | KeyEvent.VK_F24, 102 | // 方位键8 103 | KeyEvent.VK_LEFT, 104 | KeyEvent.VK_RIGHT, 105 | KeyEvent.VK_UP, 106 | KeyEvent.VK_DOWN, 107 | KeyEvent.VK_KP_LEFT, 108 | KeyEvent.VK_KP_RIGHT, 109 | KeyEvent.VK_KP_UP, 110 | KeyEvent.VK_KP_DOWN,// 数字键盘方向键 111 | // 常用键16 112 | KeyEvent.VK_PAGE_UP, 113 | KeyEvent.VK_PAGE_DOWN, 114 | KeyEvent.VK_HOME, 115 | KeyEvent.VK_END, 116 | KeyEvent.VK_TAB, 117 | KeyEvent.VK_CAPS_LOCK, 118 | KeyEvent.VK_SHIFT, 119 | KeyEvent.VK_ALT, 120 | KeyEvent.VK_CONTROL, 121 | KeyEvent.VK_SPACE, 122 | KeyEvent.VK_ENTER, 123 | KeyEvent.VK_WINDOWS, 124 | KeyEvent.VK_INSERT, 125 | KeyEvent.VK_DELETE, 126 | KeyEvent.VK_BACK_SPACE, 127 | KeyEvent.VK_ESCAPE, 128 | // 符号键19 129 | KeyEvent.VK_CLOSE_BRACKET, 130 | KeyEvent.VK_AT, 131 | KeyEvent.VK_BACK_SLASH, 132 | KeyEvent.VK_CIRCUMFLEX, 133 | KeyEvent.VK_COLON, 134 | KeyEvent.VK_COMMA, 135 | KeyEvent.VK_DOLLAR, 136 | KeyEvent.VK_EQUALS, 137 | KeyEvent.VK_EXCLAMATION_MARK, 138 | KeyEvent.VK_LEFT_PARENTHESIS, 139 | KeyEvent.VK_MINUS, 140 | KeyEvent.VK_NUMBER_SIGN, 141 | KeyEvent.VK_OPEN_BRACKET, 142 | KeyEvent.VK_PERIOD, 143 | KeyEvent.VK_PLUS, 144 | KeyEvent.VK_RIGHT_PARENTHESIS, 145 | KeyEvent.VK_SEMICOLON, 146 | KeyEvent.VK_SLASH, 147 | KeyEvent.VK_UNDERSCORE, 148 | 149 | // 其他字段值78 150 | KeyEvent.VK_ACCEPT, KeyEvent.VK_ADD, KeyEvent.VK_AGAIN, 151 | KeyEvent.VK_ALL_CANDIDATES, KeyEvent.VK_ALPHANUMERIC, 152 | KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_AMPERSAND, KeyEvent.VK_ASTERISK, 153 | KeyEvent.VK_BACK_QUOTE, KeyEvent.VK_BEGIN, KeyEvent.VK_BRACELEFT, 154 | KeyEvent.VK_BRACERIGHT, KeyEvent.VK_CANCEL, KeyEvent.VK_CIRCUMFLEX, 155 | KeyEvent.VK_CLEAR, KeyEvent.VK_CODE_INPUT, KeyEvent.VK_COMPOSE, 156 | KeyEvent.VK_CONTEXT_MENU, KeyEvent.VK_CONVERT, KeyEvent.VK_COPY, 157 | KeyEvent.VK_CUT, KeyEvent.VK_DEAD_ABOVEDOT, 158 | KeyEvent.VK_DEAD_ABOVERING, KeyEvent.VK_DEAD_ACUTE, 159 | KeyEvent.VK_DEAD_BREVE, KeyEvent.VK_DEAD_CARON, 160 | KeyEvent.VK_DEAD_CEDILLA, KeyEvent.VK_DEAD_CIRCUMFLEX, 161 | KeyEvent.VK_DEAD_DIAERESIS, KeyEvent.VK_DEAD_DOUBLEACUTE, 162 | KeyEvent.VK_DEAD_GRAVE, KeyEvent.VK_DEAD_IOTA, 163 | KeyEvent.VK_DEAD_MACRON, KeyEvent.VK_DEAD_OGONEK, 164 | KeyEvent.VK_DEAD_SEMIVOICED_SOUND, KeyEvent.VK_DEAD_TILDE, 165 | KeyEvent.VK_DEAD_VOICED_SOUND, KeyEvent.VK_DECIMAL, 166 | KeyEvent.VK_DIVIDE, KeyEvent.VK_EURO_SIGN, KeyEvent.VK_FINAL, 167 | KeyEvent.VK_FIND, KeyEvent.VK_FULL_WIDTH, KeyEvent.VK_GREATER, 168 | KeyEvent.VK_HALF_WIDTH, KeyEvent.VK_HELP, KeyEvent.VK_HIRAGANA, 169 | KeyEvent.VK_INPUT_METHOD_ON_OFF, 170 | KeyEvent.VK_INVERTED_EXCLAMATION_MARK, 171 | KeyEvent.VK_JAPANESE_HIRAGANA, KeyEvent.VK_JAPANESE_KATAKANA, 172 | KeyEvent.VK_JAPANESE_ROMAN, KeyEvent.VK_KANA, 173 | KeyEvent.VK_KANA_LOCK, KeyEvent.VK_KANJI, KeyEvent.VK_KATAKANA, 174 | KeyEvent.VK_LEFT_PARENTHESIS, KeyEvent.VK_LESS, KeyEvent.VK_META, 175 | KeyEvent.VK_MODECHANGE, KeyEvent.VK_MULTIPLY, 176 | KeyEvent.VK_NONCONVERT, KeyEvent.VK_PASTE, KeyEvent.VK_PAUSE, 177 | KeyEvent.VK_PREVIOUS_CANDIDATE, KeyEvent.VK_PRINTSCREEN, 178 | KeyEvent.VK_PROPS, KeyEvent.VK_QUOTE, KeyEvent.VK_QUOTEDBL, 179 | KeyEvent.VK_ROMAN_CHARACTERS, KeyEvent.VK_SCROLL_LOCK, 180 | KeyEvent.VK_SEPARATER, KeyEvent.VK_SEPARATOR, KeyEvent.VK_STOP, 181 | KeyEvent.VK_SUBTRACT, KeyEvent.VK_UNDEFINED, 182 | KeyEvent.VK_UNDERSCORE, KeyEvent.VK_UNDO 183 | }; 184 | //数组index为键值对应的键盘按键 185 | static String[] key = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", 186 | "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", 187 | "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", 188 | "8", 189 | "9", 190 | "NUMPAD0", 191 | "NUMPAD1", 192 | "NUMPAD2", 193 | "NUMPAD3", 194 | "NUMPAD4", 195 | "NUMPAD5", 196 | "NUMPAD6", 197 | "NUMPAD7", 198 | "NUMPAD8", 199 | "NUMPAD9", 200 | "NUM_LOCK", 201 | "F1", 202 | "F2", 203 | "F3", 204 | "F4", 205 | "F5", 206 | "F6", 207 | "F7", 208 | "F8", 209 | "F9", 210 | "F10", 211 | "F11", 212 | "F12", 213 | "F13", 214 | "F14", 215 | "F15", 216 | "F16", 217 | "F17", 218 | "F18", 219 | "F19", 220 | "F20", 221 | "F21", 222 | "F22", 223 | "F23", 224 | "F24", 225 | "LEFT", 226 | "RIGHT", 227 | "UP", 228 | "DOWN", 229 | "KP_LEFT", 230 | "KP_RIGHT", 231 | "KP_UP", 232 | "KP_DOWN", 233 | "PAGE_UP", 234 | "PAGE_DOWN", 235 | "PAGE_HOME", 236 | "PAGE_END", 237 | "TAB", 238 | "CAPS_LOCK", 239 | "SHIFT", 240 | "ALT", 241 | "CTRL", 242 | "SPACE", 243 | "ENTER", 244 | "WINDOWS", 245 | "INSERT", 246 | "DELETE", 247 | "BACK_SPACE", 248 | "ESCAPE", 249 | 250 | // 符号键 251 | "CLOSE_BRACKET", 252 | "AT", 253 | "BACK_SLASH", 254 | "CIRCUMFLEX", 255 | "COLON", 256 | "COMMA", 257 | "DOLLAR", 258 | "EQUALS", 259 | "EXCLAMATION_MARK", 260 | "LEFT_PARENTHESIS", 261 | "MINUS", 262 | "NUMBER_SIGN", 263 | "OPEN_BRACKET", 264 | "PERIOD", 265 | "PLUS", 266 | "RIGHT_PARENTHESIS", 267 | "SEMICOLON", 268 | "SLASH", 269 | "UNDERSCORE", 270 | 271 | // "]","@","\\","`",":",",","$","=","!","(","-","#","[",".", 272 | // "+",")",";","/","_" 273 | 274 | // 其他字段值78 275 | "ACCEPT", "ADD", "AGAIN", "ALL_CANDIDATES", "ALPHANUMERIC", 276 | "ALT_GRAPH", "AMPERSAND", "ASTERISK", "BACK_QUOTE", "BEGIN", 277 | "BRACELEFT", "BRACERIGHT", "CANCEL", "CIRCUMFLEX", "CLEAR", 278 | "CODE_INPUT", "COMPOSE", "CONTEXT_MENU", "CONVERT", "COPY", "CUT", 279 | "DEAD_ABOVEDOT", "DEAD_ABOVERING", "DEAD_ACUTE", "DEAD_BREVE", 280 | "DEAD_CARON", "DEAD_CEDILLA", "DEAD_CIRCUMFLEX", "DEAD_DIAERESIS", 281 | "DEAD_DOUBLEACUTE", "DEAD_GRAVE", "DEAD_IOTA", "DEAD_MACRON", 282 | "DEAD_OGONEK", "DEAD_SEMIVOICED_SOUND", "DEAD_TILDE", 283 | "DEAD_VOICED_SOUND", "DECIMAL", "DIVIDE", "EURO_SIGN", "FINAL", 284 | "FIND", "FULL_WIDTH", "GREATER", "HALF_WIDTH", "HELP", "HIRAGANA", 285 | "INPUT_METHOD_ON_OFF", "INVERTED_EXCLAMATION_MARK", 286 | "JAPANESE_HIRAGANA", "JAPANESE_KATAKANA", "JAPANESE_ROMAN", "KANA", 287 | "KANA_LOCK", "KANJI", "KATAKANA", "LEFT_PARENTHESIS", "LESS", 288 | "META", "MODECHANGE", "MULTIPLY", "NONCONVERT", "PASTE", "PAUSE", 289 | "PREVIOUS_CANDIDATE", "PRINTSCREEN", "PROPS", "QUOTE", "QUOTEDBL", 290 | "ROMAN_CHARACTERS", "SCROLL_LOCK", "SEPARATER", "SEPARATOR", 291 | "STOP", "SUBTRACT", "UNDEFINED", "UNDERSCORE", "UNDO" 292 | 293 | }; 294 | 295 | static Integer[] ShieldKeyCode = { 296 | // F功能键 297 | KeyEvent.VK_F1, KeyEvent.VK_F2, KeyEvent.VK_F3, KeyEvent.VK_F4, 298 | KeyEvent.VK_F5, KeyEvent.VK_F6, 299 | KeyEvent.VK_F7, 300 | KeyEvent.VK_F8, 301 | KeyEvent.VK_F9, 302 | KeyEvent.VK_F10, 303 | KeyEvent.VK_F11, 304 | KeyEvent.VK_F12, 305 | // 方位键 306 | KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_UP, 307 | KeyEvent.VK_DOWN, 308 | KeyEvent.VK_KP_LEFT, 309 | KeyEvent.VK_KP_RIGHT, 310 | KeyEvent.VK_KP_UP, 311 | KeyEvent.VK_KP_DOWN, 312 | // 常用键15 313 | KeyEvent.VK_PAGE_UP, KeyEvent.VK_PAGE_DOWN, KeyEvent.VK_HOME, 314 | KeyEvent.VK_END, KeyEvent.VK_TAB, KeyEvent.VK_CAPS_LOCK, 315 | KeyEvent.VK_SHIFT, KeyEvent.VK_ALT, KeyEvent.VK_CONTROL, 316 | KeyEvent.VK_SPACE, KeyEvent.VK_ENTER, KeyEvent.VK_INSERT, 317 | KeyEvent.VK_DELETE, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_ESCAPE, 318 | 319 | }; 320 | 321 | // 初始化哈希表 322 | static { 323 | for (int i = 0; i < javaKeyCode.length; i++) { 324 | keycode2str.put(javaKeyCode[i], key[i]); 325 | } 326 | for (int i = 0; i < key.length; i++) { 327 | str2keycode.put(key[i], javaKeyCode[i]); 328 | } 329 | // 屏蔽键 330 | for (int i = 0; i < ShieldKeyCode.length; i++) { 331 | ShieldKeyCodeMap.put(ShieldKeyCode[i], 332 | keycode2str.get(ShieldKeyCode[i])); 333 | } 334 | } 335 | 336 | // 判断是否为屏蔽键 337 | public static boolean isShieldKeyCode(Integer keyCode) { 338 | return ShieldKeyCodeMap.containsKey(keyCode); 339 | } 340 | 341 | // 获取keycode2str 342 | public static Map getkeycode2str() { 343 | return keycode2str; 344 | } 345 | 346 | // 获取str2keycode 347 | public static Map getstr2keycode() { 348 | return str2keycode; 349 | } 350 | 351 | // 得到哈希表keycode2str键值 352 | public static String getKey(Integer keyCode) { 353 | if (keyCode != null && (!keyCode.equals(""))) { 354 | return keycode2str.get(keyCode); 355 | } 356 | return null; 357 | } 358 | 359 | // 得到哈希表str2keycode键值 360 | public static Integer getJavaKeyCode(String keyStr) { 361 | if (! StringUtil.isBlank(keyStr)) { 362 | return str2keycode.get(keyStr.toUpperCase()); 363 | } 364 | return -1; 365 | } 366 | } -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/util/R.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 HUST. 3 | * Visit https://github.com/hustcc 4 | * All right reserved. 5 | */ 6 | package cc.hust.keyhelper.util; 7 | 8 | /** 9 | * @author Xewee.Zhiwei.Wang 10 | * @version 2013-2-18 下午1:01:43 11 | * @Contract wzwahl36@QQ.com or https://github.com/hustcc 12 | */ 13 | public class R { 14 | public static final String EMAIL_PIC_PATH = "res/wzwahl36atqqcom.gif"; 15 | public static final String POWER_ON_PIC_PATH = "res/power_on.png"; 16 | public static final String POWER_OFF_PIC_PATH = "res/power_off.png"; 17 | public static final String HELP_PIC_PATH = "res/help.png"; 18 | public static final String LOGO_PIC_PATH = "res/logo.png"; 19 | } 20 | -------------------------------------------------------------------------------- /src/cc/hust/keyhelper/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package cc.hust.keyhelper.util; 2 | 3 | public class StringUtil { 4 | public static boolean isBlank(String str) { 5 | return str == null || str.trim().equals(""); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/HotkeyListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * JIntellitype 3 | * ----------------- 4 | * Copyright 2005-2008 Emil A. Lefkof III, Melloware Inc. 5 | * 6 | * I always give it my best shot to make a program useful and solid, but 7 | * remeber that there is absolutely no warranty for using this program as 8 | * stated in the following terms: 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | package com.melloware.jintellitype; 23 | 24 | 25 | /** 26 | * Listener interface for Windows Hotkey events registered using the 27 | * Windows API call RegisterHotKey to globally listen for a key combination 28 | * regardless if your application has focus or not. 29 | *

30 | * Copyright (c) 1999-2008 31 | * Melloware, Inc. 32 | * @author Emil A. Lefkof III 33 | * @version 1.3.1 34 | * 35 | * @see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputfunctions/registerhotkey.asp 36 | */ 37 | public interface HotkeyListener 38 | { 39 | /** 40 | * Event fired when a WM_HOTKEY message is received that was initiated 41 | * by this application. 42 | *

43 | * @param identifier the unique Identifer the Hotkey was assigned 44 | */ 45 | void onHotKey( int identifier ); 46 | } -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/IntellitypeListener.java: -------------------------------------------------------------------------------- 1 | /** 2 | * JIntellitype 3 | * ----------------- 4 | * Copyright 2005-2008 Emil A. Lefkof III, Melloware Inc. 5 | * 6 | * I always give it my best shot to make a program useful and solid, but 7 | * remeber that there is absolutely no warranty for using this program as 8 | * stated in the following terms: 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | package com.melloware.jintellitype; 23 | 24 | 25 | /** 26 | * Listener interface for Windows Intellitype events. Intellitype are Windows 27 | * App Commands that are specialand were introduced with Microsoft Keyboards 28 | * that had special keys for Play, Pause, Stop, Next etc for controlling 29 | * Media applications like Windows Media Player, Itunes, and Winamp. 30 | *

31 | * If you have ever wanted your Swing/SWT application to respond to these global 32 | * events you now can with JIntellitype. Just implement this interface and 33 | * you can now take action when those special Media keys are pressed. 34 | *

35 | * Copyright (c) 1999-2008 36 | * Melloware, Inc. 37 | * @author Emil A. Lefkof III 38 | * @version 1.3.1 39 | * 40 | * @see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputmessages/wm_appcommand.asp 41 | */ 42 | public interface IntellitypeListener 43 | { 44 | /** 45 | * Event fired when a WM_APPCOMMAND message is received that was initiated 46 | * by this application. 47 | *

48 | * @param command the WM_APPCOMMAND that was pressed 49 | */ 50 | void onIntellitype( int command ); 51 | } -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/JIntellitype.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/src/com/melloware/jintellitype/JIntellitype.dll -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/JIntellitype.java: -------------------------------------------------------------------------------- 1 | /** 2 | * JIntellitype ----------------- Copyright 2005-2008 Emil A. Lefkof III, 3 | * Melloware Inc. I always give it my best shot to make a program useful and 4 | * solid, but remeber that there is absolutely no warranty for using this 5 | * program as stated in the following terms: Licensed under the Apache License, 6 | * Version 2.0 (the "License"); you may not use this file except in compliance 7 | * with the License. You may obtain a copy of the License at 8 | * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law 9 | * or agreed to in writing, software distributed under the License is 10 | * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 | * KIND, either express or implied. See the License for the specific language 12 | * governing permissions and limitations under the License. 13 | */ 14 | package com.melloware.jintellitype; 15 | 16 | import java.awt.event.InputEvent; 17 | import java.awt.event.KeyEvent; 18 | import java.io.File; 19 | import java.io.FileOutputStream; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.io.OutputStream; 23 | import java.util.Collections; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.concurrent.CopyOnWriteArrayList; 27 | 28 | import javax.swing.SwingUtilities; 29 | 30 | /** 31 | * JIntellitype A Java Implementation for using the Windows API Intellitype 32 | * commands and the RegisterHotKey and UnRegisterHotkey API calls for globally 33 | * responding to key events. Intellitype are commands that are using for Play, 34 | * Stop, Next on Media keyboards or some laptops that have those special keys. 35 | *

36 | * JIntellitype class that is used to call Windows API calls using the 37 | * JIntellitype.dll. 38 | *

39 | * This file comes with native code in JINTELLITYPE.DLL The DLL should go in 40 | * C:/WINDOWS/SYSTEM or in your current directory 41 | *

42 | *

43 | * Copyright (c) 1999-2008 Melloware, Inc. 44 | * @author Emil A. Lefkof III 45 | * @version 1.3.1 46 | */ 47 | public final class JIntellitype implements JIntellitypeConstants { 48 | 49 | /** 50 | * Static variable to hold singleton. 51 | */ 52 | private static JIntellitype jintellitype = null; 53 | 54 | /** 55 | * Static variable for double checked thread safety. 56 | */ 57 | private static boolean isInitialized = false; 58 | 59 | /** 60 | * Static variable to hold the libary location if set 61 | */ 62 | private static String libraryLocation = null; 63 | 64 | /** 65 | * Listeners collection for Hotkey events 66 | */ 67 | private final List hotkeyListeners = Collections 68 | .synchronizedList(new CopyOnWriteArrayList()); 69 | 70 | /** 71 | * Listeners collection for Hotkey events 72 | */ 73 | private final List intellitypeListeners = Collections 74 | .synchronizedList(new CopyOnWriteArrayList()); 75 | 76 | /** 77 | * Handler is used by JNI code to keep different JVM instances separate 78 | */ 79 | private final int handler = 0; 80 | 81 | /** 82 | * Map containing key->keycode mapping 83 | * @see #registerHotKey(int, String) 84 | * @see #getKey2KeycodeMapping() 85 | */ 86 | private final HashMap keycodeMap; 87 | 88 | /** 89 | * Private Constructor to prevent instantiation. Initialize the library for 90 | * calling. 91 | */ 92 | private JIntellitype() { 93 | try { 94 | // Load JNI library 95 | System.loadLibrary("JIntellitype"); 96 | } catch (Throwable ex) { 97 | try { 98 | if (getLibraryLocation() != null) { 99 | System.load(getLibraryLocation()); 100 | } else { 101 | String jarPath = "com/melloware/jintellitype/"; 102 | String tmpDir = System.getProperty("java.io.tmpdir"); 103 | try { 104 | String dll = "JIntellitype.dll"; 105 | fromJarToFs(jarPath + dll, tmpDir + dll); 106 | System.load(tmpDir + dll); 107 | } catch (UnsatisfiedLinkError e) { 108 | String dll = "JIntellitype64.dll"; 109 | fromJarToFs(jarPath + dll, tmpDir + dll); 110 | System.load(tmpDir + dll); 111 | } 112 | } 113 | } catch (Throwable ex2) { 114 | throw new JIntellitypeException( 115 | "Could not load JIntellitype.dll from local file system or from inside JAR", ex2); 116 | } 117 | } 118 | 119 | initializeLibrary(); 120 | this.keycodeMap = getKey2KeycodeMapping(); 121 | } 122 | 123 | /** 124 | * Pulls a file out of the JAR and puts it on the File Path. 125 | *

126 | * @param jarPath the path to the JAR 127 | * @param filePath the file path to extract to 128 | * @throws IOException if any IO error occurs 129 | */ 130 | private void fromJarToFs(String jarPath, String filePath) throws IOException { 131 | File file = new File(filePath); 132 | if (file.exists()) { 133 | boolean success = file.delete(); 134 | if (!success) { 135 | throw new IOException("couldn't delete " + filePath); 136 | } 137 | } 138 | InputStream is = null; 139 | OutputStream os = null; 140 | try { 141 | is = ClassLoader.getSystemClassLoader().getResourceAsStream(jarPath); 142 | os = new FileOutputStream(filePath); 143 | byte[] buffer = new byte[8192]; 144 | int bytesRead; 145 | while ((bytesRead = is.read(buffer)) != -1) { 146 | os.write(buffer, 0, bytesRead); 147 | } 148 | } finally { 149 | if (is != null) { 150 | is.close(); 151 | } 152 | if (os != null) { 153 | os.close(); 154 | } 155 | } 156 | } 157 | 158 | /** 159 | * Gets the singleton instance of the JIntellitype object. 160 | *

161 | * But the possibility of creation of more instance is only before the 162 | * instance is created. Since all code defined inside getInstance method is 163 | * in the synchronized block, even the subsequent requests will also come and 164 | * wait in the synchronized block. This is a performance issue. The same can 165 | * be solved using double-checked lock. Following is the implementation of 166 | * Singleton with lazy initialization and double-checked lock. 167 | *

168 | * @return an instance of JIntellitype class 169 | */ 170 | public static JIntellitype getInstance() { 171 | if (!isInitialized) { 172 | synchronized (JIntellitype.class) { 173 | if (!isInitialized) { 174 | jintellitype = new JIntellitype(); 175 | isInitialized = true; 176 | } 177 | } 178 | } 179 | return jintellitype; 180 | } 181 | 182 | /** 183 | * Adds a listener for hotkeys. 184 | *

185 | * @param listener the HotKeyListener to be added 186 | */ 187 | public void addHotKeyListener(HotkeyListener listener) { 188 | hotkeyListeners.add(listener); 189 | } 190 | 191 | /** 192 | * Adds a listener for intellitype commands. 193 | *

194 | * @param listener the IntellitypeListener to be added 195 | */ 196 | public void addIntellitypeListener(IntellitypeListener listener) { 197 | intellitypeListeners.add(listener); 198 | } 199 | 200 | /** 201 | * Cleans up all resources used by JIntellitype. 202 | */ 203 | public void cleanUp() { 204 | try { 205 | terminate(); 206 | } catch (UnsatisfiedLinkError ex) { 207 | throw new JIntellitypeException(ERROR_MESSAGE, ex); 208 | } catch (RuntimeException ex) { 209 | throw new JIntellitypeException(ex); 210 | } 211 | } 212 | 213 | /** 214 | * Registers a Hotkey with windows. This combination will be responded to by 215 | * all registered HotKeyListeners. Uses the JIntellitypeConstants for MOD, 216 | * ALT, CTRL, and WINDOWS keys. 217 | *

218 | * @param identifier a unique identifier for this key combination 219 | * @param modifier MOD_SHIFT, MOD_ALT, MOD_CONTROL, MOD_WIN from 220 | * JIntellitypeConstants, or 0 if no modifier needed 221 | * @param keycode the key to respond to in Ascii integer, 65 for A 222 | */ 223 | public void registerHotKey(int identifier, int modifier, int keycode) { 224 | try { 225 | int modifiers = swingToIntelliType(modifier); 226 | if (modifiers == 0) { 227 | modifiers = modifier; 228 | } 229 | regHotKey(identifier, modifier, keycode); 230 | } catch (UnsatisfiedLinkError ex) { 231 | throw new JIntellitypeException(ERROR_MESSAGE, ex); 232 | } catch (RuntimeException ex) { 233 | throw new JIntellitypeException(ex); 234 | } 235 | } 236 | 237 | /** 238 | * Registers a Hotkey with windows. This combination will be responded to by 239 | * all registered HotKeyListeners. Use the Swing InputEvent constants from 240 | * java.awt.InputEvent. 241 | *

242 | * @param identifier a unique identifier for this key combination 243 | * @param modifier InputEvent.SHIFT_MASK, InputEvent.ALT_MASK, 244 | * InputEvent.CTRL_MASK, or 0 if no modifier needed 245 | * @param keycode the key to respond to in Ascii integer, 65 for A 246 | */ 247 | public void registerSwingHotKey(int identifier, int modifier, int keycode) { 248 | try { 249 | regHotKey(identifier, swingToIntelliType(modifier), keycode); 250 | } catch (UnsatisfiedLinkError ex) { 251 | throw new JIntellitypeException(ERROR_MESSAGE, ex); 252 | } catch (RuntimeException ex) { 253 | throw new JIntellitypeException(ex); 254 | } 255 | } 256 | 257 | /** 258 | * Registers a Hotkey with windows. This combination will be responded to by 259 | * all registered HotKeyListeners. Use the identifiers CTRL, SHIFT, ALT 260 | * and/or WIN. 261 | *

262 | * @param identifier a unique identifier for this key combination 263 | * @param modifierAndKeyCode String with modifiers separated by + and keycode 264 | * (e.g. CTRL+SHIFT+A) 265 | * @see #registerHotKey(int, int, int) 266 | * @see #registerSwingHotKey(int, int, int) 267 | */ 268 | public void registerHotKey(int identifier, String modifierAndKeyCode) { 269 | String[] split = modifierAndKeyCode.split("\\+"); 270 | int mask = 0; 271 | int keycode = 0; 272 | 273 | for (int i = 0; i < split.length; i++) { 274 | if ("ALT".equalsIgnoreCase(split[i])) { 275 | mask += JIntellitype.MOD_ALT; 276 | } else if ("CTRL".equalsIgnoreCase(split[i]) || "CONTROL".equalsIgnoreCase(split[i])) { 277 | mask += JIntellitype.MOD_CONTROL; 278 | } else if ("SHIFT".equalsIgnoreCase(split[i])) { 279 | mask += JIntellitype.MOD_SHIFT; 280 | } else if ("WIN".equalsIgnoreCase(split[i])) { 281 | mask += JIntellitype.MOD_WIN; 282 | } else if (keycodeMap.containsKey(split[i].toLowerCase())) { 283 | keycode = keycodeMap.get(split[i].toLowerCase()); 284 | } 285 | } 286 | registerHotKey(identifier, mask, keycode); 287 | } 288 | 289 | /** 290 | * Removes a listener for hotkeys. 291 | */ 292 | public void removeHotKeyListener(HotkeyListener listener) { 293 | hotkeyListeners.remove(listener); 294 | } 295 | 296 | /** 297 | * Removes a listener for intellitype commands. 298 | */ 299 | public void removeIntellitypeListener(IntellitypeListener listener) { 300 | intellitypeListeners.remove(listener); 301 | } 302 | 303 | /** 304 | * Unregisters a previously registered Hotkey identified by its unique 305 | * identifier. 306 | *

307 | * @param identifier the unique identifer of this Hotkey 308 | */ 309 | public void unregisterHotKey(int identifier) { 310 | try { 311 | unregHotKey(identifier); 312 | } catch (UnsatisfiedLinkError ex) { 313 | throw new JIntellitypeException(ERROR_MESSAGE, ex); 314 | } catch (RuntimeException ex) { 315 | throw new JIntellitypeException(ex); 316 | } 317 | } 318 | 319 | /** 320 | * Checks to see if this application is already running. 321 | *

322 | * @param appTitle the name of the application to check for 323 | * @return true if running, false if not running 324 | */ 325 | public static boolean checkInstanceAlreadyRunning(String appTitle) { 326 | return getInstance().isRunning(appTitle); 327 | } 328 | 329 | /** 330 | * Checks to make sure the OS is a Windows flavor and that the JIntellitype 331 | * DLL is found in the path and the JDK is 32 bit not 64 bit. The DLL 332 | * currently only supports 32 bit JDK. 333 | *

334 | * @return true if Jintellitype may be used, false if not 335 | */ 336 | public static boolean isJIntellitypeSupported() { 337 | boolean result = false; 338 | String os = "none"; 339 | 340 | try { 341 | os = System.getProperty("os.name").toLowerCase(); 342 | } catch (SecurityException ex) { 343 | // we are not allowed to look at this property 344 | System.err.println("Caught a SecurityException reading the system property " 345 | + "'os.name'; the SystemUtils property value will default to null."); 346 | } 347 | 348 | // only works on Windows OS currently 349 | if (os.startsWith("windows")) { 350 | // try an get the instance and if it succeeds then return true 351 | try { 352 | getInstance(); 353 | result = true; 354 | } catch (Exception e) { 355 | result = false; 356 | } 357 | } 358 | 359 | return result; 360 | } 361 | 362 | /** 363 | * Gets the libraryLocation. 364 | *

365 | * @return Returns the libraryLocation. 366 | */ 367 | public static String getLibraryLocation() { 368 | return libraryLocation; 369 | } 370 | 371 | /** 372 | * Sets the libraryLocation. 373 | *

374 | * @param libraryLocation The libraryLocation to set. 375 | */ 376 | public static void setLibraryLocation(String libraryLocation) { 377 | final File dll = new File(libraryLocation); 378 | if (!dll.isAbsolute()) { 379 | JIntellitype.libraryLocation = dll.getAbsolutePath(); 380 | } else { 381 | // absolute path, no further calculation needed 382 | JIntellitype.libraryLocation = libraryLocation; 383 | } 384 | } 385 | 386 | /** 387 | * Sets the libraryLocation of the DLL using a File object. 388 | *

389 | * @param libraryFile the java.io.File representing the DLL 390 | */ 391 | public static void setLibraryLocation(File libraryFile) { 392 | if (!libraryFile.isAbsolute()) { 393 | JIntellitype.libraryLocation = libraryFile.getAbsolutePath(); 394 | } 395 | } 396 | 397 | /** 398 | * Notifies all listeners that Hotkey was pressed. 399 | *

400 | * @param identifier the unique identifier received 401 | */ 402 | protected void onHotKey(final int identifier) { 403 | for (final HotkeyListener hotkeyListener : hotkeyListeners) { 404 | SwingUtilities.invokeLater(new Runnable() { 405 | public void run() { 406 | hotkeyListener.onHotKey(identifier); 407 | } 408 | }); 409 | } 410 | } 411 | 412 | /** 413 | * Notifies all listeners that Intellitype command was received. 414 | *

415 | * @param command the unique WM_APPCOMMAND received 416 | */ 417 | protected void onIntellitype(final int command) { 418 | for (final IntellitypeListener intellitypeListener : intellitypeListeners) { 419 | SwingUtilities.invokeLater(new Runnable() { 420 | public void run() { 421 | intellitypeListener.onIntellitype(command); 422 | } 423 | }); 424 | } 425 | } 426 | 427 | /** 428 | * Swing modifier value to Jintellipad conversion. If no conversion needed 429 | * just return the original value. This lets users pass either the original 430 | * JIntellitype constants or Swing InputEvent constants. 431 | *

432 | * @param swingKeystrokeModifier the Swing KeystrokeModifier to check 433 | * @return Jintellitype the JIntellitype modifier value 434 | */ 435 | protected static int swingToIntelliType(int swingKeystrokeModifier) { 436 | int mask = 0; 437 | if ((swingKeystrokeModifier & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK 438 | || (swingKeystrokeModifier & InputEvent.SHIFT_DOWN_MASK) == InputEvent.SHIFT_DOWN_MASK) { 439 | mask |= JIntellitypeConstants.MOD_SHIFT; 440 | } 441 | if ((swingKeystrokeModifier & InputEvent.ALT_MASK) == InputEvent.ALT_MASK 442 | || (swingKeystrokeModifier & InputEvent.ALT_DOWN_MASK) == InputEvent.ALT_DOWN_MASK) { 443 | mask |= JIntellitypeConstants.MOD_ALT; 444 | } 445 | if ((swingKeystrokeModifier & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK 446 | || (swingKeystrokeModifier & InputEvent.CTRL_DOWN_MASK) == InputEvent.CTRL_DOWN_MASK) { 447 | mask |= JIntellitypeConstants.MOD_CONTROL; 448 | } 449 | if ((swingKeystrokeModifier & InputEvent.META_MASK) == InputEvent.META_MASK 450 | || (swingKeystrokeModifier & InputEvent.META_DOWN_MASK) == InputEvent.META_DOWN_MASK) { 451 | mask |= JIntellitypeConstants.MOD_WIN; 452 | } 453 | 454 | return mask; 455 | } 456 | 457 | /** 458 | * Puts all constants from {@link java.awt.event.KeyEvent} in a keycodeMap. 459 | * The key is the lower case form of it. 460 | * @return Map containing key->keycode mapping DOCU Now enables the user to 461 | * use all keys specified here instead of just [A-Z],[0-9] as before 462 | */ 463 | private HashMap getKey2KeycodeMapping() { 464 | HashMap map = new HashMap(); 465 | 466 | map.put("first", KeyEvent.KEY_FIRST); 467 | map.put("last", KeyEvent.KEY_LAST); 468 | map.put("typed", KeyEvent.KEY_TYPED); 469 | map.put("pressed", KeyEvent.KEY_PRESSED); 470 | map.put("released", KeyEvent.KEY_RELEASED); 471 | map.put("enter", 13); 472 | map.put("back_space", KeyEvent.VK_BACK_SPACE); 473 | map.put("tab", KeyEvent.VK_TAB); 474 | map.put("cancel", KeyEvent.VK_CANCEL); 475 | map.put("clear", KeyEvent.VK_CLEAR); 476 | map.put("pause", KeyEvent.VK_PAUSE); 477 | map.put("caps_lock", KeyEvent.VK_CAPS_LOCK); 478 | map.put("escape", KeyEvent.VK_ESCAPE); 479 | map.put("space", KeyEvent.VK_SPACE); 480 | map.put("page_up", KeyEvent.VK_PAGE_UP); 481 | map.put("page_down", KeyEvent.VK_PAGE_DOWN); 482 | map.put("end", KeyEvent.VK_END); 483 | map.put("home", KeyEvent.VK_HOME); 484 | map.put("left", KeyEvent.VK_LEFT); 485 | map.put("up", KeyEvent.VK_UP); 486 | map.put("right", KeyEvent.VK_RIGHT); 487 | map.put("down", KeyEvent.VK_DOWN); 488 | map.put("comma", 188); 489 | map.put("minus", 109); 490 | map.put("period", 110); 491 | map.put("slash", 191); 492 | map.put("accent `", 192); 493 | map.put("0", KeyEvent.VK_0); 494 | map.put("1", KeyEvent.VK_1); 495 | map.put("2", KeyEvent.VK_2); 496 | map.put("3", KeyEvent.VK_3); 497 | map.put("4", KeyEvent.VK_4); 498 | map.put("5", KeyEvent.VK_5); 499 | map.put("6", KeyEvent.VK_6); 500 | map.put("7", KeyEvent.VK_7); 501 | map.put("8", KeyEvent.VK_8); 502 | map.put("9", KeyEvent.VK_9); 503 | map.put("semicolon", 186); 504 | map.put("equals", 187); 505 | map.put("a", KeyEvent.VK_A); 506 | map.put("b", KeyEvent.VK_B); 507 | map.put("c", KeyEvent.VK_C); 508 | map.put("d", KeyEvent.VK_D); 509 | map.put("e", KeyEvent.VK_E); 510 | map.put("f", KeyEvent.VK_F); 511 | map.put("g", KeyEvent.VK_G); 512 | map.put("h", KeyEvent.VK_H); 513 | map.put("i", KeyEvent.VK_I); 514 | map.put("j", KeyEvent.VK_J); 515 | map.put("k", KeyEvent.VK_K); 516 | map.put("l", KeyEvent.VK_L); 517 | map.put("m", KeyEvent.VK_M); 518 | map.put("n", KeyEvent.VK_N); 519 | map.put("o", KeyEvent.VK_O); 520 | map.put("p", KeyEvent.VK_P); 521 | map.put("q", KeyEvent.VK_Q); 522 | map.put("r", KeyEvent.VK_R); 523 | map.put("s", KeyEvent.VK_S); 524 | map.put("t", KeyEvent.VK_T); 525 | map.put("u", KeyEvent.VK_U); 526 | map.put("v", KeyEvent.VK_V); 527 | map.put("w", KeyEvent.VK_W); 528 | map.put("x", KeyEvent.VK_X); 529 | map.put("y", KeyEvent.VK_Y); 530 | map.put("z", KeyEvent.VK_Z); 531 | map.put("open_bracket", 219); 532 | map.put("back_slash", 220); 533 | map.put("close_bracket", 221); 534 | map.put("numpad0", KeyEvent.VK_NUMPAD0); 535 | map.put("numpad1", KeyEvent.VK_NUMPAD1); 536 | map.put("numpad2", KeyEvent.VK_NUMPAD2); 537 | map.put("numpad3", KeyEvent.VK_NUMPAD3); 538 | map.put("numpad4", KeyEvent.VK_NUMPAD4); 539 | map.put("numpad5", KeyEvent.VK_NUMPAD5); 540 | map.put("numpad6", KeyEvent.VK_NUMPAD6); 541 | map.put("numpad7", KeyEvent.VK_NUMPAD7); 542 | map.put("numpad8", KeyEvent.VK_NUMPAD8); 543 | map.put("numpad9", KeyEvent.VK_NUMPAD9); 544 | map.put("multiply", KeyEvent.VK_MULTIPLY); 545 | map.put("add", KeyEvent.VK_ADD); 546 | map.put("separator", KeyEvent.VK_SEPARATOR); 547 | map.put("subtract", KeyEvent.VK_SUBTRACT); 548 | map.put("decimal", KeyEvent.VK_DECIMAL); 549 | map.put("divide", KeyEvent.VK_DIVIDE); 550 | map.put("delete", 46); 551 | map.put("num_lock", KeyEvent.VK_NUM_LOCK); 552 | map.put("scroll_lock", KeyEvent.VK_SCROLL_LOCK); 553 | map.put("f1", KeyEvent.VK_F1); 554 | map.put("f2", KeyEvent.VK_F2); 555 | map.put("f3", KeyEvent.VK_F3); 556 | map.put("f4", KeyEvent.VK_F4); 557 | map.put("f5", KeyEvent.VK_F5); 558 | map.put("f6", KeyEvent.VK_F6); 559 | map.put("f7", KeyEvent.VK_F7); 560 | map.put("f8", KeyEvent.VK_F8); 561 | map.put("f9", KeyEvent.VK_F9); 562 | map.put("f10", KeyEvent.VK_F10); 563 | map.put("f11", KeyEvent.VK_F11); 564 | map.put("f12", KeyEvent.VK_F12); 565 | map.put("f13", KeyEvent.VK_F13); 566 | map.put("f14", KeyEvent.VK_F14); 567 | map.put("f15", KeyEvent.VK_F15); 568 | map.put("f16", KeyEvent.VK_F16); 569 | map.put("f17", KeyEvent.VK_F17); 570 | map.put("f18", KeyEvent.VK_F18); 571 | map.put("f19", KeyEvent.VK_F19); 572 | map.put("f20", KeyEvent.VK_F20); 573 | map.put("f21", KeyEvent.VK_F21); 574 | map.put("f22", KeyEvent.VK_F22); 575 | map.put("f23", KeyEvent.VK_F23); 576 | map.put("f24", KeyEvent.VK_F24); 577 | map.put("printscreen", 44); 578 | map.put("insert", 45); 579 | map.put("help", 47); 580 | map.put("meta", KeyEvent.VK_META); 581 | map.put("back_quote", KeyEvent.VK_BACK_QUOTE); 582 | map.put("quote", KeyEvent.VK_QUOTE); 583 | map.put("kp_up", KeyEvent.VK_KP_UP); 584 | map.put("kp_down", KeyEvent.VK_KP_DOWN); 585 | map.put("kp_left", KeyEvent.VK_KP_LEFT); 586 | map.put("kp_right", KeyEvent.VK_KP_RIGHT); 587 | map.put("dead_grave", KeyEvent.VK_DEAD_GRAVE); 588 | map.put("dead_acute", KeyEvent.VK_DEAD_ACUTE); 589 | map.put("dead_circumflex", KeyEvent.VK_DEAD_CIRCUMFLEX); 590 | map.put("dead_tilde", KeyEvent.VK_DEAD_TILDE); 591 | map.put("dead_macron", KeyEvent.VK_DEAD_MACRON); 592 | map.put("dead_breve", KeyEvent.VK_DEAD_BREVE); 593 | map.put("dead_abovedot", KeyEvent.VK_DEAD_ABOVEDOT); 594 | map.put("dead_diaeresis", KeyEvent.VK_DEAD_DIAERESIS); 595 | map.put("dead_abovering", KeyEvent.VK_DEAD_ABOVERING); 596 | map.put("dead_doubleacute", KeyEvent.VK_DEAD_DOUBLEACUTE); 597 | map.put("dead_caron", KeyEvent.VK_DEAD_CARON); 598 | map.put("dead_cedilla", KeyEvent.VK_DEAD_CEDILLA); 599 | map.put("dead_ogonek", KeyEvent.VK_DEAD_OGONEK); 600 | map.put("dead_iota", KeyEvent.VK_DEAD_IOTA); 601 | map.put("dead_voiced_sound", KeyEvent.VK_DEAD_VOICED_SOUND); 602 | map.put("dead_semivoiced_sound", KeyEvent.VK_DEAD_SEMIVOICED_SOUND); 603 | map.put("ampersand", KeyEvent.VK_AMPERSAND); 604 | map.put("asterisk", KeyEvent.VK_ASTERISK); 605 | map.put("quotedbl", KeyEvent.VK_QUOTEDBL); 606 | map.put("less", KeyEvent.VK_LESS); 607 | map.put("greater", KeyEvent.VK_GREATER); 608 | map.put("braceleft", KeyEvent.VK_BRACELEFT); 609 | map.put("braceright", KeyEvent.VK_BRACERIGHT); 610 | map.put("at", KeyEvent.VK_AT); 611 | map.put("colon", KeyEvent.VK_COLON); 612 | map.put("circumflex", KeyEvent.VK_CIRCUMFLEX); 613 | map.put("dollar", KeyEvent.VK_DOLLAR); 614 | map.put("euro_sign", KeyEvent.VK_EURO_SIGN); 615 | map.put("exclamation_mark", KeyEvent.VK_EXCLAMATION_MARK); 616 | map.put("inverted_exclamation_mark", KeyEvent.VK_INVERTED_EXCLAMATION_MARK); 617 | map.put("left_parenthesis", KeyEvent.VK_LEFT_PARENTHESIS); 618 | map.put("number_sign", KeyEvent.VK_NUMBER_SIGN); 619 | map.put("plus", KeyEvent.VK_PLUS); 620 | map.put("right_parenthesis", KeyEvent.VK_RIGHT_PARENTHESIS); 621 | map.put("underscore", KeyEvent.VK_UNDERSCORE); 622 | map.put("context_menu", KeyEvent.VK_CONTEXT_MENU); 623 | map.put("final", KeyEvent.VK_FINAL); 624 | map.put("convert", KeyEvent.VK_CONVERT); 625 | map.put("nonconvert", KeyEvent.VK_NONCONVERT); 626 | map.put("accept", KeyEvent.VK_ACCEPT); 627 | map.put("modechange", KeyEvent.VK_MODECHANGE); 628 | map.put("kana", KeyEvent.VK_KANA); 629 | map.put("kanji", KeyEvent.VK_KANJI); 630 | map.put("alphanumeric", KeyEvent.VK_ALPHANUMERIC); 631 | map.put("katakana", KeyEvent.VK_KATAKANA); 632 | map.put("hiragana", KeyEvent.VK_HIRAGANA); 633 | map.put("full_width", KeyEvent.VK_FULL_WIDTH); 634 | map.put("half_width", KeyEvent.VK_HALF_WIDTH); 635 | map.put("roman_characters", KeyEvent.VK_ROMAN_CHARACTERS); 636 | map.put("all_candidates", KeyEvent.VK_ALL_CANDIDATES); 637 | map.put("previous_candidate", KeyEvent.VK_PREVIOUS_CANDIDATE); 638 | map.put("code_input", KeyEvent.VK_CODE_INPUT); 639 | map.put("japanese_katakana", KeyEvent.VK_JAPANESE_KATAKANA); 640 | map.put("japanese_hiragana", KeyEvent.VK_JAPANESE_HIRAGANA); 641 | map.put("japanese_roman", KeyEvent.VK_JAPANESE_ROMAN); 642 | map.put("kana_lock", KeyEvent.VK_KANA_LOCK); 643 | map.put("input_method_on_off", KeyEvent.VK_INPUT_METHOD_ON_OFF); 644 | map.put("cut", KeyEvent.VK_CUT); 645 | map.put("copy", KeyEvent.VK_COPY); 646 | map.put("paste", KeyEvent.VK_PASTE); 647 | map.put("undo", KeyEvent.VK_UNDO); 648 | map.put("again", KeyEvent.VK_AGAIN); 649 | map.put("find", KeyEvent.VK_FIND); 650 | map.put("props", KeyEvent.VK_PROPS); 651 | map.put("stop", KeyEvent.VK_STOP); 652 | map.put("compose", KeyEvent.VK_COMPOSE); 653 | map.put("alt_graph", KeyEvent.VK_ALT_GRAPH); 654 | map.put("begin", KeyEvent.VK_BEGIN); 655 | 656 | return map; 657 | } 658 | 659 | private synchronized native void initializeLibrary() throws UnsatisfiedLinkError; 660 | 661 | private synchronized native void regHotKey(int identifier, int modifier, int keycode) throws UnsatisfiedLinkError; 662 | 663 | private synchronized native void terminate() throws UnsatisfiedLinkError; 664 | 665 | private synchronized native void unregHotKey(int identifier) throws UnsatisfiedLinkError; 666 | 667 | /** 668 | * Checks if there's an instance with hidden window title = appName running 669 | * Can be used to detect that another instance of your app is already running 670 | * (so exit..) 671 | *

672 | * @param appName = the title of the hidden window to search for 673 | */ 674 | private synchronized native boolean isRunning(String appName); 675 | } -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/JIntellitype64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hustcc/KeyHelper/6b413254301e977aed84ad3c4913d10b2826a3d0/src/com/melloware/jintellitype/JIntellitype64.dll -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/JIntellitypeConstants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * JIntellitype 3 | * ----------------- 4 | * Copyright 2005-2008 Emil A. Lefkof III, Melloware Inc. 5 | * 6 | * I always give it my best shot to make a program useful and solid, but 7 | * remeber that there is absolutely no warranty for using this program as 8 | * stated in the following terms: 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | package com.melloware.jintellitype; 23 | 24 | /** 25 | * Constants from the Windows API used in JIntellitype. 26 | *

27 | * Message information can be found on MSDN here: 28 | * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardinput/keyboardinputreference/keyboardinputmessages/wm_appcommand.asp 29 | *

30 | * Copyright (c) 1999-2008 31 | * Melloware, Inc. 32 | * @author Emil A. Lefkof III 33 | * @version 1.3.1 34 | */ 35 | public interface JIntellitypeConstants { 36 | 37 | public static final String ERROR_MESSAGE = "JIntellitype DLL Error"; 38 | 39 | // Modifier keys, can be added together 40 | 41 | /** 42 | * ALT key for registering Hotkeys. 43 | */ 44 | public static final int MOD_ALT = 1; 45 | 46 | /** 47 | * CONTROL key for registering Hotkeys. 48 | */ 49 | public static final int MOD_CONTROL = 2; 50 | 51 | /** 52 | * SHIFT key for registering Hotkeys. 53 | */ 54 | public static final int MOD_SHIFT = 4; 55 | 56 | /** 57 | * WINDOWS key for registering Hotkeys. 58 | */ 59 | public static final int MOD_WIN = 8; 60 | 61 | 62 | // Intellitype Virtual Key Constants from MSDN 63 | 64 | /** 65 | * Browser Navigate backward 66 | */ 67 | public static final int APPCOMMAND_BROWSER_BACKWARD = 1; 68 | 69 | /** 70 | * Browser Navigate forward 71 | */ 72 | public static final int APPCOMMAND_BROWSER_FORWARD = 2; 73 | 74 | /** 75 | * Browser Refresh page 76 | */ 77 | public static final int APPCOMMAND_BROWSER_REFRESH = 3; 78 | 79 | /** 80 | * Browser Stop download 81 | */ 82 | public static final int APPCOMMAND_BROWSER_STOP = 4; 83 | 84 | /** 85 | * Browser Open search 86 | */ 87 | public static final int APPCOMMAND_BROWSER_SEARCH = 5; 88 | 89 | /** 90 | * Browser Open favorites 91 | */ 92 | public static final int APPCOMMAND_BROWSER_FAVOURITES = 6; 93 | 94 | /** 95 | * Browser Navigate home 96 | */ 97 | public static final int APPCOMMAND_BROWSER_HOME = 7; 98 | 99 | /** 100 | * Mute the volume 101 | */ 102 | public static final int APPCOMMAND_VOLUME_MUTE = 8; 103 | 104 | /** 105 | * Lower the volume 106 | */ 107 | public static final int APPCOMMAND_VOLUME_DOWN = 9; 108 | 109 | /** 110 | * Raise the volume 111 | */ 112 | public static final int APPCOMMAND_VOLUME_UP = 10; 113 | 114 | /** 115 | * Media application go to next track. 116 | */ 117 | public static final int APPCOMMAND_MEDIA_NEXTTRACK = 11; 118 | 119 | /** 120 | * Media application Go to previous track. 121 | */ 122 | public static final int APPCOMMAND_MEDIA_PREVIOUSTRACK = 12; 123 | 124 | /** 125 | * Media application Stop playback. 126 | */ 127 | public static final int APPCOMMAND_MEDIA_STOP = 13; 128 | 129 | /** 130 | * Media application Play or pause playback. 131 | */ 132 | public static final int APPCOMMAND_MEDIA_PLAY_PAUSE = 14; 133 | 134 | /** 135 | * Open mail application 136 | */ 137 | public static final int APPCOMMAND_LAUNCH_MAIL = 15; 138 | 139 | /** 140 | * Go to Media Select mode. 141 | */ 142 | public static final int APPCOMMAND_LAUNCH_MEDIA_SELECT = 16; 143 | 144 | /** 145 | * Start App1. 146 | */ 147 | public static final int APPCOMMAND_LAUNCH_APP1 = 17; 148 | 149 | /** 150 | * Start App2. 151 | */ 152 | public static final int APPCOMMAND_LAUNCH_APP2 = 18; 153 | 154 | public static final int APPCOMMAND_BASS_DOWN = 19; 155 | public static final int APPCOMMAND_BASS_BOOST = 20; 156 | public static final int APPCOMMAND_BASS_UP = 21; 157 | public static final int APPCOMMAND_TREBLE_DOWN = 22; 158 | public static final int APPCOMMAND_TREBLE_UP = 23; 159 | public static final int APPCOMMAND_MICROPHONE_VOLUME_MUTE = 24; 160 | public static final int APPCOMMAND_MICROPHONE_VOLUME_DOWN = 25; 161 | public static final int APPCOMMAND_MICROPHONE_VOLUME_UP = 26; 162 | public static final int APPCOMMAND_HELP = 27; 163 | public static final int APPCOMMAND_FIND = 28; 164 | public static final int APPCOMMAND_NEW = 29; 165 | public static final int APPCOMMAND_OPEN = 30; 166 | public static final int APPCOMMAND_CLOSE = 31; 167 | public static final int APPCOMMAND_SAVE = 32; 168 | public static final int APPCOMMAND_PRINT = 33; 169 | public static final int APPCOMMAND_UNDO = 34; 170 | public static final int APPCOMMAND_REDO = 35; 171 | public static final int APPCOMMAND_COPY = 36; 172 | public static final int APPCOMMAND_CUT = 37; 173 | public static final int APPCOMMAND_PASTE = 38; 174 | public static final int APPCOMMAND_REPLY_TO_MAIL = 39; 175 | public static final int APPCOMMAND_FORWARD_MAIL = 40; 176 | public static final int APPCOMMAND_SEND_MAIL = 41; 177 | public static final int APPCOMMAND_SPELL_CHECK = 42; 178 | public static final int APPCOMMAND_DICTATE_OR_COMMAND_CONTROL_TOGGLE = 43; 179 | public static final int APPCOMMAND_MIC_ON_OFF_TOGGLE = 44; 180 | public static final int APPCOMMAND_CORRECTION_LIST = 45; 181 | 182 | } 183 | -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/JIntellitypeException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * JIntellitype 3 | * ----------------- 4 | * Copyright 2005-2008 Emil A. Lefkof III, Melloware Inc. 5 | * 6 | * I always give it my best shot to make a program useful and solid, but 7 | * remeber that there is absolutely no warranty for using this program as 8 | * stated in the following terms: 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | package com.melloware.jintellitype; 23 | 24 | 25 | /** 26 | * Exception class for all JIntellitype Exceptions. 27 | *

28 | * Copyright (c) 1999-2008 29 | * Melloware, Inc. 30 | * @author Emil A. Lefkof III 31 | * @version 1.3.1 32 | */ 33 | public class JIntellitypeException extends RuntimeException { 34 | /** 35 | * 36 | */ 37 | private static final long serialVersionUID = 1L; 38 | 39 | 40 | public JIntellitypeException() { 41 | super(); 42 | } 43 | 44 | 45 | public JIntellitypeException(String aMessage, Throwable aCause) { 46 | super(aMessage, aCause); 47 | } 48 | 49 | 50 | public JIntellitypeException(String aMessage) { 51 | super(aMessage); 52 | } 53 | 54 | 55 | public JIntellitypeException(Throwable aCause) { 56 | super(aCause); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/com/melloware/jintellitype/Main.java: -------------------------------------------------------------------------------- 1 | /** 2 | * JIntellitype 3 | * ----------------- 4 | * Copyright 2005-2008 Emil A. Lefkof III, Melloware Inc. 5 | * 6 | * I always give it my best shot to make a program useful and solid, but 7 | * remeber that there is absolutely no warranty for using this program as 8 | * stated in the following terms: 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | package com.melloware.jintellitype; 23 | 24 | import java.util.Properties; 25 | 26 | /** 27 | * Simple executable class that is used as the Main-Class in the JIntellitype 28 | * jar. Outputs version information and other information about the environment 29 | * on which the jar is being executed. 30 | *

31 | * Copyright (c) 1999-2008 32 | * Melloware, Inc. 33 | * @author Emil A. Lefkof III 34 | * @version 1.3.1 35 | */ 36 | public final class Main { 37 | 38 | /** 39 | * Private constructor to make sure this class is never instantiated. 40 | * 41 | */ 42 | private Main() { 43 | // private constructor to make singleton. 44 | } 45 | 46 | /** Main method that does what the class level javadoc states. */ 47 | public static void main(String[] argv) { 48 | System.out.println("JIntellitype version \"" + getProjectVersion() + "\""); 49 | System.out.println(" "); 50 | 51 | System.out.println("Running on java version \"" + System.getProperty("java.version") + "\"" 52 | + " (build " + System.getProperty("java.runtime.version") + ")" 53 | + " from " + System.getProperty("java.vendor")); 54 | 55 | System.out.println("Operating environment \"" + System.getProperty("os.name") + "\"" 56 | + " version " + System.getProperty("os.version") + " on " + System.getProperty("os.arch")); 57 | 58 | System.out.println("For more information on JIntellitype please visit http://www.melloware.com"); 59 | } 60 | 61 | /** 62 | * Attempts to read the version number out of the pom.properties. If not found 63 | * then RUNNING.IN.IDE.FULL is returned as the version. 64 | *

65 | * @return the full version number of this application 66 | */ 67 | private static String getProjectVersion() { 68 | String version; 69 | 70 | try { 71 | final Properties pomProperties = new Properties(); 72 | pomProperties.load(Main.class.getResourceAsStream("/META-INF/maven/com.melloware/jintellitype/pom.properties")); 73 | version = pomProperties.getProperty("version"); 74 | } catch (Exception e) { 75 | version = "RUNNING.IN.IDE.FULL"; 76 | } 77 | return version; 78 | } 79 | } --------------------------------------------------------------------------------