使用Java是否可以禁用Windows键?

6

是否可以使用Java禁用Windows键和Alt+Tab键?


一些按键无法被捕获,除非使用内核模式设备驱动程序。为什么Windows允许应用程序防止用户切换当前任务? - rep_movsd
虽然你对Alt+Tab有一定的观点,但在全屏应用程序(如游戏)中禁用Win键也有很好的理由。我无法告诉你有多少次我在游戏中意外碰到了左边的Win键,结果整个屏幕都最小化了。 - Will
@Will - 可能是的,Windows 设计师们持有不同的看法... - Stephen C
由于某种原因,在DirectDraw独占模式下运行时,Ctrl-Alt-Del被捕获,但其他键没有... - rep_movsd
1个回答

12

您可以使用JNA来实现此操作。

在类路径中包含jna.jar和platform.jar,并创建以下类。此类禁用了左Windows键(0x5B)和右Windows键(0x5C)。因此,您可以在switch case语句中添加其他代码。

当您的应用程序启动时,请尽快调用KeyHook.blockWindowsKey()。另一方面,在应用程序关闭时调用unblockWindowsKey()。

由于只有在isWindows()为true时才执行该代码,因此即使在运行另一个操作系统时,您也可以始终调用KeyHook.blockWindowsKey()。



import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.KBDLLHOOKSTRUCT;
import com.sun.jna.platform.win32.WinUser.LowLevelKeyboardProc;
import com.sun.jna.platform.win32.WinUser.MSG;

public class KeyHook {
    private static HHOOK hhk;            // 钩子句柄
    private static LowLevelKeyboardProc keyboardHook;  // 键盘事件回调函数
    private static User32 lib;           // Win32 API 库

    /**
     * 拦截Windows键
     */
    public static void blockWindowsKey() {
        if (isWindows()) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    lib = User32.INSTANCE;
                    HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
                    keyboardHook = new LowLevelKeyboardProc() {
                        public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
                            if (nCode >= 0) {
                                switch (info.vkCode){
                                    case 0x5B:  // 左Windows键
                                    case 0x5C:  // 右Windows键
                                        return new LRESULT(1); // 返回1表示拦截按键
                                    default: // 不做处理
                                }
                            }
                            return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
                        }
                    };
                    hhk = lib.SetWindowsHookEx(13, keyboardHook, hMod, 0); // 设置全局键盘钩子,以拦截所有键盘事件

                    // 进入消息循环
                    int result;
                    MSG msg = new MSG();
                    while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
                        if (result == -1) {
                            break;
                        } else {
                            lib.TranslateMessage(msg);
                            lib.DispatchMessage(msg);
                        }
                    }

                    // 卸载钩子
                    lib.UnhookWindowsHookEx(hhk);
                }
            }).start();
        }
    }

    /**
     * 解除Windows键拦截
     */
    public static void unblockWindowsKey() {
        if (isWindows() && lib != null) {
            lib.UnhookWindowsHookEx(hhk); // 卸载钩子
        }
    }

    /**
     * 判断操作系统是否为Windows
     */
    public static boolean isWindows(){
        String os = System.getProperty("os.name").toLowerCase();
        return (os.indexOf( "win" ) >= 0);
    }
}


1
你好。有没有办法禁用ctrl-alt-del?您的代码运行良好,但无法阻止ctrl-alt-del。任务管理器会弹出。 - MOD
如何销毁这个线程?在我运行了 unblockWindowsKey() 之后,这个线程仍然在后台运行。 - NM Naufaldo
@NMNaufaldo 你可以将Thread对象存储在类的字段中,并在禁用键阻塞器时中断它。在while循环中,当线程被中断时,你也可以使用break语句来退出循环。或者,你可以将该线程标记为守护线程,以允许JVM在该线程仍在运行时终止。 - Pieter12345

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接