Ok, bin wieder da. Ich habe das Testprogramm ein wenig umgestrickt, aber die zentralen Routinen sind gleich geblieben.
Hier erst mal die Ausgaben: es klappt alles wunderbar. Getestet werden jewils:
- die Taste
- die Taste mit Shift
- die Taste mit Alt + Ctrl (= Alt-Gr)
- die Taste mit VK_LSHIFT (tut nicht)
- die Taste mit VK_RMENU (was laut MS Doku Alt-Gr sein soll - tut nicht)
Wichtig sind mir also nur die ersten drei Zeilen, und da schauts m.E. sehr gut aus
Testing: Taste [1 !]
Scancode: 0x 2 VirtualkeyCode: 0x31 [1]
Scancode: 0x 2 VirtualkeyCode: 0x31 [!]
Scancode: 0x 2 VirtualkeyCode: 0x31 failed with code: 0
Scancode: 0x 2 VirtualkeyCode: 0x31 [1]
Scancode: 0x 2 VirtualkeyCode: 0x31 [1]
Done.
Testing: Taste [q @]
Scancode: 0x a VirtualkeyCode: 0x51 [q]
Scancode: 0x a VirtualkeyCode: 0x51 [Q]
Scancode: 0x a VirtualkeyCode: 0x51 [@]
Scancode: 0x a VirtualkeyCode: 0x51 [q]
Scancode: 0x a VirtualkeyCode: 0x51 [q]
Done.
Testing: Taste [ß ? /]
Scancode: 0x c VirtualkeyCode: 0xdb [ß]
Scancode: 0x c VirtualkeyCode: 0xdb [?]
Scancode: 0x c VirtualkeyCode: 0xdb [\]
Scancode: 0x c VirtualkeyCode: 0xdb [ß]
Scancode: 0x c VirtualkeyCode: 0xdb [ß]
Done.
>Exit code: 0 Time: 0.4125
Alles anzeigen
Der Code
#include <WinAPIConstants.au3>
#include <WinAPISys.au3>
#include <WinAPIvkeysConstants.au3>
#include <Array.au3>
Global Const $stateON = 0x81
TestAllCharacterMappings(0x31,0x02,"Taste [1 !]")
TestAllCharacterMappings(0x51,0x0A,"Taste [q @]")
TestAllCharacterMappings(0xDB,0x0C,"Taste [ß ? /]")
;Todo: Dead keys
;TestAllCharacterMappings(0xDC,0x29,"Taste [^]")
;TestAllCharacterMappings(0x41,0x1E,"Taste [a]")
Func TestAllCharacterMappings($VkCode,$ScanCode,$sCaption)
ConsoleWrite("Testing: " & $sCaption & @CRLF)
TestCharacterMapping($vkCode,$scanCode)
TestCharacterMapping($vkCode,$scanCode,ToArray($VK_CAPITAL))
TestCharacterMapping($vkCode,$scanCode,ToArray($VK_MENU, $VK_CONTROL))
TestCharacterMapping($vkCode,$scanCode,ToArray($VK_LSHIFT)) ; schlägt immer fehl
TestCharacterMapping($vkCode,$scanCode,ToArray($VK_RMENU)) ; schlägt immer fehl
ConsoleWrite("Done." & @CRLF)
EndFunc
Func TestCharacterMapping($VkCode,$ScanCode,$ArrVkModifiers = NULL])
; set the modifiers
Local $tKeyboardState = _WinAPI_GetKeyboardState()
If IsArray($ArrVkModifiers) Then
for $i = 0 to UBound($ArrVkModifiers) - 1
DLLStructSetData($tKeyboardState, 1, $StateON, $ArrVkModifiers[$i] + 1)
Next
EndIf
; DumpDLLArray($tKeyboardState,256,"Keyboard State")
; do the conversion
Local $keyBuffer = ""
Local $result = _User32_ToUnicodeEx($VkCode, $ScanCode, DllStructGetPtr($tKeyboardState) , $keyBuffer, 5,0, _WinAPI_GetKeyboardLayout(_WinAPI_GetDesktopWindow()))
ConsoleWrite(" Scancode: " & StringFormat("0x%2x",$ScanCode) & " VirtualkeyCode: " & StringFormat("0x%2x",$VkCode))
if $result > 0 then
ConsoleWrite(" [" & $keyBuffer & "]" & @CRLF)
Else
ConsoleWrite(" failed with code: " & $result & @CRLF)
endif
EndFunc
Func _User32_ToUnicodeEx($wVirtKey, $wScanCode, $lpKeyState, ByRef $pwszBuff, $cchBuff, $wFlags, $dwhkl)
Local $vRetVal = DllCall("user32.dll", "int", "ToUnicodeEx", "UINT", $wVirtKey, "UINT", $wScanCode, "ptr", $lpKeyState, "wstr", $pwszBuff, "int", $cchBuff, "UINT", $wFlags, "hwnd", $dwhkl)
$pwszBuff = $vRetVal[4]
Return $vRetVal[0]
EndFunc
Func DumpDLLArray($Array,$LengthOfArray,$NameOfArray,$ElementNumber = 1)
ConsoleWrite("Hex Dump of " & VarGetType($Array) & " " & $NameOfArray & @CRLF)
ConsoleWrite("------------------!-------------------------------------" & @CRLF)
For $i = 1 to $LengthOfArray
If MOD($i,16) = 1 then
ConsoleWrite(StringFormat("[%2x]",$i - 1))
EndIf
ConsoleWrite(StringFormat("%3x",DllStructGetData($Array,$ElementNumber,$i)))
If MOD($i,16) = 0 then
ConsoleWrite(@CRLF)
EndIf
Next
ConsoleWrite(@CRLF)
endfunc
Func ToArray($am0 = NULL, $am1 = NULL, $am2 = NULL, $am3 = NULL, $am4 = NULL, $am5 = NULL, $am6 = NULL, $am7 = NULL, $am8 = NULL, $am9 = NULL)
Local $result[] = [0]
_ArrayDelete($result,0) ; :-(
for $i = 0 to 9
If Eval("am" & $i) then _ArrayAdd($result,Eval("am" & $i))
Next
Return $result
EndFunc
Alles anzeigen
Ändere ich die Deifnition von $StateON auf 0x80, klappt nix mehr.
Das Einzige was man noch verbessern kann, wäre den Fall $result = -1 (dead Key) zu behandeln. Da ich das aber für meine Aufgabe nicht brauche, schenke ich es mir.
------
Deinen Hinweis auf "fahrlässigen Umgang mit Variablen" habe ich ernst genommen und im Rahmen meiner AutoIt Kenntnisse überdacht, finde aber beim konkreten Code nichts dabei, ihn so zu schreiben. Das direkte Übergeben von Funktionsresultaten als Parameter ist m.E. ein absoluter Standard, sollte ein Interpreter damit nicht zurecht kommen würde ich das als gravierenden Mangel betrachten. Wo genau siehst Du hier kokretes Potenzial, dass die interne Optimierung mir irgendwo dazwischen funkt?
HG, Armin