Auslesen von Fernbedienungstasten

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

Autohotkey1962
Posts: 5
Joined: 02 Jan 2020, 04:21

Auslesen von Fernbedienungstasten

02 Jan 2020, 04:37

Hallo Freunde, ich bin neu hier. Ich habe mir die Befehle und Funktionen schon einmal grob angesehen. Aber irgendwie werde ich bzgl. meines Problems nicht fündig. Ich möchte gern eine an den USB Port angeschlossene Fernbedienung auslesen, bzw. ich möchte mir anzeigen lassen, was passiert, wenn ich auf der Fernbedienung eine Taste drücke. Diese zurück gegebenen Werte würde ich dann gern per Script dazu nutzen, parallel zur eigentlichen Funktion (Musik steuern) eine weitere Software zu steuern.

In etwa so:

Taste auf der Fernbedienung wird gedrückt und Musik über die mit der Fernbedienung gelieferte Musiksoftware startet. AHK liest die Daten aus und über ein Skript wird beim Druck auf Taste X ein Button in einem bereits anderweitig geöffneten Windowsprogramm gedrückt.

Vielen Dank für Eure Hilfe bei einem absoluten Newbee.

Und by the way: Ein Frohes Neues Jahr.
gregster
Posts: 3736
Joined: 30 Sep 2013, 06:48

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 06:59

Willkommen im Forum!

Ich hab persönlich keinerlei Erfahrung mit solchen Fernbedienungen, aber du könntest mal schauen, ob AHK die Tastendrücke registriert (vgl. https://www.autohotkey.com/docs/KeyList.htm#SpecialKeys). Wenn das der Fall ist, dürfte es im Anschluss kein Problem sein, kontext-abhängige Hotkeys zu erstellen (mit den #IfWin... und #If Direktiven).
Evtl. gibt es auch bestimmte Optionen in den Einstellungen deiner Fernbedienung, die beeinflussen, was gesendet wird.
Autohotkey1962
Posts: 5
Joined: 02 Jan 2020, 04:21

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 07:25

Okay, verstehe ich das richtig, dass ich einfach folgende Zeilen in eine ahk Datei kopiere und diese dann durch einen Doppelklick starte, um dann eine taste zu drücken um festzustellen, ob die Fernbedienungstasten registriert werden?

#InstallKeybdHook
SC159:: ; Replace 159 with your key's value.
MsgBox, %A_ThisHotkey% was pressed.
return

Wenn ich das mache, passiert leider rein gar nichts Sichtbares. Es wird gar keine Messagebox geöffnet.
Ich habe dann mal in der Windowstrayleiste das grüne AHK Symbol doppelt geklickt. Da konnte ich dann noch die Funktion "keyhistory and scriptinfo" unter dem Menü "view" einschalten.
Da sah ich zumindest einmal, wenn ich eine Taste auf dem Keyboard drückte und ich mit F5 refreshte, welche Keyboardtaste ich gedrückt hatte. Beim Drücken der Fernbedienung passierte leider nichts.

Wo liegt also der Fehler, dass keine Messagebox mit entsprechendem Ergebnis angezeigt wird?
haichen
Posts: 303
Joined: 09 Feb 2014, 08:24

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 08:25

Das Skript nutzt einen bereits bekannten Tastencode und gibt ihn aus. Du mußt deine Tastencodes aber erst herausfinden.

Installiere Autohotkey, schreib dann das hier mal in eine Datei mit der Endung .ahk und starte sie mit einem Doppelklick.

Code: Select all

#InstallKeybdHook
Im Tray (Windows Taskleiste unten rechts) siehst du dann ein grünes Icon mit einem H. Mach einen Doppelklick darauf. Ein Fenster öffnet sich. Im Menü View ruft du das Untermenü "Key History.." auf. Da siehst du dann Tastendrücke. Da kannst du alle deine Tastendrücke sehen. Drücke ein paarmal Tasten deiner Fernbedienung und rufe dann nochmal die Key History auf. Mit den Codes die du so findest kannst du dann das Skript so ändern wie du es bereits getan hast. Den Tastencode mußt du an deine Funde anpassen. Findest du SC123 (nur ein Beispiel) für eine deine Ferbedienungstasten schreibst du also in dein Skript

Code: Select all

#InstallKeybdHook
SC123:: 
MsgBox, Taste %A_ThisHotkey% auf der Fernbedienung wurde gedrückt
return
gregster
Posts: 3736
Joined: 30 Sep 2013, 06:48

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 08:30

Die msgbox würde nur angezeigt, wenn deine Fernbedienung zufällig den Scancode SC159 senden würde - der fungierte hier nur als Beispiel ("Replace 159 with your key's value.").
Da konnte ich dann noch die Funktion "keyhistory and scriptinfo" unter dem Menü "view" einschalten.
Da sah ich zumindest einmal, wenn ich eine Taste auf dem Keyboard drückte und ich mit F5 refreshte, welche Keyboardtaste ich gedrückt hatte. Beim Drücken der Fernbedienung passierte leider nichts.
Das ist allerdings eher ein Problem. Wenn die KeyHistory nichts anzeigt, dann bleiben vielleicht nur die 'Alternate Solutions', die erwähnt werden. Aber ob die hier funktionieren, kann man nicht wissen.

Aber wie gesagt, ich habe keinerlei Erfahrung mit solchen Fernbedienungen und weiß nicht, was die überhaupt senden. Vielleicht reagiert nur "die mit der Fernbedienung gelieferte Musiksoftware" auf irgendwelche Signale/Nachrichten der Fernbedienung, aber es werden keine herkömmlichen Tastendrücke gesendet. Ob und wie man die detektieren kann, hängt wahrscheinlich vom jeweiligen Produkt ab... ich würde mal beim Hersteller schauen, ob die entsprechende Informationen bereithalten oder ein Forum haben, wo das diskutiert wird.

Vielleicht kann man auch in der mitgelieferten Software einstellen, dass die Fernbediennung bestimmte Tasten(kombinationen) senden soll. Das könnte helfen.
haichen
Posts: 303
Joined: 09 Feb 2014, 08:24

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 08:48

Du könntest zusätzlich mal #InstallMouseHook in das Skript schreiben. Der Rest wie du es schon herausgefunden hattest. Skript neu starten, KeyHistory anzeigen lassen nachdem du auf der Fernbedienung Tasten gedrückt hast. Vielleicht werden diese Tasten darüber erkannt.
haichen
Posts: 303
Joined: 09 Feb 2014, 08:24

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 08:57

Ich habe mal meinen Logitech Presenter getestet. Der sendet schön PgDn, PgUp und andere Tasten.
just me
Posts: 6733
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 11:38

Moin,

auch ich habe keine Ahnung vom Umgang mit Fernbedienungen. Falls diese sich aber dem Rechner gegenüber als HID (Human Interface Device) zu erkennen geben, könnten die folgenden Skripte aus meiner Grabbelkiste etwas bringen:

RawInput.ahk:

Code: Select all

#NoEnv
; ================================================================================================================================
; Auto-execute section
; ================================================================================================================================
; Context menu LV Devices
Menu, CtxDev, Add, &Register, CtxDevRegister
Menu, CtxDev, Add, &Copy, CtxDevCopy
Menu, CtxDev, Add
Menu, CtxDev, Add, Refresh, CtxDevRefresh
; --------------------------------------------------------------------------------------------------------------------------------
; Context menu LV Info
Menu, CtxInf, Add, &Copy, CtxInfCopy
; --------------------------------------------------------------------------------------------------------------------------------
; Context menu LV Registered
Menu, CtxReg, Add, &Unregister, CtxRegUnregister
Menu, CtxReg, Add, &Copy, CtxRegCopy
Menu, CtyReg, Add
Menu, CtxReg, Add, Unregister All, CtxRegUnregisterAll
; --------------------------------------------------------------------------------------------------------------------------------
; Context menu LV RawInput
Menu, CtxRaw, Add, &Clear, CtxRawClear
Menu, CtxRaw, Add, &Copy, CtxRawCopy
; --------------------------------------------------------------------------------------------------------------------------------
Gui, Main: New, +OwnDialogs +HwndHMAIN
Gui, Add, Text, xm, Device List:
Gui, Add, ListView, xm y+2 w810 r10 vDevices gMainShowInfo -LV0x10 -Multi AltSubmit, Handle|Type|Page|Usage|Name
Gui, Add, Text, xm, Additional Device Info:
Gui, Add, Text, xm+410 yp, Registered Devices:
Gui, Add, ListView, xm y+2 w400 r6 vInfo NoSortHdr -LV0x10, Key|Value
Gui, Add, ListView, xm+410 yp w400 r6 vRegistered NoSortHdr -LV0x10, Page|Usage|Flags|HWND
Gui, Add, Text, xm, Raw Input:
Gui, Add, ListView, xm y+2 w810 r10 vRawInput -LV0x10 -Multi -Hdr, Raw Input
LV_Add("", "DummyEntry")
Gui, Add, StatusBar
; --------------------------------------------------------------------------------------------------------------------------------
GoSub, MainRefreshDevices
Gui, Main: Show, , RawInput Devices (Main GUI HWND = %HMAIN%)
; --------------------------------------------------------------------------------------------------------------------------------
OnMessage(0x00FF, "OnRawInput")  ; WM_INPUT
OnMessage(0x00FE, "OnDevChange") ; WM_INPUT_DEVICE_CHANGE - Win Vista+
Return
; ================================================================================================================================
; Main GUI
; ================================================================================================================================
MainGuiClose:
MainGuiEscape:
Gosub, MainUnregisterAll
ExitApp
; --------------------------------------------------------------------------------------------------------------------------------
MainGuiContextMenu:
If (A_GuiControl = "Devices") {
   Gui, ListView, Devices
   If (Selected := LV_GetNext())
      Menu, CtxDev, Show
}
Else If (A_GuiControl = "Registered") {
   Gui, ListView, Registered
   If (Selected := LV_GetNext())
      Menu, CtxReg, Show
}
Else If (A_GuiControl = "Info") {
   Gui, ListView, Info
   If LV_GetCount()
      Menu, CtxInf, Show
}
Else If (A_GuiControl = "RawInput") {
   Gui, ListView, RawInput
   If LV_GetCount() {
      Selected := LV_GetNext()
      Menu, CtxRaw, % Selected ? "Enable" : "Disable", &Copy
      Menu, CtxRaw, Show
   }
}
Return
; --------------------------------------------------------------------------------------------------------------------------------
MainRefreshDevices:
Gui, Main: Default
Gui, ListView, Devices
DevArr := RI_GetDeviceList()
GuiControl, -g, Devices
LV_Delete()
For Index, Dev In DevArr.Lst {
   DevName := RI_GetDeviceName(Dev.Handle)
   DevInfo := RI_GetDeviceInfo(Dev.Handle)
   LV_Add("", Dev.Handle, Dev.Type, DevInfo.Page, DevInfo.Usage, DevName)
}
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
Gui, ListView, Info
LV_Delete()
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
GuiControl, +gMainShowInfo, Devices
Cnt := DevArr.Cnt
SB_SetText("   Devices: Total = " . Cnt.T . ", HID = " . Cnt.H . ", Keyboard = " . Cnt.K . ", Mouse = " . Cnt.M)
Return
; --------------------------------------------------------------------------------------------------------------------------------
MainRefreshRegistered:
Gui, Main: Default
Gui, ListView, Registered
DevArr := RI_GetRegisteredDevices()
LV_Delete()
For Index, Dev In DevArr
   LV_Add("", Dev.Page, Dev.Usage, Dev.Flags, Dev.HWND)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
Return
; --------------------------------------------------------------------------------------------------------------------------------
MainUnregisterAll:
Gui, Main: Default
Gui, ListView, Registered
GuiControl, -Redraw, Registered
CurrentRow := LV_GetCount()
Loop, % LV_GetCount() {
   LV_GetText(Page, CurrentRow, 1)
   LV_GetText(Usage, CurrentRow, 2)
   If !RI_UnRegisterDevices(Page, Usage)
      MsgBox, 16, %A_ThisLabel%, Could not unregister device!`nPage: %Page%`nUsage: %Usage%`nFlags: %Flags%`nError: %A_LastError%
   Else
      LV_Delete(CurrentRow)
   CurrentRow--
}
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, "AutoHdr")
GuiControl, +Redraw, Registered
Return
; --------------------------------------------------------------------------------------------------------------------------------
MainShowInfo:
Critical
Gui, ListView, Devices
If (A_GuiEvent == "I") && InStr(ErrorLevel, "S", 1) {
   LV_GetText(DevHandle, A_EventInfo, 1)
   DevInfo := RI_GetDeviceInfo(DevHandle)
   Gui, ListView, Info
   LV_Delete()
   For Key, Value In DevInfo
      If Key Not In DevType,Page,Usage
         LV_Add("", Key, Value)
   Loop, % LV_GetCount("Column")
      LV_ModifyCol(A_Index, "AutoHdr")
}
Return
; ================================================================================================================================
; Register GUI
; ================================================================================================================================
RegisterApply:
Gui, +OwnDialogs
Gui, Submit, NoHide
GuiControlGet, Page
Flags := 0
For Each, Flag In CheckBoxes
   Flags |= (%Flag%) ? RI_RIDEV(Flag) : 0
