9

我正在尝试开发类似远程桌面/ VNC 客户端的东西。我有必要捕获客户端窗口中的所有事件。我正在使用的方法是覆盖以下processEvent方法JFrame

@Override
protected void processEvent(AWTEvent e) {
    ...
}

Windows但是,在键或窗口等事件Alt+Tab被停用时:

...    
00000191 KEY_PRESSED,keyCode=524,keyText=Windows,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_LEFT,rawCode=91,primaryLevelUnicode=0,scancode=91,extendedKeyCode=0x20c 
00000192 KEY_RELEASED,keyCode=524,keyText=Windows,keyChar=Undefined keyChar,keyLocation=KEY_LOCATION_LEFT,rawCode=91,primaryLevelUnicode=0,scancode=91,extendedKeyCode=0x20c 
000000ce WINDOW_DEACTIVATED,opposite=null,oldState=0,newState=0 
...

如何在此类事件中保持窗口处于活动状态?

更喜欢纯 Java 解决方案。如果没有纯 Java 解决方案,有人可以指出我的 JNA 解决方案(或任何其他解决方案)吗?

EDIT1: *解决了窗口停用的模糊术语“焦点”*强调非纯 Java 解决方案是可以接受的

4

4 回答 4

1

1.) JNA 附带了一个几乎可以满足您需求的示例:

http://java.net/projects/jna/sources/svn/content/trunk/jnalib/contrib/w32keyhook/KeyHook.java

为了阻止一个键,只需返回 1 而不是调用CallNextHookEx-cf。MSDN文档。

2.) JNativeHook允许您挂钩到全局事件处理,但现在没有办法阻止事件被传递 - 例如,Windows 键仍将激活开始菜单。但是它仍然值得一看,因为它的开销要少得多,并且您可以修改它(从CallNextHookEx 这里开始)以按照您想要的方式运行。虽然它是根据 GPL 许可的。

3.) 另一种干净的方法是切换到 SWT 并使用SWT Win32 Extensions来拦截键盘事件。

于 2012-12-21T20:57:43.947 回答
1

您能否将窗口始终设置为可聚焦(Window.setFocusableWindowState),因为 JFrame 确实从 Window 继承了该方法。像这样简单的东西:window.setFocusableWindowsState(true). 在关键事件侦听器内部调用:(此代码已修改,但最初来自JFrame 的 Unresponsive KeyListener

public class MyFrame extends JFrame { 

    private class MyDispatcher implements KeyEventDispatcher 
    {
        private JFrame frame;

        public MyDispatcher(JFrame jf)
        {
            this.frame = jf;
        }

        public boolean dispatchKeyEvent(KeyEvent e) 
        {
            frame.setFocusableWindowState(true);
            return false;
        }
    }

    public MyFrame() 
    {
        add(new JTextField());
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.addKeyEventDispatcher(new MyDispatcher(this));
    }

    public static void main(String[] args) 
    {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}

我没有测试这段代码,但我希望至少这个想法能让你朝着正确的方向前进。

于 2012-12-20T16:36:50.587 回答
0

您可以使用WindowListener。希望这将有助于捕获事件。还有windowfocuslistener,windowstatelistener。

public class WindowListenerImpl implements WindowListener(){
     @Override
                        public void windowOpened(WindowEvent windowevent) {
                           //urs windowevent to get source.

                        }

                        @Override
                        public void windowIconified(WindowEvent windowevent) {
                           //urs windowevent to get source.

                        }

                        @Override
                        public void windowDeiconified(WindowEvent windowevent) {
                            //urs windowevent to get source.

                        }

                        @Override
                        public void windowDeactivated(WindowEvent windowevent) {

                             //urs windowevent to get source.
                        }

                        @Override
                        public void windowClosing(WindowEvent windowevent) {
                           //urs windowevent to get source.

                        }

                        @Override
                        public void windowClosed(WindowEvent windowevent) {
                             //urs windowevent to get source.

                        }

                        @Override
                        public void windowActivated(WindowEvent windowevent) {
                           //urs windowevent to get source.

                        }
    public WindowEvent{
    public static void main(String[] args){
    WindowListenerImpl  listenerImpl=new WindowListenerImpl ();
    new JFrame.addWindowListener(listenerImpl);
    }
于 2012-12-21T11:38:05.610 回答
0

您可以设置自定义 FocusManager 并覆盖 dispatchEvent 方法或使用 Toolkit.getDefaultToolkit().addAWTEventListener(..)。但是,这不会捕获操作系统捕获的 keyEvents,但是如果您在工具包中注册,您仍然会收到诸如重绘之类的事件。

于 2012-12-15T23:31:20.080 回答