[Solved] Read keyboard state in a macro

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
DavidHMcCracken
Posts: 44
Joined: Tue Apr 10, 2018 6:15 am

[Solved] Read keyboard state in a macro

Post by DavidHMcCracken »

Does OO/LO or UNO provide a function to enable a macro to determine the keyboard state, specifically of Shift, Ctrl, and Alt? I realize that I can register a keyboard listener but that is very expensive for an occasional event triggered by something else.
Last edited by Hagar Delest on Sat Jan 16, 2021 10:19 pm, edited 1 time in total.
Reason: tagged solved.
W10 Libre 6.1.5.2 and Ubuntu-Mate 18.04 Libre 6.0.7.3
eeigor
Posts: 214
Joined: Sun Apr 12, 2020 10:56 pm

Re: Read keyboard state in a macro

Post by eeigor »

I suppose you need an analog of the Win API:
Declare Function GetKeyboardState Lib "user32" (lpKeyState As Byte) As Long
But I can't find... The alphabetical list of functions, statements, and operators does not contain such a built-in function.

Example for all or almost all keys (information from this forum).
Paste the code below into the document module. Run the StartXKeyHandler() procedure, return to the document window and press any keys, including functional ones, adding modifier keys. Stop the process by calling the StopXKeyHandler() procedure.
Author: onidarbe (Belgium)

Code: Select all

'––––––––––––––––––––––––––––––––– 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 and Alt alone do not trigger this event.
Function XKeyHandler_keyPressed(oEvent) As Boolean
    XKeyHandler_keyPressed = False  'Don't cancel this‼

    REM  If oEvent.KeyCode = com.sun.star.awt.Key.RETURN Then  'if the "ENTER" key is pressed, 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
On Windows it works, on Linux you need to handle the DELETE key press differently.
Ubuntu 18.04 LTS • LibreOffice 7.5.3.2 Community
DavidHMcCracken
Posts: 44
Joined: Tue Apr 10, 2018 6:15 am

Re: Read keyboard state in a macro

Post by DavidHMcCracken »

I haven't found an answer to the question as I stated it but I have found a simple answer to my specific problem. I only wanted to know the mod keys (Shift, Ctrl, Alt) at the time of a mouse button click. I knew that this information was available in a keypress event but didn't realize that it is also in a mouse click event. The following code illustrates its use. For a broader discussion of the context see viewtopic.php?f=25&t=99888 "Hyperlink Listener".

Code: Select all

function MyMouseClick_mouseReleased(ev as object) as boolean
  dim vc as object
  if ThisComponent.CurrentController.ViewCursor.HyperlinkURL <> "" and _
    ev.Buttons = MyMouseButtons and ev.Modifiers = MyMouseMods then
	  vc = ThisComponent.CurrentController.ViewCursor
	  if ThisComponent.Text.compareRegionStarts(vc.Start, vc.End) = 0 then
             Follow hyperlink my way
        endif
   endif
   ' Default FALSE return
end function

W10 Libre 6.1.5.2 and Ubuntu-Mate 18.04 Libre 6.0.7.3
Post Reply