2014-02-03 5 views
5

Как я могу отправить пользовательское событие ключа SWT таким образом, чтобы оно приводило к набору этого точного буквенного символа без какого-либо преобразования?Пользовательские ключевые события

Мы создаем пользовательскую экранную графическую клавиатуру, которая позволяет использовать несколько возможных макетов: QWERTY является основным, но некоторые другие планируются, в том числе те, которые визуально имитируют раскладку клавиатуры iPhone или другие, которые являются нестандартными относительными к ПК.

Я хотел был бы иметь возможность послать любой произвольный символ моего выбора в качестве события, так что это приведет к набору этого точного символа. Тем не менее, всякий раз, когда я отправляю событие с заданным символом, SWT, кажется, автоматически интерпретирует и преобразует его на основе настроек клавиатуры и статуса, меняя его на заглавные буквы/строчные буквы или используя сдвинутые символы в зависимости от того, сдвиг или сдвиг нажата клавиша (например, настоящая на реальной клавиатуре). Например, передача символа «T» через ключевое событие приведет к либо «t», либо «T» в зависимости от клавиши переключения. Он выполняет аналогично символу «4», делая либо «4», либо «$» на основе сдвига.

Это проблематично, поскольку я хочу выполнять перенос символов вручную и, возможно, не желаю использовать те же символы сдвига, что и стандартная клавиатура QWERTY в любом случае (возможно, например, я хочу '$' быть сдвинутой (или «функциональной» клавишей) версии «R» на более мелкой клавиатуре, подобной сотовому телефону). Как я могу использовать эти события, чтобы не использовать QWERTY-ключи?

Документация для поля «характер» в SWT событий говорит следующее:

символ, представленный ключом, который набирался. Это окончательный символ , который появляется после применения всех модификаторов. Например, для , когда пользователь набирает Ctrl + A, значение символа равно 0x01. Это значение важно, чтобы приложения не пытались изменить значение знака на основе состояния (например, SWT.CTRL) или результат будет неправильным.

Это заставляет меня полагать, что это не должно быть преобразование моего персонажа, как оно есть, поскольку я приказываю ему использовать мой «окончательный» результат.

Я создал простой, автономный пример, чтобы продемонстрировать мою проблему (обратите внимание, что это не так, как я делаю фактическую клавиатуру, и предназначено только для выделения ключевого вопроса события):

screenshot

import org.eclipse.swt.SWT; 
import org.eclipse.swt.events.SelectionAdapter; 
import org.eclipse.swt.events.SelectionEvent; 
import org.eclipse.swt.events.SelectionListener; 
import org.eclipse.swt.layout.GridLayout; 
import org.eclipse.swt.widgets.Display; 
import org.eclipse.swt.widgets.Event; 
import org.eclipse.swt.widgets.Shell; 
import org.eclipse.swt.widgets.Text; 
import org.eclipse.swt.layout.GridData; 
import org.eclipse.swt.widgets.Composite; 
import org.eclipse.swt.widgets.Button; 

public class KeyboardIssueExample extends Shell { 
    private Text txtTextArea; 
    private Composite cmpButtons; 
    private Button btnBigA; 
    private Button btnBigS; 
    private Button btnLittleD; 
    private Button btnSix; 
    private Button btnSeven; 
    private Button btnDollah; 
    private Button btnStar; 

    private SelectionListener mainListener = new SelectionAdapter() { 
     @Override 
     public void widgetSelected(SelectionEvent selE) { 
      Button b = (Button)selE.widget; 
      char c = b.getText().charAt(0); 
      sendKey(c); 
     } 
    }; 

