Код нажатой клавиши

Автор Sliv0210, 15 декабря 2020, 08:57

0 Пользователи и 1 гость просматривают эту тему.

Sliv0210

Добрый день...
подскажите пжлста как получить код нажатой клавиши?

eeigor

#1
com.sun.star.awt.XKeyHandler
<prefix>_KeyPressed()
Подробно здесь.

Мы ведь отвечали уже на ваш вопрос в другой теме (?)
В этом файле "Event Listeners & Handlers.ods" обработчик нажатия клавиш реагирует на все клавиши клавиатуры, ибо регистрируемое событие (название клавиши) выводится в строке состояния. Выберите код своей клавиши или создайте константу с этим кодом. Возможно, есть уже готовые константы – не знаю.

UPD: key
Например:
If oEvent.KeyCode = com.sun.star.awt.Key.RETURN Then <...>
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

eeigor

Sliv0210, темы с макросами лучше помещать в разделе Basic
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

Sliv0210

Цитата: eeigor от 15 декабря 2020, 14:27
Sliv0210, темы с макросами лучше помещать в разделе Basic
Хорошо... впредь буду знать

eeigor

#4
Автор темы подозрительно молчит...
Цитата: Sliv0210 от 15 декабря 2020, 08:57подскажите пжлста как получить код нажатой клавиши
Function XKeyHandler_KeyPressed(oEvent) As Boolean
   XKeyHandler_KeyPressed = False  'cancel KeyPressed
   MsgBox(oEvent.KeyCode)
End Function


Sliv0210, вам из примера ниже надо совсем немного: глобальная переменная, старт/стоп и 3 обработчика событий.
Обработка нажатия клавиши производится по такой схеме:
Function XKeyHandler_keyPressed(oEvent) As Boolean
   If oEvent.KeyCode = com.sun.star.awt.Key.RETURN Then ...  'если нажата клавиша "ВВОД", то ...
       ' Ваш код...
   End If
End Function


Если вы не хотите, чтобы нажатие обрабатывалось и системой (а только вами в коде обработчика события), то добавьте строку:
   XKeyHandler_KeyPressed = True

Код ниже выглядит угрожающе, но реагирует на нажатие любой клавиши в соответствии с её кодом.
Вставьте код ниже в модуль документа. Запустите процедуру StartXKeyHandler(), вернитесь в окно документа и нажимайте клавиши... любые, в том числе и функциональные (см. скриншот 1), добавляя клавиши-модификаторы (см. скриншот 2). Остановите процесс, вызвав процедуру StopXKeyHandler().
Автор: onidarbe (Бельгия)

'––––––––––––––––––––––––––––––––– XKeyHandler –––––––––––––––––––––––––––––––––

Global oXKeyHandler As Object

Sub StartXKeyHandler()
   If IsNull(oXKeyHandler) Then  'только если ещё не запущен
       oXKeyHandler = CreateUnoListener("XKeyHandler_", "com.sun.star.awt.XKeyHandler")
       ThisComponent.GetCurrentController.AddKeyHandler(oXKeyHandler)
   End If
End Sub

Sub StopXKeyHandler()
   If Not IsNull(oXKeyHandler) Then  'только если всё ещё работает
       ThisComponent.GetCurrentController.removeKeyHandler(oXKeyHandler)
       oXKeyHandler = Nothing  'чтобы узнать позже, что этот обработчик остановлен
   End If
End Sub

Sub XKeyHandler_disposing(oEvent)
   Call StopXKeyHandler
End Sub

