You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaFX制作Windows锁屏?需屏蔽Win键与Alt+Tab组合键

解决JavaFX全屏窗口屏蔽Windows键与Alt+Tab的方案

问题分析

你当前的JavaFX代码仅能拦截应用内普通按键,但Windows键、Alt+Tab这类系统级快捷键由Windows系统优先处理,JavaFX的事件过滤器无法直接捕获拦截,必须借助Windows原生API实现全局键盘钩子,或是调整窗口属性让它成为系统顶层锁定窗口。

实现方案

方案1:使用JNA调用Windows API(推荐)

通过JNA(Java Native Access)直接调用Windows的user32.dll函数,注册全局键盘钩子拦截指定系统快捷键。

  1. 添加JNA依赖
    在Maven/Gradle中引入依赖:

    <!-- Maven 依赖 -->
    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna</artifactId>
        <version>5.13.0</version>
    </dependency>
    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna-platform</artifactId>
        <version>5.13.0</version>
    </dependency>
    
  2. 编写全局键盘钩子类
    创建类处理全局键盘事件:

    import com.sun.jna.platform.win32.*;
    import com.sun.jna.win32.W32APIOptions;
    
    public class GlobalKeyHook implements WinUser.LowLevelKeyboardProc {
        private WinUser.HHOOK hHook;
        private final WinUser.LowLevelKeyboardProc keyboardProc = this;
    
        public GlobalKeyHook() {
            hHook = User32.INSTANCE.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL, keyboardProc, Kernel32.INSTANCE.GetModuleHandle(null), 0);
        }
    
        @Override
        public WinDef.LRESULT callback(int nCode, WinDef.WPARAM wParam, WinUser.KBDLLHOOKSTRUCT lParam) {
            if (nCode >= 0) {
                int keyCode = lParam.vkCode;
                // 拦截左右Windows键、Alt+Tab、Alt+Esc、Ctrl+Esc
                boolean isWinKey = keyCode == WinUser.VK_LWIN || keyCode == WinUser.VK_RWIN;
                boolean isAltTab = (User32.INSTANCE.GetAsyncKeyState(WinUser.VK_MENU) < 0) && keyCode == WinUser.VK_TAB;
                boolean isAltEsc = (User32.INSTANCE.GetAsyncKeyState(WinUser.VK_MENU) < 0) && keyCode == WinUser.VK_ESCAPE;
                boolean isCtrlEsc = (User32.INSTANCE.GetAsyncKeyState(WinUser.VK_CONTROL) < 0) && keyCode == WinUser.VK_ESCAPE;
    
                if (isWinKey || isAltTab || isAltEsc || isCtrlEsc) {
                    // 拦截该按键事件
                    return new WinDef.LRESULT(1);
                }
            }
            return User32.INSTANCE.CallNextHookEx(hHook, nCode, wParam, lParam.getPointer());
        }
    
        public void unhook() {
            if (hHook != null) {
                User32.INSTANCE.UnhookWindowsHookEx(hHook);
                hHook = null;
            }
        }
    }
    
  3. 集成到JavaFX启动类
    修改start方法,添加钩子初始化与销毁逻辑:

    private GlobalKeyHook keyHook;
    
    @Override
    public void start(Stage primaryStage) {
        try {
            // 初始化全局键盘钩子
            keyHook = new GlobalKeyHook();
    
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(Main.class.getResource("/vista/PantallaBloqueo.fxml"));
            Pane ventana = (Pane) loader.load();
    
            Scene escena = new Scene(ventana);
    
            primaryStage.setScene(escena);
            primaryStage.setFullScreen(true);
            primaryStage.setOnCloseRequest(e -> e.consume());
            primaryStage.setFullScreenExitKeyCombination(KeyCombination.NO_MATCH);
            // 全局钩子已处理Alt相关按键,移除原有局部拦截
            primaryStage.setAlwaysOnTop(true);
    
            primaryStage.show();
    
            // 程序退出时销毁钩子
            Runtime.getRuntime().addShutdownHook(new Thread(keyHook::unhook));
        } catch (IOException error) {
            error.printStackTrace();
        }
    }
    
    @Override
    public void stop() throws Exception {
        super.stop();
        if (keyHook != null) {
            keyHook.unhook();
        }
    }
    

方案2:设置窗口为系统顶层锁定样式(进阶)

若要实现类似Windows登录界面的彻底锁定效果,可调用Windows API调整窗口扩展样式:

// 在窗口显示后执行
Platform.runLater(() -> {
   Window window = primaryStage.getScene().getWindow();
   HWND hwnd = new HWND(Native.getComponentPointer(window));
   // 设置窗口为工具窗口+顶层窗口,移除任务栏显示
   int exStyle = User32.INSTANCE.GetWindowLong(hwnd, User32.GWL_EXSTYLE);
   exStyle |= WinUser.WS_EX_TOOLWINDOW | WinUser.WS_EX_TOPMOST;
   exStyle &= ~WinUser.WS_EX_APPWINDOW;
   User32.INSTANCE.SetWindowLong(hwnd, User32.GWL_EXSTYLE, exStyle);
});

注意事项

  • 全局键盘钩子需要程序以管理员权限运行,否则无法正常拦截系统快捷键。
  • 务必保留退出机制(如登录验证通过后调用keyHook.unhook()并关闭窗口),避免出现无法操作系统的情况。
  • 建议使用最新稳定版JNA,避免兼容性问题。

内容的提问来源于stack exchange,提问作者David Tzintzun Gonzalez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 11:42:46