MenuShortcut KeyEvent не работает

Приведенный ниже код является тестируемым классом, который должен распечатывать некоторый текст, когда на клавиатуре нажата клавиша Control+A, а также отображать изображение в системном трее. Все это зависит от того, поддерживается ли системный трей вашей операционной системой.

Моя проблема в том, что текст не печатается, когда я нажимаю Control+A, он печатается только тогда, когда я нажимаю на элемент в системном трее.

/**
 *
 * @author Tyluur
 * @since Aug 23, 2013
 */
public class Testable {

public static void main(String... args) {
    registerTrayItems();
}

private static void registerTrayItems() {
    if (SystemTray.isSupported()) {
        SystemTray tray = SystemTray.getSystemTray();
        TrayIcon icon = null;
        MenuShortcut shortcut = new MenuShortcut(KeyEvent.VK_A);
        MenuItem menuItem = new MenuItem("Toggle", shortcut);
        menuItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.err.println("The action has been called!");
            }
        });
        PopupMenu popup = new PopupMenu();
        popup.add(menuItem);
        try {
            icon = new TrayIcon(new ImageIcon(new URL("http://i.imgur.com/xQoz2TN.png")).getImage(), "Typer", popup);
            tray.add(icon);
        } catch (MalformedURLException | AWTException e) {
            e.printStackTrace();
        }
    }       
}

}

2 ответа

Решение

Причина, по которой ваш код не работает, состоит в том, что Java не "глобально" прослушивает ваше ключевое событие, а только тогда, когда меню имеет ваш фокус и отображается.

Это также причина, почему нет возможности написать чистый кейлоггер Java. Java только позволяет вам захватывать оконные сообщения.

Обходной путь должен был бы реализовать один из этих вариантов:

  • Используйте JNI/JNA/ любую другую встроенную оболочку для доступа к перехвату глобальных ключей
  • Используйте невидимое окно, всегда находящееся сверху и не отображаемое в системном трее, в котором фиксируются события. Я бы не советовал использовать этот, так как он может либо не работать как шарм, либо раздражать вашего пользователя.

Верхний подход не сложен, но потребует от вас использовать собственный доступ, и поэтому ваше приложение становится специфичным для платформы.

Удачи!

Похоже, что из API вы должны попробовать этот конструктор для MenuItem()

MenuShortcut shortcut = new MenuShortcut(KeyEvent.VK_A, false);

по умолчанию требуется также нажатие клавиши Shift.

Другие вопросы по тегам