'   Shift, Ctrl и Alt сами по себе не вызывают это событие.
Function XKeyHandler_keyPressed(oEvent) As Boolean
   XKeyHandler_keyPressed = False  'Don't cancel this‼

   REM  If oEvent.KeyCode = com.sun.star.awt.Key.RETURN Then ...  'если нажата клавиша "ВВОД", то ...

   vCode = oEvent.KeyCode
   Select Case vCode
       Case 256 To 265: vName = "Num" & vCode - 256
       Case 512 To 537: vName = Chr(vCode - 447)
       Case 768 To 793: vName = "F" & vCode - 767
       Case 1024 To 1031: vName = Choose(vCode - 1023 _
        , "DOWN", "UP", "LEFT", "RIGHT", "HOME", "END", "PAGEUP", "PAGEDOWN")
       Case 1280 To 1290: vName = Choose(vCode - 1279 _
        , "RETURN", "ESCAPE", "TAB", "BACKSPACE", "SPACE", "INSERT", "DELETE", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE")
       Case 1291 To 1301: vName = Choose(vCode - 1290 _
        , "POINT", "COMMA", "LESS", "GREATER", "EQUAL", "OPEN", "CUT", "COPY", "PASTE", "UNDO", "REPEAT")
       Case 1302 To 1311: vName = Choose(vCode - 1301 _
        , "FIND", "PROPERTIES", "FRONT", "CONTEXTMENU", "HELP", "MENU", "HANGUL_HANJA", "DECIMAL", "TILDE", "QUOTELEFT")
       Case 1536 To 1557: vName = Choose(vCode - 1535 _
        , "DELETE_TO_BEGIN_OF_LINE", "DELETE_TO_END_OF_LINE", "DELETE_TO_BEGIN_OF_PARAGRAPH", "DELETE_TO_END_OF_PARAGRAPH" _
        , "DELETE_WORD_BACKWARD", "DELETE_WORD_FORWARD", "INSERT_LINEBREAK", "INSERT_PARAGRAPH" _
        , "MOVE_WORD_BACKWARD", "MOVE_WORD_FORWARD", "MOVE_TO_BEGIN_OF_LINE", "MOVE_TO_END_OF_LINE" _
        , "MOVE_TO_BEGIN_OF_PARAGRAPH", "MOVE_TO_END_OF_PARAGRAPH" _
        , "SELECT_BACKWARD", "SELECT_FORWARD", "SELECT_WORD_BACKWARD", "SELECT_WORD_FORWARD" _
        , "SELECT_WORD", "SELECT_LINE", "SELECT_PARAGRAPH", "SELECT_ALL")
       Case Else: vName = "???"
   End Select

   vFunc = Choose(oEvent.KeyFunc + 1, "", "NEW", "OPEN", "SAVE", "SAVEAS", "PRINT", "CLOSE", "QUIT", "CUT", "COPY", "PASTE" _
    , "UNDO", "REDO", "DELETE", "REPEAT", "FIND", "FINDBACKWARD", "PROPERTIES", "FRONT")
   oMod = oEvent.Modifiers  '1=Shift, 2=Ctrl, 4=Alt
   If oMod and 1 Then vMod = vMod & "+SHIFT"
   If oMod and 2 Then vMod = vMod & "+CTRL"
   If oMod and 4 Then vMod = vMod & "+ALT"

   vChar = oEvent.KeyChar
   If vChar = "" Then
       vOut = vName
   ElseIf Asc(vChar) > 32 And Asc(vChar) < 176 Then
       vOut = vChar
   Else
       vOut = vName
   End If

   MsgBox "Key " & Chr$(34) & vOut & vMod & Chr$(34)
End Function

Function XKeyHandler_keyReleased(oEvent) As Boolean
   XKeyHandler_keyReleased = False  'Don't cancel this‼
End Function


Примечания:
1. Код выше в целом работает: при нажатии на любую клавишу (раскладка только латинская) информация выводится в окно MsgBox().
2. Есть глюк при дополнительном нажатии одновременно трех клавиш-модификаторов Shift+Ctrl+Alt (см. скриншот 3), срабатывает строка:
   Case Else: vName = "???"   'зд. стоят три вопросительных знака, и их можно увидеть в окне MsgBox()

   Автор кода сообщает, что "Shift, Ctrl и Alt сами по себе не вызывают событие XKeyHandler_keyPressed", однако у меня при нажатии всех трёх клавиш-модификаторов одновременно событие срабатывает, но результат ошибочный (см. тот же скриншот 3).  

3. ERROR: При нажатии на клавишу DELETE (код клавиши верен, vName = "DELETE") переменной vChar присваивается некий код (см. скриншот 4, строка DELETE не выведена), но переменная должна содержать пустую строку:
   vChar = oEvent.KeyChar  'что-то здесь не так
   If vChar = "" Then
       vOut = vName
   ElseIf Asc(vChar) > 32 And Asc(vChar) < 176 Then
       vOut = vChar
   Else
       vOut = vName
   End If

   Проблема в том, что oEvent.KeyCode = 1286 (vName = "DELETE"), но oEvent.KeyChar тоже содержит нечто, что мы видим на скриншоте. Поясните, кто знает.
   Что-то вроде: «Управляющий символ для удаления (на перфолентах)» (007F).

4. Case-Choose
   Коды некоторых (небуквенных) клавиш преобразовываются в соответствующие слова (наименования констант) для вывода сообщения. С диапазоном кодов в селекторе Case сопоставлены слова в функции Choose(). Полный перечень кодов и слов (наименований констант) здесь.
   Не опознаётся клавиша CAPSLOCK = 1312 (легко добавить).

В остальном - всё хорошо. Пример полезен для ознакомления.

Протестировано в среде Ubuntu 18.04 LTS • LO 7.0.2.2.

Автору - респект!

P.S. Если кто-то будет тестировать у себя, отпишитесь...
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

eeigor

#5
Судя по всему, проблема (особенность) с клавишей DELETE имеет место только для UNIX-систем, но не для DOS/WINDOWS.

UPD:
Протестировал под WINDOWS – ошибок с нажатием трёх клавиш-модификаторов и клавишей DELETE нет! Ошибки, описанные выше в примечаниях 2 и 3 – только для... ну, у меня LINUX.
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community

bigor

Запустил на kubuntu 19.10  LO Version: 7.0.1.2
Build ID: 7cbcfc562f6eb6708b5ff7d7397325de9e764452
CPU threads: 4; OS: Linux 5.3; UI render: default; VCL: kf5
Locale: ru-RU (ru_RU.UTF-8); ИП: ru-RU
Calc: threaded
с буквами цифрами все нормально, клавиши модификаторы (Alt, Shift, Ctrl) выдают перед именем ??? даже при одиночном нажатии, delete  выдает " "
Поддержать разработчиков LibreOffice можно можно тут, а наш форум вот тут

eeigor

#7
Bigor, мы тут ничего сделать не можем. На WINDOWS всё работает правильно. Правда, нажатия клавиш "CAPSLOCK", "NUMLOCK", "SCROLLLOCK" не перехватываются. Но это и неважно. Так, ради полноты исследования вопроса...

oEvent.Modifiers должно содержать информацию о клавишах-модификаторах. Тут тоже добавить нечего...
А нажатие клавиши DELETE в UNIX-системах надо просто по-другому обработать.
Добавляю этот пример в свою "библиотеку кода".
Ubuntu 18.04 LTS • LibreOffice 7.5.1.2 Community