Захват всех событий в JFrame без деактивации окна

112
14

Я пытаюсь разработать нечто вроде удаленного рабочего стола/клиента 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-решения приемлемы

спросил(а) 2012-12-12T11:53:00+04:00 7 лет, 2 месяца назад
1
Решение
49

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-21T23:57:00+04:00 7 лет, 2 месяца назад
52

Не можете ли вы постоянно настраивать окно (Window.setFocusableWindowState), потому что JFrame наследует этот метод из окна. Что-то простое: window.setFocusableWindowsState(true). И внутри ключевого слушателя событий вызовите это:
(этот код изменен, но первоначально из Unresponsive KeyListener для JFrame)


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-20T19:36:00+04:00 7 лет, 2 месяца назад
35

Вы можете использовать WindowListener.Hope, это поможет захватить событие. Также есть windowfocuslistener, windowstatististener.


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-21T14:38:00+04:00 7 лет, 2 месяца назад
35

Вы можете установить собственный FocusManager и переопределить метод dispatchEvent или использовать Toolkit.getDefaultToolkit(). addAWTEventListener (..). Однако это не поймает OS-уловленные keyEvents, но вы все равно получите события, такие как перерисовка, если вы зарегистрируетесь в наборе инструментов.

ответил(а) 2012-12-16T02:31:00+04:00 7 лет, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема