将键盘重新映射到较低级别 [英] Remapping the Keyboard at a low level

查看:121
本文介绍了将键盘重新映射到较低级别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在替换最初为MSDOS编写的遗留C应用程序(是的,信不信由你!)。此应用程序使用一个特殊重映射的键盘拦截DOS键盘中断(记住??!)有时会改变用户按下的键的扫描码,以便进行不同的处理。然后在键上放置特殊标签,告诉用户这些键的新含义。

We are replacing a legacy C application originally written for MSDOS (yes, believe it or not!). This application uses a specially remapped keyboard which intercepts the DOS keyboard interrupt (remember that??!) to sometimes alter the scan codes of the keys pressed by the user so that different processing would occur. Special labels were then placed on the keys telling the users the "new" meaning of these keys.

需要新的Java版本来保留目标组的键盘布局用户非常熟悉。

The new Java version is required to preserve this keyboard layout which the targeted group of users is very familiar with.

我们尝试做的一个例子如下:

An example of what we are trying to do is as follows:

您可能从未想过这一点,但现代电话的数字键盘与计算机键盘的数字键盘相反。前者1-2-3位于顶行,后者位于底行。我们需要使键盘的数字键盘看起来像电话。让我们说,当用户在数字键盘上输入7时,我们希望它看起来好像输入1,当他输入8时,我们想要一个2,当他输入3时我们想要一个9。

You may never have thought about this, but the numeric keypad of a modern telephone is reversed from the numeric keypad of a computer keyboard. On the former 1-2-3 is on the top row and on the latter it is on the bottom row. We are required to make the keyboard's numeric keypad look like the telephone. Let's say, when the user types "7" on the numeric keypad, we want it look as though he typed a "1", when he types an "8", we want a "2", when he types a "3" we want a "9".

我们还需要做更多的事情来模拟DOS应用程序,但我们现在甚至无法解决这个简单的情况。我已经遍布Key Binding,KeyAdapters,KeyListeners,甚至KeyEventDispatcher,我无法做到这一点。我很确定我们必须在Java允许的最低级别上工作,以尽可能接近遗留应用程序的工作。不用说,我们希望最干净的实现成为可能,这样应用程序级代码就不会被inputMaps和actionMaps等所困扰。尽可能地,这需要全局处理。任何人都可以帮忙吗?

There is much more that we have to do to emulate the DOS application, but we can't even solve this simple case now. I have been all over Key Binding, KeyAdapters, KeyListeners, and even KeyEventDispatchers, and I cannot make this work. I am pretty sure we have to work on the lowest level we are allowed to work by Java to come as close as possible to what the legacy app does. And needless to say, we want the cleanest implementation possible, so that the application level code is not littered with inputMaps and actionMaps etc. As much as possible this needs to be handled globally. Can anyone help?

推荐答案

我的堆栈溢出!
答案就在这里:
http://download.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html
说:

My stack overfloweth! The answer was here: http://download.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html which says:


对于按下键和按键释放的
事件,getKeyCode方法返回
事件的keyCode。对于键入的
事件,getKeyCode方法总是
返回VK_UNDEFINED。

For key pressed and key released events, the getKeyCode method returns the event's keyCode. For key typed events, the getKeyCode method always returns VK_UNDEFINED.

我原来的尝试认为它可以获得KEY_TYPED上的keyCode。它不能,并且KEY_TYPED事件破坏了在KEY_PRESSED中完成的映射。

My original attempt thought it could get a keyCode on KEY_TYPED. It could not, and it was the KEY_TYPED event that was clobbering the mapping done in KEY_PRESSED.

这是一个有效的实现:

import static java.awt.event.KeyEvent.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;


public class KeyboardDispatcherDemo extends JFrame {

    /**
     * This class shows how to map numeric keypad keys.
     * It performs two conversions:
     * 1. lower-to-uppercase
     * 2. if numeric keypad 7-9 is typed, 1-3 appears and vice versa.
     * 
     * This is modified from the code at 
     * http://www.exampledepot.com/egs/java.awt/DispatchKey.html#comment-51807
     * which demoes the lower-to-upper conversion.
     * 
     * It doesn't yet handle modified numeric keypad keys.
     * 
     */
    public KeyboardDispatcherDemo() {

        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(
            new KeyEventDispatcher() {
                private char lastMappedKey;
                private final Map<Integer, Character> keyMap = 
                    new HashMap<Integer, Character>() { 
                {
                    put(VK_NUMPAD1, '7'); 
                    put(VK_NUMPAD2, '8'); 
                    put(VK_NUMPAD3, '9'); 
                    put(VK_NUMPAD7, '1'); 
                    put(VK_NUMPAD8, '2'); 
                    put(VK_NUMPAD9, '3'); 

                }};

                public boolean dispatchKeyEvent(KeyEvent e) {
                    System.out.println(String.format("INPUT: %s", e.toString()));
                    boolean dispatch = false;
                    switch (e.getID()) {
                    case KeyEvent.KEY_PRESSED:
                        dispatch = dispatchKeyPressed(e);
                        break;
                    case KeyEvent.KEY_TYPED:
                        dispatch = dispatchKeyTyped(e);
                        break;
                    case KeyEvent.KEY_RELEASED: 
                        dispatch = dispatchKeyReleased(e);
                        break;
                    default:
                        throw new IllegalArgumentException();
                    }
                    System.out.println(String.format("OUTPUT: %s", e.toString()));
                    System.out.println();
                    return dispatch;
                }
                private boolean dispatchKeyPressed(KeyEvent e) {
                    char k = e.getKeyChar();
                    if (k != CHAR_UNDEFINED) {
                        if (Character.isLetter(k)) {
                            e.setKeyChar(Character.toUpperCase(e.getKeyChar()));
                        } else if (e.getModifiers() == 0){
                            Character mapping = keyMap.get(e.getKeyCode());
                            if (mapping != null) {
                                e.setKeyChar(mapping);
                            }
                        }
                        // save the last mapping so that KEY_TYPED can use it.
                        // note we don't do this for modifier keys.
                        this.lastMappedKey = e.getKeyChar();
                    }
                    return false;
                }

                // KEY_TYPED events don't have keyCodes so we rely on the
                // lastMappedKey that was saved on KeyPressed.
                private boolean dispatchKeyTyped(KeyEvent e) {
                    char k = e.getKeyChar();
                    if (k != CHAR_UNDEFINED) {
                        e.setKeyChar(lastMappedKey);
                    }
                    return false;
                }
                private boolean dispatchKeyReleased(KeyEvent e) {
                    char k = e.getKeyChar();
                    if (k != CHAR_UNDEFINED) {
                        e.setKeyChar(lastMappedKey);
                        this.lastMappedKey=CHAR_UNDEFINED;
                    }
                    return false;

                }
            });




        setTitle("KeyboardDispatcherDemo");
        JPanel panel = new JPanel();
        panel.setBackground(new Color(204, 153, 255));
        panel.setLayout(new BorderLayout());
        getContentPane().add(panel, BorderLayout.CENTER);

        JTextArea staticText = new JTextArea();
        staticText.setText("This demonstrates how to map numeric keypad keys.  It uppercases all letters and converts Numeric Keypad 1-3 to 7-9 and vice versa.  Try it.");
        staticText.setLineWrap(true);
        staticText.setWrapStyleWord(true);
        panel.add(staticText, BorderLayout.NORTH);
        staticText.setFocusable(false);

        JTextField textField = new JTextField();
        textField.setText("");
        textField.setHorizontalAlignment(SwingConstants.LEFT);
        panel.add(textField, BorderLayout.SOUTH);
        textField.setColumns(10);
        textField.setFocusable(true);


        setSize(getPreferredSize());

        setVisible(true);


    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        new KeyboardDispatcherDemo();

    }

    @Override
    public Dimension getPreferredSize() {
        // TODO Auto-generated method stub
        return new Dimension(400,300);
    }

}

感谢所有推动我走向的人答案。

Thanks to all who nudged me toward the answer.

这让我想到了下一个问题...敬请期待。

which brings me to my next question ... stay tuned.

这篇关于将键盘重新映射到较低级别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