    /** 
    * Launch the application. 
    * @param args 
    */ 
    public static void main(String args[]) { 
     try { 
      Display display = Display.getDefault(); 
      KeyboardIssueExample shell = new KeyboardIssueExample(display); 
      shell.open(); 
      shell.layout(); 
      while (!shell.isDisposed()) { 
       if (!display.readAndDispatch()) { 
        display.sleep(); 
       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Create the shell. 
    * @param display 
    */ 
    public KeyboardIssueExample(Display display) { 
     super(display, SWT.SHELL_TRIM); 
     createContents(); 
    } 

    /** 
    * Create contents of the shell. 
    */ 
    protected void createContents() { 
     setText("SWT Application"); 
     setSize(450, 300); 
     setLayout(new GridLayout()); 

     txtTextArea = new Text(this, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI); 
     txtTextArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); 

     cmpButtons = new Composite(this, SWT.NONE); 
     cmpButtons.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     GridLayout gl_cmpButtons = new GridLayout(7, false); 
     gl_cmpButtons.marginWidth = 0; 
     gl_cmpButtons.marginHeight = 0; 
     cmpButtons.setLayout(gl_cmpButtons); 

     btnBigA = new Button(cmpButtons, SWT.NONE); 
     btnBigA.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     btnBigA.setText("A"); 

     btnBigS = new Button(cmpButtons, SWT.NONE); 
     btnBigS.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     btnBigS.setText("S"); 

     btnLittleD = new Button(cmpButtons, SWT.NONE); 
     btnLittleD.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     btnLittleD.setText("d"); 

     btnSix = new Button(cmpButtons, SWT.NONE); 
     btnSix.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     btnSix.setText("6"); 

     btnSeven = new Button(cmpButtons, SWT.NONE); 
     btnSeven.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     btnSeven.setText("7"); 

     btnDollah = new Button(cmpButtons, SWT.NONE); 
     btnDollah.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     btnDollah.setText("$"); 

     btnStar = new Button(cmpButtons, SWT.NONE); 
     btnStar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); 
     btnStar.setText("*"); 

     init(); 
    } 

    private void init() { 
     btnBigA.addSelectionListener(mainListener); 
     btnBigS.addSelectionListener(mainListener); 
     btnLittleD.addSelectionListener(mainListener); 
     btnSix.addSelectionListener(mainListener); 
     btnSeven.addSelectionListener(mainListener); 
     btnDollah.addSelectionListener(mainListener); 
     btnStar.addSelectionListener(mainListener); 
    } 

    @Override 
    protected void checkSubclass() { 
     // Disable the check that prevents subclassing of SWT components 
    } 


    private void sendKey(char c) { 
     sendKeyEvent(c, SWT.KeyDown); 
     sendKeyEvent(c, SWT.KeyUp); 
    } 

    private void sendKeyEvent(char c, int eventType) { 
     txtTextArea.forceFocus(); 
     Event event = new Event(); 
     event.type = eventType; 
     event.character = c; 
     getDisplay().post(event); 
    } 

} 

Как вы увидите, ключевые события не уважают мое собственное использование капитализации, а вместо этого использует свой собственный. Как хлопотно.

+0

+1 Отличный вопрос. Не ожидал, что SWT будет вести себя так ... – Baz

+0

@Baz Спасибо, Baz. Хотя я волнуюсь, теперь - ты тот, на который я обычно рассчитываю, действительно знаю ответ! = P –

+0

Извините, что разочаровал вас:/ – Baz

ответ

3

Глядя на источник Display.post для Mac и для Windows существует много кода, специфичного для событий вверх/вниз по клавишам. Это включает в себя вызовы API-интерфейсов, специфичных для ОС, для преобразования указанного символа и кода ключа в параметры, требуемые специфичным для ОС способом, используемым для генерации события штриховки.

Для Windows этот код вызывает VkKeyScan, который, согласно документации Microsoft, просматривает текущее состояние клавиатуры.

Display имеет метод postEvent(Event), который добавляет в очередь событий, не изменяя ничего, но это не является общедоступным, поэтому вам нужно будет получить к нему доступ с использованием отражения. Поскольку он не является частью официального API, он может измениться.

Редактировать: Для этого есть отчет об ошибке Eclipse here. Он был открыт в течение 10 лет, поэтому, вероятно, он не будет исправлен!

Обновление: Существует также метод Widget.notifyListeners(eventType, Event), который может быть использован для отправки ключевых событий определенному элементу управления. Вам нужно будет создать Event и установить необходимые поля.

+0

+1 Отличный ответ! – Baz

Смежные вопросы