keycodes per sendmessage schicken

01/11/2009 12:58 tonitusch666#1
Hallo,

also ich wollte das ControlSend für einfache Fälle durch nen user32.dll call ersetzen, da grad das shift, alt, control handling etwas speziell ist (und ichs auch nicht brauch).

EDIT: ok knapp vorbei ist halt auch daneben, hab jetzt im AutoIt source gespickt und dabei noch gelernt, dass es naben Vk noch scancode gibt und das ist nicht immer der gleiche Wert...

Code:
Func KeySend($inkey, $evt ="pressed")
	$user32 = DllOpen("user32.dll")
	if $user32 = -1 Then
		ConsoleWrite("KeySend: cannot open user32.dll")
		Exit
	EndIf
	
	$WM_KEYDOWN = 0x100
	$WM_KEYUP   = 0x101

	If StringUpper($inkey) = "RETURN" Then
		$skey = 0x0D
	ElseIf StringUpper($inkey) = "SPACE" Then
		$skey = 0x20
	Else
		$key = DllCall($user32, "int", "VkKeyScan", "int", Asc(StringLower($inkey)))
		$skey = $key[0]
	EndIf
	$ret = DllCall($user32, "int", "MapVirtualKey", "int", $skey, "int", 0)
	$lparam = BitShift($ret[0], -16)
	$lparam = BitOr($lparam, 1)
	
	Select
	Case $evt = "pressed"
		DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", $skey, "int", $lparam)
		Sleep(15)
		DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYUP, "int", $skey, "int",   BitOR($lparam, 0xC0000000))
	Case $evt = "down"
		DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", $skey, "int", $lparam)
	Case $evt = "up"
		DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYUP, "int", $skey, "int",   BitOR($lparam, 0xC0000000))
	EndSelect

	DllClose($user32)
EndFunc
So klappt es jetzt für einfache Anwendungen...

mfg
01/11/2009 13:28 blauwiggle#2
Da hab ich auch schon im AutoIT.de Forum nachgefragt ... . Mal schauen was die klugen Leute dort rausfinden.
01/11/2009 20:05 tonitusch666#3
gelöst, siehe oben :)
01/12/2009 06:05 blauwiggle#4
Hmm, funktioniert denn damit ein '@' bzw. wie könnte man denn noch ein @ machen? ^^
01/12/2009 16:46 Gabba2#5
Ja das geht da müsst dann aber denke ich den ASCII Code manuell dir raussuchen (64 für @) oder gibt es in AutoIT eine Möglichkeit sich direkt den ASCII für zB. {space} sich ausgeben zu lassen?
01/12/2009 20:33 tonitusch666#6
Jo also aktueller Stand s.o., also alles für das es einen VKEY definiert gibt, kann man so einfach lösen. Das sleep(xx) ist notwendig damit die msg Reihenfolge passt, da WM_KEYDOWN zerlegt wird in eine KEYDOWN und eine CHAR msg. Wenn man den sleep weglässt geht es für single events, jedoch kann man nicht in textinput felder senden, da dann der CHAR erst nach dem UP kommt. Das dürfte dem keydowndelay entsprechen, muss man probieren, ob das schon so passt für jeden Rechner/Windows.
01/16/2009 00:10 tonitusch666#7
Also hab jetzt nochmal probiert, ob man so was wie CTRL+ALT+q = @ schicken kann, habs aber nicht hinbekommen. Hab dann noch mit WM_SYSKEYDOWN experimentiert, hat aber auch nicht geklappt. Alle Lösungen die scheinbar funktioneren (so wie AutoIt das macht) modifizieren die KeyBoardState Struktur und schreiben sie danach wieder zurück. In dem
Moment wo die verbogen ist, wirkt sich das auch auf den normalen Keyboard Input aus und dadurch ensteht diese "lustige" Groß-/Kleinschreibung.
Beim testen mit dem @ über ControlSend() ist mir allerdings eine spannende Sache aufgefallen, nämlich dass es das als ASCII Zeichen gibt 0x40 und Autoit interessanter Weise das gar nicht als CTRL-ALT q verschickt sonder als char code 0x40, daraus ist nun folgende Lösung entstanden mit der ich meine e-mail adresse testhalber in den chat window geschickt habe:
Code:
$skey = 0x40
$lparam = 0x00100001
DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYDOWN, "int", 0x71, "int", $lparam)
DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_CHAR, "int", $skey, "int", $lparam)
Sleep(20)
DllCall($user32, "int", "PostMessage", "hwnd", $hwnd, "int", $WM_KEYUP, "int", 0x71, "int", BitOR($lparam, 0xC0000000))
mfg