If !RI_RegisterDevices(Page, Usage, Flags, HWND) {
   MsgBox, 16, %A_ThisLabel%, Could not register devices!`nPage: %Page%`nUsage: %Usage%`nFlags: %Flags%`nError: %A_LastError%
   Return
}
GoSub, MainRefreshRegistered
; We don't want to return here!
; --------------------------------------------------------------------------------------------------------------------------------
RegisterGuiClose:
Gui, Main: -Disabled
Gui, Register: Destroy
GuiControl, Main:Focus, Devices
Return
; --------------------------------------------------------------------------------------------------------------------------------
RegisterCheckFlags:
If (A_GuiControl = "PAGEONLY") {
   GuiControl, , EXCLUDE, 0
   GuiControl, , NOLEGACY, 0
}
Else If (A_GuiControl = "EXCLUDE") {
   GuiControl, , PAGEONLY, 0
   GuiControl, , NOLEGACY, 0
}
Else If (A_GuiControl = "NOLEGACY") {
   GuiControl, , EXCLUDE, 0
   GuiControl, , PAGEONLY, 0
}
Return
; ================================================================================================================================
; CtxDev menu
; ================================================================================================================================
CtxDevRegister:
Gui, Main: Default
Gui, ListView, Devices
LV_GetText(DevHandle, Selected, 1)
LV_GetText(DevType, Selected, 2)
LV_GetText(DevPage, Selected, 3)
LV_GetText(DevUsage, Selected, 4)
TypeStr := RI_RIM(DevType)
Gui, Register: New, +OwnerMain +HwndHREG, Register %TypeStr% Devices
Gui, Margin, 10, 10
Gui, Add, Text, xm, Usage Page:
Gui, Add, Edit, xm y+2 w400 vPage Disabled, % DevInfo.Page
Gui, Add, Text, xm, Usage:
Gui, Add, Edit, xm y+2 w400 vUsage Number, % DevInfo.Usage
Gui, Add, Text, xm, HWND:
Gui, Add, Edit, xm y+2 w400 vHWND, %HMAIN%
Gui, Add, Text, xm, Flags:
CheckBoxes := RI_RIDEV_ForType(DevType)
For Each, Flag In CheckBoxes {
   If (Flag = "DEFAULT") || (Flag = "REMOVE")
      Continue
   Gui, Add, CheckBox, v%Flag% gRegisterCheckFlags, %Flag%
}
Gui, Add, Button, xm w100 gRegisterApply, &Apply
Gui, Add, Button, xm+300 yp wp gRegisterGuiClose, &Cancel
Gui, Main: +Disabled
Gui, Register: Show
Return
; --------------------------------------------------------------------------------------------------------------------------------
CtxDevCopy:
Gui, Main: Default
Gui, +OwnDialogs
Gui, ListView, Devices
LV_GetText(DevType, Selected, 2)
LV_GetText(DevPage, Selected, 3)
LV_GetText(DevUsage, Selected, 4)
LV_GetText(DevName, Selected, 5)
Device := Format("Type: {:}`r`nPage: {:}`r`nUsage: {:}`r`nName: {:}", DevType, DevPage, DevUsage, DevName)
Clipboard := Device
MsgBox, 0, %A_ThisLabel%, Content of the selected row has been copied to the clipboard:`r`n`r`n%Device%
Return
; --------------------------------------------------------------------------------------------------------------------------------
CtxDevRefresh:
GoSub, MainRefreshDevices
Return
; ================================================================================================================================
; CtxInf menu
; ================================================================================================================================
CtxInfCopy:
Gui, Main: Default
Gui, +OwnDialogs
Gui, ListView, Info
Info := ""
Loop, % LV_GetCount() {
   LV_GetText(Key, A_Index, 1)
   LV_GetText(Val, A_Index, 2)
   Info .= (A_Index > 1 ? "`r`n" : "") . Key . ": " . Val
}
If (Info) {
   Clipboard := Info
   MsgBox, 0, %A_ThisLabel%, The content has been copied to the clipboard:`r`n`r`n%Info%
}
Return
; ================================================================================================================================
; CtxReg menu
; ================================================================================================================================
CtxRegUnregister:
Gui, Main: Default
Gui, ListView, Registered
LV_GetText(Page, Selected, 1)
LV_GetText(Usage, Selected, 2)
If !RI_UnRegisterDevices(Page, Usage) {
   MsgBox, 16, %A_ThisLabel%
         , Could not remove registered device!`nPage: %Page% - Usage: %Usage% - Flags: %Flags% Error: %A_LastError%
   Return
}
GoSub, MainRefreshRegistered
Return
; --------------------------------------------------------------------------------------------------------------------------------
CtxRegCopy:
Gui, ListView, Registered
LV_GetText(Page, Selected, 1)
LV_GetText(Usage, Selected, 2)
LV_GetText(Flags, Selected, 3)
Registered := "Page: " . Page . "`r`nUsage: " . Usage . "`r`nFlags: " . Flags
Clipboard := Registered
MsgBox, 0, %A_ThisLabel%, The content of the selected row has been copied to the clipboard:`r`n`r`n%Registered%
Return
; --------------------------------------------------------------------------------------------------------------------------------
CtxRegUnregisterAll:
GoSub, MainUnregisterAll
Return
; ================================================================================================================================
; CtxReg menu
; ================================================================================================================================
CtxRawClear:
Gui, Main: Default
Gui, ListView, RawInput
LV_Delete()
Return
; --------------------------------------------------------------------------------------------------------------------------------
CtxRawCopy:
Gui, Main: Default
Gui, ListView, RawInput
LV_GetText(Rawdata, Selected)
If (Rawdata) {
   Clipboard := Rawdata
   MsgBox, 0, %A_ThisLabel%, The content of the selected row has been copied to the clipboard:`r`n`r`n%Rawdata%
}
Return
; ================================================================================================================================
; Raw input message handlers
; ================================================================================================================================
OnRawInput(Type, RawInput, Msg, HWND) { ; WM_INPUT
   Gui, Main: Default
   Gui, ListView, RawInput
   If (InputObj := RI_GetData(RawInput)) {
      InputStr := ""
      For Each, Key In InputObj["*Keys"]
         InputStr .= (InputStr ? ", " : "") . Key . ": " . InputObj[Key]
      LV_Add("", InputStr)
   }
   Return DllCall("DefWindowProc", "Ptr", HWND, "UInt", Msg, "Ptr", Type, "Ptr", RawInput, "Ptr")
}
; --------------------------------------------------------------------------------------------------------------------------------
OnDevChange(Action, Handle) { ; WM_INPUT_DEVICE_CHANGE - Win Vista+
   Static GIDC := {0: "REMOVAL", 1: "ARRIVAL"}
   Critical
   ; MsgBox, 0, %A_ThisFunc%, % Format("Called with action {:} for device 0x{:X}.", GIDC[Action], Handle)
   Refresh := True
   If (Action = 1) { ; GIDC_ARRIVAL
      Gui, Main: Default
      Gui, ListView, RawInput
      Loop, % LV_GetCount {
         LV_GetText(DevHandle, A_Index)
         If (DevHandle = Handle)
            Refresh := False
      } Until (Refresh = False)
   }
   If (Refresh)
      SetTimer, MainRefreshDevices, -20
}
; ================================================================================================================================
#Include RI.ahk

RI.ahk (include):

Code: Select all

; ================================================================================================================================
; Raw Input
;     -> msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx
; RIDEV_... (Flag) constants
;     -> msdn.microsoft.com/en-us/library/windows/desktop/ms645565(v=vs.85).aspx
; RIM_TYPE... constants
;     -> msdn.microsoft.com/en-us/library/windows/desktop/ms645568(v=vs.85).aspx
; HID Clients Supported in Windows
;     -> docs.microsoft.com/en-us/windows-hardware/drivers/hid/hid-clients-supported-in-windows
; Top-Level Collections Opened by Windows for System Use
;     -> docs.microsoft.com/en-us/windows-hardware/drivers/hid/top-level-collections-opened-by-windows-for-system-use
; --------------------------------------------------------------------------------------------------------------------------------
; Some notes about RIDEV_... flags as a result of my testing on Win 10:
;     RIDEV_DEVNOTIFY and RIDEV_EXINPUTSINK require Win Vista+
;     Seemingly,
;        -  RIDEV_DEVNOTIFY can be used alone or combined with all other flags.
;           Apparently, the flag is stripped from the values returned by GetRegisteredRawInputDevices().
;     Also seemingly,
;        -  RIDEV_EXCLUDE, RIDEV_PAGEONLY, and RIDEV_NOLEGACY are exclusive and cannot be combined.
;           If you registered devices with RIDEV_PAGEONLY you must add this flag to RIDEV_REMOVE, too.
;        -  If both REDEV_INPUTSINK and RIDEV_EXINPUTSINK are specified RIDEV_EXINPUTSINK supersedes RIDEV_INPUTSINK.
;        -  RIDEV_APPKEYS is only valid for keyboard devices (Page: 1, Usage: 6) and requires RIDEV_NOLEGACY.
;        -  RIDEV_NOLEGACY, RIDEV_CAPTUREMOUSE, and RIDEV_NOHOTKEYS are only valid for keyboard/mouse devices
;           (Page: 1, Usage: 6/2). RIDEV_CAPTUREMOUSE and RIDEV_NOHOTKEYS share the same flag value 0x00000200.
;     Consider carefully testing raw input using the RIDEV_NOLEGACY flag. It prevents all normal keyboard/mouse notifications.
; ================================================================================================================================
; GetRawInputDeviceList() -> msdn.microsoft.com/en-us/library/windows/desktop/ms645598(v=vs.85).aspx
; On success, the function returns a simple array of objects containung the following key-value pairs:
;     Handle   -  The handle to the raw input device.
;     Type     -  The type of device: 0 = TYPEMOUSE, 1 = TYPEKEYBOARD, 2 = TYPEHID
;     Page     -  The top-level collection Usage Page for the device (always 1 for type 0 and 1).
;     Usage    -  The top-level collection Usage for the device (always 2 for type 0 and 6 for type 1).
;     Name     -  The name of the device.
; ================================================================================================================================
RI_GetDeviceList() {
   Static RIM := {0: "M", 1: "K", 2: "H"} ; RIM_TYPE...
   StructSize := A_PtrSize * 2 ; size of a RAWINPUTDEVICELIST structure
   DevCount := 0
   DllCall("GetRawInputDeviceList", "Ptr", 0, "UIntP", DevCount, "UInt", StructSize)
   If (DevCount) {
      VarSetCapacity(ListArr, StructSize * DevCount, 0) ; array of RAWINPUTDEVICELIST structures
      If (DllCall("GetRawInputDeviceList", "Ptr", &ListArr, "UIntP", DevCount, "UInt", StructSize, "Int") = DevCount) {
         DevObj := {Cnt: {H: 0, K: 0, M: 0, T: DevCount}, Lst: {}} ; Cnt = counters, Lst = device list
         Addr := &ListArr
         Loop, %DevCount% {
            DevType := NumGet(Addr + A_PtrSize, "UInt")
            DevHandle := Format("0x{:X}", NumGet(Addr + 0, "UPtr"))
            DevObj.Cnt[RIM[DevType]]++
            DevObj.Lst.Push({Handle: DevHandle, Type: DevType})
            Addr += StructSize
         }
         Return DevObj
      }
   }
   Return False
}
; ================================================================================================================================
; GetRawInputDeviceInfo() -> msdn.microsoft.com/en-us/library/windows/desktop/ms645597(v=vs.85).aspx
; On success, the dunction returns the name of the device.
; ================================================================================================================================
RI_GetDeviceName(DevHandle) {
   ; RIDI_DEVICENAME = 0x20000007
   DevName := ""
   Length := 0
   DllCall("GetRawInputDeviceInfo", "Ptr", DevHandle, "UInt", 0x20000007, "Ptr", 0, "UIntP", Length)
   If (Length) {
      VarSetCapacity(DevName, Length << !!A_IsUnicode, 0)
      DllCall("GetRawInputDeviceInfo", "Ptr", DevHandle, "UInt", 0x20000007, "Str", DevName, "UIntP", Length)
   }
   Return DevName
}
; ================================================================================================================================
; GetRawInputDeviceInfo() -> msdn.microsoft.com/en-us/library/windows/desktop/ms645597(v=vs.85).aspx
; On success, the function returns an object containing the following key-value pairs:
;     All devices:
;        DevType     -  The type of device: 0 = TYPEMOUSE, 1 = TYPEKEYBOARD, 2 = TYPEHID
;        Page        -  The top-level collection Usage Page for the device (always 1 for type 0 and 1).
;        Usage       -  The top-level collection Usage for the device (always 2 for type 0 and 6 for type 1).
;     Mouse devices (DevType = 0):
;        ID          -  The identifier of the mouse device.
;        Buttons     -  The number of buttons for the mouse.
;        Rate        -  The number of data points per second. This information may not be applicable for every mouse device.
;        HWheel      -  True if the mouse has a wheel for horizontal scrolling; otherwise, False (Win Vista+).
;     Keyboard devices (DevType = 1):
;        Type        -  The type of the keyboard.
;        SubType     -  The subtype of the keyboard.
;        ScanMode    -  The scan code mode.
;        FnKeys      -  The number of function keys on the keyboard.
;        Indicators  -  The number of LED indicators on the keyboard.
;        TotalKeys   -  The total number of keys on the keyboard.
;     HID devices (DevType = 2:
;        VendorID    -  The vendor identifier for the HID.
;        ProductID   -  The product identifier for the HID.
;        Version     -  The version number for the HID.
; ================================================================================================================================
RI_GetDeviceInfo(DevHandle) {
   ; RIDI_DEVICEINFO = 0x2000000B
   Static OSV := DllCall("GetVersion", "UChar")
   DevInfo := ""
   Length := 0
   DllCall("GetRawInputDeviceInfo", "Ptr", DevHandle, "UInt", 0x2000000B, "Ptr", 0, "UIntP", Length)
   If (Length) {
      VarSetCapacity(DevInfoBuffer, Length, 0)
      If (DllCall("GetRawInputDeviceInfo", "Ptr", DevHandle, "UInt", 0x2000000B, "Ptr", &DevInfoBuffer, "UIntP", Length) > 0) {
         DevType := NumGet(DevInfoBuffer, 4, "UInt")
         If (DevType = 0) {      ; RIM_TYPEMOUSE - for the mouse, the Usage Page is 1 and the Usage is 2.
            DevInfo := {DevType: DevType}
            DevInfo.ID := NumGet(DevInfoBuffer, 8, "UInt")
            DevInfo.Buttons := NumGet(DevInfoBuffer, 12, "UInt")
            DevInfo.Rate := NumGet(DevInfoBuffer, 16, "UInt")
            DevInfo.HWheel := OSV > 5 ? NumGet(DevInfoBuffer, 20, "UInt") : 0
            DevInfo.Page := 1
            DevInfo.Usage := 2
         }
         Else If (DevType = 1) { ; RIM_TYPEKEYBOARD - for the keyboard, the Usage Page is 1 and the Usage is 6.                                                 ;
            DevInfo := {DevType: DevType}
            DevInfo.Type := NumGet(DevInfoBuffer, 8, "UInt")
            DevInfo.SubType := NumGet(DevInfoBuffer, 12, "UInt")
            DevInfo.ScanMode := NumGet(DevInfoBuffer, 16, "UInt")
            DevInfo.FnKeys := NumGet(DevInfoBuffer, 20, "UInt")
            DevInfo.Indicators := NumGet(DevInfoBuffer, 24, "UInt")
            DevInfo.TotalKeys := NumGet(DevInfoBuffer, 28, "UInt")
            DevInfo.Page := 1
            DevInfo.Usage := 6
         }
         Else If (DevType = 2) { ; RIM_TYPEHID
            DevInfo := {DevType: DevType}
            DevInfo.VendorID := NumGet(DevInfoBuffer, 8, "UInt")
            DevInfo.ProductID := NumGet(DevInfoBuffer, 12, "UInt")
            DevInfo.Version := NumGet(DevInfoBuffer, 16, "UInt")
            DevInfo.Page := NumGet(DevInfoBuffer, 20, "UShort")
            DevInfo.Usage := NumGet(DevInfoBuffer, 22, "UShort")
         }
      }
   }
   Return DevInfo
}
; ================================================================================================================================
; GetRawInputData() -> msdn.microsoft.com/en-us/library/windows/desktop/ms645596(v=vs.85).aspx
; You must pass the lParam of the WM_INPUT message as the data handle.
; On success, the function returns an object containing the following key-value pairs:
;     All devices:
;        *Keys       -  A simple array containing the valid keys for this object.
;        DevType     -  The type of device: 0 = TYPEMOUSE, 1 = TYPEKEYBOARD, 2 = TYPEHID
;        Handle      -  The handle to the device generating the raw input data.
;        Param       -  The value passed in the wParam parameter of the WM_INPUT message.
;     Mouse devices (DevType = 0) -> msdn.microsoft.com/en-us/library/windows/desktop/ms645578(v=vs.85).aspx:
;        State       -  The mouse state.
;        BtnFlags    -  The transition state of the mouse buttons.
;        BtnData     -  If BtnFlags is RI_MOUSE_WHEEL, this member is a signed value that specifies the wheel delta.
;        RawBtns     -  The raw state of the mouse buttons.
;        LastX       -  The motion in the X direction, signed relative or absolute motion, depending on the value of State.
;        LastY       -  The motion in the Y direction, signed relative or absolute motion, depending on the value of State.
;        Extra       -  The device-specific additional information for the event.
;     Keyboard devices (DevType = 1) -> msdn.microsoft.com/en-us/library/windows/desktop/ms645575(v=vs.85).aspx:
;        SC          -  The scan code from the key depression.
;        Flags       -  Flags for scan code information.
;        VK          -  Windows message compatible virtual-key code.
;        Msg         -  The corresponding window message, for example WM_KEYDOWN, WM_SYSKEYDOWN, and so forth
;        Extra       -  The device-specific additional information for the event.
;     HID devices (DevType = 2) ->  msdn.microsoft.com/en-us/library/windows/desktop/ms645549(v=vs.85).aspx:
;        Size        -  The size, in bytes, of each HID input in Data.
;        Count       -  The number of HID inputs in Data.
;        Data        -  The raw input data, as hexadecial strings separated by one space.
; ================================================================================================================================
RI_GetData(Handle) {
   ; RID_INPUT = 0x10000003
   Static Keys := {0: ["DevType", "Handle", "Param", "State", "BtnFlags", "BtnData", "RawBtns", "LastX", "LastY", "Extra"]
                 , 1: ["DevType", "Handle", "Param", "SC", "Flags", "VK", "Msg", "Extra"]
                 , 2: ["DevType", "Handle", "Param", "Size", "Count", "Data"]}
   HdrSize := 8 + (A_PtrSize * 2)
   Size := 0
   DllCall("GetRawInputData", "Ptr", Handle, "UInt", 0x10000003, "Ptr", 0, "UIntP", Size, "UInt", HdrSize)
   If (Size) {
      VarSetCapacity(Data, Size, 0)
      If (DllCall("GetRawInputData", "Ptr", Handle, "UInt", 0x10000003, "Ptr", &Data, "UIntP", Size, "UInt", HdrSize) = Size) {
         DevType := NumGet(Data, 0, "UInt")
         DataObj := {}
         DataObj["*Keys"]   := Keys[DevType]
         DataObj["DevType"] := DevType
         DataObj["Handle"]  := NumGet(Data, 8, "UPtr")
         DataObj["Param"]   := NumGet(Data, 8 + A_PtrSize, "UPtr")
         DataAddr := &Data + HdrSize
         If (DevType = 0) { ; RIM_TYPEMOUSE
            DataObj["State"]    := Format("0x{:04X}", NumGet(DataAddr + 0, "UShort"))
            DataObj["BtnFlags"] := Format("0x{:04X}", NumGet(DataAddr + 4, "UShort"))
            DataObj["BtnData"]  := Format("0x{:04X}", NumGet(DataAddr + 6, "UShort"))
            DataObj["RawBtns"]  := Format("0x{:08X}", NumGet(DataAddr + 8, "UInt"))
            DataObj["LastX"]    := NumGet(DataAddr + 12, "Int")
            DataObj["LastY"]    := NumGet(DataAddr + 16, "Int")
            DataObj["Extra"]    := Format("0x{:08X}", NumGet(DataAddr + 20, "UInt"))
            Return DataObj
         }
         If (DevType = 1) { ; RIM_TYPEKEYBOARD
            DataObj["SC"]    := Format("{:03X}", NumGet(DataAddr + 0, "UShort"))
            DataObj["Flags"] := NumGet(DataAddr + 2, "UShort")
            DataObj["VK"]    := Format("{:02X}", NumGet(DataAddr + 6, "UShort"))
            DataObj["Msg"]   := Format("0x{:04X}", NumGet(DataAddr + 8, "UInt"))
            DataObj["Extra"] := Format("0x{:08X}", NumGet(DataAddr + 12, "UInt"))
            Return DataObj
         }
         If (DevType = 2) { ; RIM_TYPEHID
            SizeHID := NumGet(DataAddr + 0, "UInt")
            CountHID := NumGet(DataAddr + 4, "UInt")
            RawData := ""
            DataAddr += 8
            Loop, %CountHID% {
               Loop, %SizeHID%
                  RawData .= Format("{:02X}", NumGet(DataAddr++, "UChar"))
               RawData .= " "
            }
            DataObj["Size"]  := SizeHID
            DataObj["Count"] := CountHID
            DataObj["Data"]  := RTrim(RawData)
            Return DataObj
         }
      }
   }
   Return False
}
; ================================================================================================================================
; GetRegisteredRawInputDevices() -> msdn.microsoft.com/en-us/library/windows/desktop/ms645599(v=vs.85).aspx
; On success, the function returns a simple array of objects containing the following key-value pairs:
;     Page     -  The top-level collection Usage Page for the device (always 1 for type 0 and 1).
;     Usage    -  The top-level collection Usage for the device (always 2 for type 0 and 6 for type 1).
;     Flags    -  The mode flag that specifies how to interpret the information provided by Page and Usage.
;     HWND     -  The handle to the target window. If NULL it follows the keyboard focus.
; ================================================================================================================================
RI_GetRegisteredDevices() {
   StructSize := 8 + A_PtrSize ; size of a RAWINPUTDEVICE structure
   DevCount := 0
   DllCall("GetRegisteredRawInputDevices", "Ptr", 0, "UIntP", DevCount, "UInt", StructSize)
   If (DevCount) {
      VarSetCapacity(DevArr, StructSize * DevCount, 0) ; array of RAWINPUTDEVICE structures
      If (DllCall("GetRegisteredRawInputDevices", "Ptr", &DevArr, "UIntP", DevCount, "UInt", StructSize, "Int") = DevCount) {
         Registered := []
         Addr := &DevArr
         Loop, %DevCount% {
            Page  := NumGet(Addr + 0, "UShort")
            Usage := NumGet(Addr + 2, "UShort")
            Flags := Format("0x{:04X}", NumGet(Addr + 4, "UInt"))
            HWND  := NumGet(Addr + 8, "UPtr")
            Registered.Push({Flags: Flags, HWND: (HWND = 0 ? HWND : Format("0x{:X}", HWND)), Page: Page, Usage: Usage})
            Addr += StructSize
         }
         Return Registered
      }
   }
   Return False
}
; ================================================================================================================================
; RegisterRawInputDevices() -> msdn.microsoft.com/en-us/library/windows/desktop/ms645600(v=vs.85).aspx
; Surprisingly, it's not possible to register devices by handle!!!
; ================================================================================================================================
RI_RegisterDevices(Page, Usage, Flags := 0, HGUI := "") {
   Flags &= 0x3731 ; valid flags
   If Flags Is Not Integer
      Return False
   If (Flags & 0x01) ; for RIDEV_REMOVE you must call RI_UnRegisterDevices()
      Return False
   StructSize := 8 + A_PtrSize ; size of a RAWINPUTDEVICE structure
   ; Usage has to be zero in case of RIDEV_PAGEONLY, flags must include RIDEV_PAGEONLY if Usage is zero.
   If ((Flags & 0x30) = 0x20)
      Usage := 0
   Else If (Usage = 0)
      Flags |= 0x20
   ; HWND needs to be zero in case of RIDEV_EXCLUDE
   If ((Flags & 0x30) = 0x10)
      HGUI := 0
   Else If (HGUI = "")
      HGUI := A_ScriptHwnd
   VarSetCapacity(RID, StructSize, 0) ; RAWINPUTDEVICE structure
   NumPut(Page,  RID, 0, "UShort")
   NumPut(Usage, RID, 2, "UShort")
   NumPut(Flags, RID, 4, "UInt")
   NumPut(HGUI,  RID, 8, "Ptr")
   Return DllCall("RegisterRawInputDevices", "Ptr", &RID, "UInt", 1, "UInt", StructSize, "UInt")
}
; ================================================================================================================================
; RegisterRawInputDevices() -> msdn.microsoft.com/en-us/library/windows/desktop/ms645600(v=vs.85).aspx
; ================================================================================================================================
RI_UnRegisterDevices(Page, Usage) {
   StructSize := 8 + A_PtrSize ; size of a RAWINPUTDEVICE structure
   Flags := Usage = 0 ? 0x21 : 0x01
   VarSetCapacity(RID, StructSize, 0) ; RAWINPUTDEVICE structure
   NumPut(Page,  RID, 0, "UShort")
   NumPut(Usage, RID, 2, "UShort")
   NumPut(Flags, RID, 4, "UInt")
   Return DllCall("RegisterRawInputDevices", "Ptr", &RID, "UInt", 1, "UInt", StructSize, "UInt")
}
; ================================================================================================================================
; RIM_... constants -> msdn.microsoft.com/en-us/library/windows/desktop/ms645581(v=vs.85).aspx
; ================================================================================================================================
RI_RIM(DevType) {
   Static RIM := {0: "TYPEMOUSE", 1: "TYPEKEYBOARD", 2: "TYPEHID", TYPEHID: 2, TYPEKEYBOARD: 1, TYPEMOUSE: 0}
   Return RIM[DevType]
}
; ================================================================================================================================
; RIDEV_... constants -> msdn.microsoft.com/en-us/library/windows/desktop/ms645565(v=vs.85).aspx
; ================================================================================================================================
RI_RIDEV(Flag) {
   Static RIDEV := {APPKEYS:      0x0400 ; only valid for keyboard devices (Page: 1, Usage: 6)
                  , CAPTUREMOUSE: 0x0200 ; only valid for mouse devices (Page: 1, Usage: 2)
                  , DEFAULT:      0x0000
                  , DEVNOTIFY:    0x2000 ; Win Vista+
                  , EXCLUDE:      0x0010
                  , EXINPUTSINK:  0x1000 ; Win Vista+
                  , INPUTSINK:    0x0100
                  , NOHOTKEYS:    0x0200 ; only valid for keyboard devices (Page: 1, Usage: 6)
                  , NOLEGACY:     0x0030 ; not valid for HID devices
                  , PAGEONLY:     0x0020
                  , REMOVE:       0x0001}
   Return RIDEV[Flag]
}
; ================================================================================================================================
; RIDEV_... constants valid for the specied device type
; ================================================================================================================================
RI_RIDEV_ForType(DevType) {
   ; H = HID, K = Keyboard (Page: 1, Usage: 6), M = Mouse (Page: 1, Usage: 2)
   Static Types := {0: "M", 1: "K", 2: "H", TYPEHID: "H", TYPEKEYBOARD: "K", TYPEMOUSE: "M"}
   Static RIDEV := {H: ["DEFAULT", "DEVNOTIFY", "EXCLUDE", "EXINPUTSINK", "INPUTSINK", "PAGEONLY", "REMOVE"]
                  , K: ["APPKEYS", "DEFAULT", "DEVNOTIFY", "EXCLUDE", "EXINPUTSINK", "INPUTSINK", "NOHOTKEYS", "NOLEGACY"
                        , "PAGEONLY", "REMOVE"]
                  , M: ["CAPTUREMOUSE", "DEFAULT", "DEVNOTIFY", "EXCLUDE", "EXINPUTSINK", "INPUTSINK", "NOLEGACY", "PAGEONLY"
                        , "REMOVE"]}
   Return RIDEV[Types[DevType]]
}
Autohotkey1962
Posts: 5
Joined: 02 Jan 2020, 04:21

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 13:05

Erst mal allen Helfern und Helferinnen einen recht herzlichen Dank. Leider hilft keines der hier genannten Scripte oder Tipps.
Offenbar funktioniert die Übertragung der Befehle anderweitig.
Ich werde mal den Hersteller anschreiben, was man da machen kann.
So scheint es jedenfalls nicht zu funktionieren.
haichen
Posts: 303
Joined: 09 Feb 2014, 08:24

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 13:25

Was hast du denn für ein Gerät?
Autohotkey1962
Posts: 5
Joined: 02 Jan 2020, 04:21

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 14:12

Es ist ein speziell entwickeltes Soundsystem für Solokünstler, also kein Massenprodukt, sondern eine Sonderanfertigung eines Elektronikingenieurs in kleiner Anzahl und entsprechend kostspielig. Ich kann damit ohne Bühnentechniker mit einfachen Tastendrücken der Fernbedienung mit den Zehen den kompletten Sound steuern, so dass beide Hände frei sind für die Kunst.
Ich möchte das halt damit noch parallel dazu eine weitere Software steuern.
gregster
Posts: 3736
Joined: 30 Sep 2013, 06:48

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 14:34

Dann ist der Macher der Fernbedienung wahrscheinlich tatsächlich ein guter Ansprechpartner.

Wenn du "nur" Software parallel starten/stoppen willst, dann könnte man ggf das mitgelieferte Programm auf Änderungen in der GUI überwachen (ob hier sinnvoll 🤷‍♂️) und dann Aktionen in einer anderen Software auslösen (wobei eine kleine Verzögerung vielleicht schon ein großes Problem darstellen könnte - in diesem Anwendungsfall; vielleicht daher keine Lösung). Die Signale der Fernbedienung auszuwerten wäre wahrscheinlich wesentlich zuverlässiger.
Autohotkey1962
Posts: 5
Joined: 02 Jan 2020, 04:21

Re: Auslesen von Fernbedienungstasten

02 Jan 2020, 14:43

Na ja, ganz so einfach ist es nicht. Es geht nicht nur darum, ein Programm parallel zu starten und zu stoppen, sondern auch einzelne Funktionen aufzurufen. Das ist von der Sache her durchaus mit AHK möglich. Ich werde den Ingenieur mal ansprechen. Mal sehen, was da machbar ist.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: Bing [Bot] and 23 guests