1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. ArminLinder

Beiträge von ArminLinder

  • DllStructGetPtr ... Speicher-Dump schlägt fehl

    • ArminLinder
    • 9. Mai 2019 um 13:44

    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

    Code
    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

    C
    #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

  • DllStructGetPtr ... Speicher-Dump schlägt fehl

    • ArminLinder
    • 8. Mai 2019 um 23:12

    Noch schnell: ja, die Werte sind jetzt alle hex, damit ich direkt mit der MS-Doku zu den VKCodes arbeiten kann, ohne jedes Mal Hex in Dec umrechnen zu müssen.

    Für heute habe ich schon Schluss gemacht, die Entwicklungsanlage ist bereits aus ... aber ich poste morgen früh das geänderte Script. Ich schwöre, es hat genau die Werte ausgespuckt, und Du siehst ja in der letzten ausgegebenen Zeile genaud as was TounicodeEx ausgibt: das korrekte "@" Zeichen, wenn ich AltGr-q simuliere.

    Das mit der 129 hat ebenfalls seine Richtigkeit: in der MS Doku steht, man müsse für eine gedrückte taste das HOB setzen, also 128. Das LOB, das ebenfalls eine (nicht näher beleuchtete) Funktionalität hat, werde, so steht es da, ignoriert. Wird es wohl nicht, denn wenn ich 0x80 statt 0x81 setze bekomme ich statt "@" ein kleines "q" zurück. Ich muss das LOB setzen, sonst tut sich nichts.

    ---------------------

    Eventuell hast Du auch noch eine schnelle Antwort zu einem Problem, an dem ich morgen kauen wollte: es wäre natürlich angesagt, wenn ich schon am KeyboardState herumpatche, den ursprünglichen State wiederherzustellen. Da gäbe es jetzt 3 Wege:

    - wenn das was $kbdState = DllStructGetPtr(_WinAPI_GetKeyboardState()) zurückbringt sowieso nur ein Pointer auf eine lokale Speicherstruktur ist, ist alles gut, ich kann die Werte getrost vergessen weil sie beim nächsten Mal sowieso neu gesetzt werden.

    - wenn das aber ein Pointer auf eine Windows Struktur ist, wenn ich also permanent etwas verändere auf das auch andere Windows Prozesse zugreifen, wäre das eher nicht gut. und ...

    - ich müsste herausfinden, wie ich eine lokale Kopie dieser Struktur anlege, die ich dann verändern und in den ToUnicodeEx Aufruf stopfen kann.

    Ob es reicht, einfach $temp = $tKeyboardState setzen um eine lokale Kopie zu erzeugen wollte ich erst mal erforschen, viele Systeme würden das als Befehl, den Pointer zu kopieren sehen, und das wäre nichtd as was ich möchte. Ich brauche eine unabhängige Kopie der gesamten Struktur.

    Ich habe bereits heute Nachmittag ein paar Seiten in der AutoIt Doku durchgeackert, bin aber unterbrochen worden und war mir am Ende noch nicht ganz schlüssig, wie das alles zusammenhängt.

    Vielleicht weißt Du es einfach so aus dem Stand?

    Gute Nacht,

    Armin.

  • DllStructGetPtr ... Speicher-Dump schlägt fehl

    • ArminLinder
    • 8. Mai 2019 um 15:12

    Klappt! Ich bin blass begeistert, und danke Dir herzlich für die Hilfe!

    Die Dump-Routine hat sich übrigens bewährt, mit der MS Doku alleine käme man nicht weit.

    Da das Array, das GetKeyboardState zurückbringt, 0-basiert ist während DLLStructSetData Arrays immer 1-basiert behandelt, muss ich zum VK Code eins dazuzählen, um den richtigen Wert zu setzen

    Einige Erkenntnise:

    - ich muss statt der 0x80 eine 0x81 setzen, damit das richtige Zeichen zurückkommt. In der MS Doku steht, es ist egal...

    Code
    DLLStructSetData($tKeyboardState, 1, 0x81, $VK_CAPITAL + 1)

    Das setzt die Hochstelltaste. Erst einmal habe ich versucht, VK_LSHIFT oder VK_RSHIFT zu setzen, das hat aber nicht geklappt.

    Um den Code für Alt-Gr zu bekommen, z.B. für den Klammeraffen, muss ich Alt-Control und den Tastencode (q = 0x10/0x51) setzen. Auf VK_RMENU reagiert die ToUnicodeEx Function nicht, genausoi wie es auf VK_LSHIFT und VK_RSHIFT nicht reagiert.:

    Code
    ; Alt-Gr
    DLLStructSetData($tKeyboardState, 1, 0x81, $VK_CONTROL + 1)
    DLLStructSetData($tKeyboardState, 1, 0x81, $VK_MENU + 1)
    
    Dump of DLLStruct Keyboard State
    ---------------!-------------------------------------
    [ 0]  0  0  0  0  0  0  0  0  1  1  0  0  0  0  0  0
    [10]  0 81 81  0  0  0  0  0  0  0  0  0  0  0  0  0
    [20]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [30]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [40]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [50]  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [60]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [70]  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0
    [80]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [90]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [a0]  0  0  1  0  0  1  0  0  0  0  0  0  0  0  0  0
    [b0]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [c0]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [d0]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [e0]  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
    [f0]  1  0  0  1  0  0  1  0  0  0  0  1  0  0  0  0
    
    1 ScanCode: 0x10	vkCode: 0x51 [@]
    Alles anzeigen
  • DllStructGetPtr ... Speicher-Dump schlägt fehl

    • ArminLinder
    • 8. Mai 2019 um 11:36

    Schaut gut aus, vielen Dank, ich probiere es gleich aus!

  • DllStructGetPtr ... Speicher-Dump schlägt fehl

    • ArminLinder
    • 7. Mai 2019 um 18:43

    Gerne! Da das Gesamtprojekt doch etwas größer ist, habe ich einen Teil herausgetrennt, der das Problem zeigt.

    C
    #include <WinAPIConstants.au3>
    #include <WinAPISys.au3>
    #include <WinAPIvkeysConstants.au3>
    
    Local $vkCode = 0x31        ; VK_Code der "1"
    Local $ScanCode = 0x02        ; testennumemr auf dem PC Keyboard
    Local $kbdState = DllStructGetPtr(_WinAPI_GetKeyboardState())
    DLLStructSetData($kbdState,1,0x80,$VK_LSHIFT)
    DumpDLLArray($kbdState,256,"Keyboard State",1)
    Local $Result = ""
    Local $ret=_User32_ToUnicodeEx($vkCode, $scanCode, $kbdState , $Result, 5,0, _WinAPI_GetKeyboardLayout(_WinAPI_GetDesktopWindow ( )))
    If $ret > 0 Then
       ConsoleWrite("ScanCode - " & $scanCode & @TAB & "vkCode - " & $vkCode & " [" & $Result &"]" & @CRLF)
    EndIF
    
    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("Dump of " & VarGetType($Array) & " " & $NameOfArray & @CRLF)
       ConsoleWrite("-------------------------------" & @CRLF)
       For $i = 1 to $LengthOfArray
          If MOD($i,16) = 1 then
             ConsoleWrite(StringFormat("[%4d]",$i))
          EndIf
          ConsoleWrite(StringFormat("%4s",DllStructGetData($Array,$ElementNumber,$i)))
          If MOD($i,16) = 0 then
             ConsoleWrite(@CRLF)
          EndIf
       Next
       ConsoleWrite(@CRLF)
    endfunc
    Alles anzeigen

    Problem 1: DumpDLLArray hat ein Problem, da es BEIM dUMP VON $kbdState 256 Nullwerte ausgibt. Es muss aber mindestens 3 Werte <> 0 geben, da ich in der Zeile vorher ja einen zu setzen versuche, und auzßerdem bevor ich das Scriupt gestartet habe Caps-Lock nd Num-Lock aktiviert habe. Selbst wenn mein Versuch, DLLStructSetData zu verwenden, irgendwie faul gewesen wäre, müssten noch die Bytes VK_CAPITAL (0x14) und VK_NUMLOCK (0x90) den Wert 0x80 haben. Der Dump sagt, haben sie nicht, aber die Konsole sagt,:


    Code
    Dump of Ptr Keyboard State
    -------------------------------
    [   1]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [  17]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [  33]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [  49]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [  65]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [  81]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [  97]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 113]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 129]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 145]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 161]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 177]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 193]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 209]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 225]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [ 241]   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    
    ScanCode - 2    vkCode - 49 [!]
    Alles anzeigen

    Du siehst am [!] dass die Umwandlung prinzipiell funktioniert hat (weil Capslock aktiviert war). Ich bin also nicht allzu weit vom Ziel entfernt. Erreicht wäre es, wenn ich Capslock deaktiveren kann,

    Code
    DLLStructSetData($kbdState,1,0x80,$VK_LSHIFT)

    sollte ja dasselbe bewirken, indem es in der Keyboard State Map das Flag für Links-Shift-Down einträgt, und dann die veränderte Map in den Aufruf von toUnicodeEx stopfe.

    So lese ich jedenfalls die Doku: https://docs.microsoft.com/en-us/windows/…etkeyboardstate

    Die zur Suche nach dem eigentlichen Fehler gedachte Dump Routine tut,d as ist denke ich bewiesen, nicht so wie ich es haben wollte, ich finde ums verr**** keinen Fehler, und wenn ich herausfinden kann, was bei ihr faul ist bin ich schon mal einen Schritt weiter weil ich dann everntuell sehen kann, was beim DLLStructSetData Aufruf mit der Struktur passiert.

    Armin.

  • DllStructGetPtr ... Speicher-Dump schlägt fehl

    • ArminLinder
    • 7. Mai 2019 um 16:32
    Code
    Local $kbdState = DllStructGetPtr(_WinAPI_GetKeyboardState())

    Ich möchte herausbekommen, welches UTF-8 Zeichen eine Windows Applikation sieht, wenn eine bestimmte Taste (gegeben durch den Hardware-Scan Code) gedrückt wird, zusätzlich möglicherweise auch noch eine Umschalttaste wie [Shift], [Alt-Gr] usw. Im Prinzip möchte ich alle Scan-Codes einer PC Tastatur in die Routine stopfen können, und danach die Tastenbelegungen verschiedener länderspezifischer Tastaturen im Klartext ausgeben.

    Problem: PC Tastaturen schicken nur einen Scan-Code, der je nach Windows Gebietsschema-Einstellung in einen Windows Code (Virtual Key Code) umgewandelt wird.

    Die Umwandlung Scancode zu Virtual Key Code habe ich soweit im Griff:

    Code
    Local $kbdState = DllStructGetPtr(_WinAPI_GetKeyboardState())
    ; DLLStructSetData($kbdState,1,0x80,$VK_LSHIFT)
    DumpDLLArray($kbdState,256,"Keyboard State",1)
    _User32_ToUnicodeEx($vkCode, $scanCode, $kbdState , $Result, 5,0, _WinAPI_GetKeyboardLayout(_WinAPI_GetDesktopWindow ( )))
    
    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("Dump of " & VarGetType($Array) & " " & $NameOfArray & @CRLF)
       ConsoleWrite("-------------------------------" & @CRLF)
       For $i = 1 to $LengthOfArray
          If MOD($i,16) = 1 then
             ConsoleWrite(StringFormat("[%4d]",$i))
          EndIf
          ConsoleWrite(StringFormat("%4s",DllStructGetData($Array,$ElementNumber,$i)))
          If MOD($i,16) = 0 then
             ConsoleWrite(@CRLF)
          EndIf
       Next
       ConsoleWrite(@CRLF)
    endfunc
    Alles anzeigen

    Im Aufruf von

    Code
    _WinAPI_GetKeyboardLayout()

    habe ich der EInfachheit halber im Moment die eigene Tastatur (Layout Deutsch) stehen, aber ich habe auch schon Code der eine andere länderspezifische Tastatur laden kann --> Problem zur Hälfte gelöst.

    Nun woillte ich noch verschiedene Modifier (Alt, Shift, Alt-gr) mitgeben um die Zweit- und Drittbelegungen der Tasten zu bekommen, und das will mir nicht gelingen.

    Es gelingt mir auch nicht, das $kbdState Array in die Konsole zu schreiben, ich bekomme immer 256 Nullwerte, obwohl ich am zurückgegebenen vkCode sehen kann, dass die Umwandung von z.B. Shift-1 in "!" geklappt hat. Natürlich rührt sich auch nichts, wenn ich versuche, Werte in $kbdState selber zu setzen, also z.B. die linke Shift-Taste per Programm zu drücken (die auskommentierte Zeile). Da aber auch dann die Funktion DumpDLLArray nur Nullen ausgibt habe ich vermutlich zwei Fehler, die ich ums ver***** nicht finden kann: das Setzend es Wertes mit DLLStructSetData schlägt irgendwie fehl, und abgesehen davon stehen in dem kbdState Array sowieso nicht die Statuswerte drinnen die ich lt. Microsoft Doku dort erwartet hätte, oder ich bin zu doof die richtigen Werte in die Konsole zu schreiben. Aktiviere ich z.B. Caps-Lock, müsste mindestens ein Byte <> 0 auftauchen, tut es aber nicht. :cursing:

    Wer kann mir einen Tipp geben wod er Wurm steckt?

    Thx, Armin

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™