所谓系统级热键就是指一组快捷键,不论当前系统焦点在哪个程序中,只要按下该键,程序就能够捕捉该事件并进行相关处理。该功能在应用程序中是非常有用的,比如系统自带的
“win+L”自动锁屏,QQ中默认的“ctrl+alt+Z”自动打开当前的消息窗口等等。
Java中的事件监听机制虽然功能强大,但是当系统焦点脱离该程序时也无能为力。要实现该功能必须调用系统的钩子函数,因此在java中也必须通过jni调用来实现,但是对于不熟悉系统函数或者其他编成语言的朋友来说却是个难题。
以前实现类似的功能都是自己通过c调用系统的钩子函数然后再通过jni调用,自己写的东西只要能满足简单的需求即可,因此功能和程序结构也比较简单。后来在国外的一个网站上发现了一个组件“jintellitype”帮我们封装了绝大部分的功能,而且结构上也采用java中的事件监听机制,我们只要在程序中通过注册即可实现,下面是一个简单的例子:
- import com.melloware.jintellitype.HotkeyListener;
- import com.melloware.jintellitype.JIntellitype;
-
- public class HotKey implements HotkeyListener {
- static final int KEY_1 = 88;
- static final int KEY_2 = 89;
- static final int KEY_3 = 90;
-
-
-
-
-
-
- public void onHotKey(int key) {
- switch (key) {
- case KEY_1:
- System.out.println("ctrl+alt+I 按下.........");
- break;
- case KEY_2:
- System.out.println("ctrl+alt+O 按下.........");
- break;
- case KEY_3:
- System.out.println("系统退出..........");
- destroy();
- }
-
- }
-
-
-
-
-
- void destroy() {
- JIntellitype.getInstance().unregisterHotKey(KEY_1);
- JIntellitype.getInstance().unregisterHotKey(KEY_2);
- JIntellitype.getInstance().unregisterHotKey(KEY_3);
- System.exit(0);
- }
-
-
-
-
- void initHotkey() {
-
- JIntellitype.getInstance().registerHotKey(KEY_1, JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT,
- (int) 'I');
- JIntellitype.getInstance().registerHotKey(KEY_2, JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT,
- (int) 'O');
- JIntellitype.getInstance().registerHotKey(KEY_3, JIntellitype.MOD_CONTROL + JIntellitype.MOD_ALT,
- (int) 'X');
-
- JIntellitype.getInstance().addHotKeyListener(this);
- }
-
- public static void main(String[] args) {
- HotKey key = new HotKey();
- key.initHotkey();
-
-
- while (true) {
- try {
- Thread.sleep(10000);
- } catch (Exception ex) {
- break;
- }
- }
- }
- }
注意:
1. 注册热键时必须是大写的。像 (int) 'I'
2.
因为用到了JIntellitype,所以遇到如何加载dll的问题。
首先,我的目标是程序只有一个exe文件。研究了一翻exe4j,没发现把dll打进exe里的方法。
退而求次,准备把dll打包到jar中,但当dll打包进jar后,系统无法加载。
解决思路:
1. 获取jar中dll文件内容:class.getResource()
2. 把内容拷贝出来
3. 加载拷贝出来的dll文件
把dll拷贝到哪里,这也是个问题,
先获取 java.library.path ,再把 dll拷贝到此路径下。这种方法不错。
static {
try {
String libpath = System.getProperty("java.library.path");
if ( libpath==null || libpath.length() == 0 ) {
throw new RuntimeException("java.library.path is null");
}
String path = null;
StringTokenizer st = new StringTokenizer(libpath, System.getProperty("path.separator"));
if ( st.hasMoreElements() ) {
path = st.nextToken();
} else {
throw new RuntimeException("can not split library path:" + libpath);
}
InputStream inputStream = Foo.class.getResource("jacob.dll").openStream();
final File dllFile = new File(new File(path), "jacob.dll");
if (!dllFile.exists()) {
FileOutputStream outputStream = new FileOutputStream(dllFile);
byte[] array = new byte[8192];
for (int i = inputStream.read(array); i != -1; i = inputStream.read(array)) {
outputStream.write(array, 0, i);
}
outputStream.close();
}
//dllFile.deleteOnExit();
Runtime.getRuntime().addShutdownHook(new Thread(){
public void run() {
if ( dllFile.exists() ) {
boolean delete = dllFile.delete();
System.out.println("delete : " + delete);
}
}
});
} catch (Throwable e) {
throw new RuntimeException("load jacob.dll error!", e);
}
}
关于不能删除dll文件问题,要先卸载它:
//卸载dll
try {
ClassLoader classLoader = this.getClass().getClassLoader();
Field field = ClassLoader.class.getDeclaredField("nativeLibraries");
field.setAccessible(true);
Vector libs = (Vector) field.get(classLoader);
Iterator it = libs.iterator();
Object o;
while (it.hasNext()) {
o = it.next();
Method finalize = o.getClass().getDeclaredMethod("finalize", new Class[0]);
finalize.setAccessible(true);
finalize.invoke(o, new Object[0]);
}
} catch (Exception ex) {
log.error("卸载dll文件出错,需要重启服务器!", ex);
throw new RuntimeException(ex);
}
经测试,此段代码有问题,没找出问题原因,以后再研究了。。。
分享到:
相关推荐
《易语言API全局热键源码解析》 易语言,作为一种中文编程语言,以其独特的语法和易用性深受初学者和专业人士的喜爱。API全局热键是计算机编程中的一个重要概念,它允许程序在不处于活动状态时也能响应特定的按键...
在开发应用程序时,为提高用户体验,经常需要设置全局热键以便用户快速启动某些功能。本文将详细介绍如何使用C#来实现全局热键的功能,并对代码进行深入解析。 #### 二、基础知识 ##### 1. P/Invoke (Platform ...
### C# 设置全局热键详解 #### 一、引言 在软件开发中,全局热键(Global Hotkeys)能够使应用程序对用户的键盘输入做出快速响应,即使该应用当前未处于活动状态。这对于提高用户体验非常有帮助,尤其适用于快捷...
全局热键,也称为快捷键或系统级热键,是一种能够在任何应用程序中响应特定按键组合的功能,使得用户可以通过键盘快速执行特定操作。在C#编程中,实现全局热键通常需要借助于Windows API(Application Programming ...
在Windows Presentation Foundation(WPF)框架中,实现系统全局热键是为应用程序提供快捷方式,使得用户无需将焦点置于应用程序窗口内,也能通过特定的按键组合执行特定操作。这种功能在许多应用程序中都非常常见,...
在本资源"C#.net 全局热键.rar"中,重点讲解了如何在C#环境下实现全局热键功能。全局热键,也称为系统热键或全局快捷键,允许用户在任何应用程序或操作系统界面下通过特定的按键组合执行特定的操作。 在Windows ...
### vb.net多个全局热键 #### 知识点概述: 本篇内容主要讲解如何在VB.NET应用程序中实现多个全局热键的功能。全局热键是指在任何应用程序中都可以激活的快捷键,这对于创建辅助工具或快捷操作非常有用。本文将详细...
本文将深入探讨如何使用Java实现这一效果,包括如何创建一个工具类库(jar),以及如何通过全局热键来触发截图操作。我们将讨论以下几个关键知识点: 1. **JNI(Java Native Interface)**: JNI是Java平台的标准...
4. **加载DLL**:在Java程序中使用`System.loadLibrary`加载DLL,并调用JNI方法。 5. **调用DLL函数**:在Java中通过JNI接口调用DLL中的函数,实现热键屏蔽和任务栏隐藏功能。 在开发过程中,需要注意的是,由于...
本篇文章将详细讲解如何在C#中实现全局热键和窗体热键的设置。 1. **窗体热键设置** 窗体热键是指在当前活动窗体上响应的快捷键。首先,为了使窗体能够捕获到键盘事件,我们需要在窗体的`KeyPreview`属性设置为`...
在这个项目中,DLL可能被用来与系统更底层的键盘事件交互,因为Java本身可能无法直接处理全局热键。 7. **运行与调用**: 要运行这个jar文件,你可以使用Java的`java -jar`命令,确保dll文件和jar文件在同一目录下...
这意味着程序可能使用了动态链接库(DLL)来实现某些功能,例如热键处理或特定的键盘逻辑。DLL文件可以被多个程序共享,减少内存占用,提高代码复用性。通过调用`LoadLibrary`和`GetProcAddress`函数,主程序可以从...
`RegisterHotKey`函数来自`user32.dll`,参数分别为窗口句柄(None表示全局热键)、热键ID(4001)、修饰键(在这里是`keyCtrl | keyAlt`)和虚拟键码(`keyF3`)。如果返回值为0,则表示注册失败,否则为成功。 ...
在Delphi编程环境中,设置全局快捷键是一项常见的需求,它可以让用户通过特定的键盘组合在任何应用程序中触发我们的功能。全局快捷键(Global Hotkeys)的实现涉及到Windows API调用和消息处理,以下将详细解释如何...
### 在C#中使用热键隐含窗口 #### 概述 本文档旨在介绍如何在C#编程语言中实现窗口的隐含功能,并通过热键(快捷键)来进行控制。...此外,还可以进一步扩展此功能,比如添加更多热键以支持不同类型的窗口操作。
全局热键,也称为系统级快捷键,是能够在任何应用程序窗口甚至无活动窗口下响应的按键组合。在桌面应用程序中,全局热键可以提供一种快速访问功能的方式,增强用户交互体验。本文将深入探讨如何在C#环境下,利用.NET...
1. **全局热键**: JIntelliType允许Java程序注册并响应全局热键,这些热键在应用程序窗口无焦点或最小化时仍然有效。这对于创建全局快捷键控制的应用非常有用,如多媒体播放器、聊天软件等。 2. **鼠标事件监听**: ...
描述中提到的`jintellitype-1.3.6.jar`和`JIntellitype.dll`是用于此目的的重要库,特别是`JIntellitype`库,它是Java平台上的一个开源库,允许开发者在他们的Java应用中创建和管理系统全局热键。 **JIntellitype库...
- `GlobalAddAtom` 和 `GlobalDeleteAtom`:这两个函数来自`kernel32.dll`,用于创建和删除全局原子,这里用于生成唯一的热键ID。 4. **构造函数**: `Hotkey`类的构造函数接收一个窗口句柄`hWnd`,并将其保存...