Hi,
ich habe - größtenteils aus Langeweile - eine UDF geschrieben, die _IsPressed (GetAsyncKeyState) benutzt, aber wie HotKeySet (Oder sogar besser) zu benutzen ist.
Vorweg: Mir ist durchaus bewusst, dass durch das AdLibRegister unter Umständen Performanceeinbrüche entstehen können. Dafür ist ja SetCheckInterval da.
Funktionen:
_IsPressed_CallBackRegister
_IsPressed_CallBackUnRegisterOld
_IsPressed_CallBackUnRegister
_IsPressed_SetCheckInterval
Weitere Informationen zu den jeweiligen Funktionen finden sich wie gewohnt in den Funktionsheadern.
Hier mal kurz eine Liste der Features:
- Eventorientiert (UP, DOWN, UPDOWN)
- Erweiterte Unterstützung für Tastenkombinationen (Theoretisch bis zu X Tastendrücke gleichzeitig abfangbar (Rekursionslimit von AutoIt))
- Callbacks (Ordentlicher als If-Abfragen mit _IsPressed in der Hauptschleife...)
Die CallBack-Funktionen müssen 2 Parameter akzeptieren: Den Tastencode der gedrückten Taste im Hex-Format und das Event ($IPC_XXX).
Example ist aber zur Verdeutlichung auch dabei.^^
Es gibt noch einen wichtigen Bug:
Wenn mehrere Tasten gleichzeitig gedrückt werden (UPDOWN-Event registriert), und eine losgelassen wird, bekommen alle anderen gedrückten Tasten erst das Event $IPC_UP und direkt danach $IPC_DOWN!
Ich überlege, ob man evtl. mit der Timer-UDF arbeiten kann. Dann würde u.U. das Skript nicht mehr pausieren, wenn mehrere Tasten gedrückt sind...
Mal schauen. So funktioniert es jedenfalls erstmal.^^
IsPressedCallback.au3
#include <Array.au3>
Global $gaCallBacks[1][3]
Global $ghUser32 = DllOpen("user32.dll")
Global $giIntervalMS = 100
Global Enum $IPC_NORMAL, $IPC_DOWN, $IPC_UP, $IPC_DOWNUP
AdlibRegister("__IsPressed_CallBackHandler", $giIntervalMS)
OnAutoItExitRegister("__IsPressed_Shutdown")
; #FUNCTION# ====================================================================================================================
; Name ..........: _IsPressed_CallBackRegister
; Description ...: Register a new hotkey.
; Syntax ........: _IsPressed_CallBackRegister($sHexKey, $sCallBack, $iMethod)
; Parameters ....: $sHexKey - Keycode as hex, see _IsPressed
; $sCallBack - Callback function
; $iMethod - $IPC_NORMAL: Original _IsPressed
; - $IPC_DOWN: Fire event on key down
; - $IPC_UP: Fire event on key up
; - $IPC_DOWNUP or $IPC_DOWN + $IPC_UP: Fire event on key down and key up
; Return values .: An id to use with _IsPressed_CallBackUnRegister
; Author ........: chesstiger (AutoIt.de)
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: See "Example.au3"
; ===============================================================================================================================
Func _IsPressed_CallBackRegister($sHexKey, $sCallBack, $iMethod = 0)
$gaCallBacks[UBound($gaCallBacks) - 1][0] = $sHexKey
$gaCallBacks[UBound($gaCallBacks) - 1][1] = $sCallBack
$gaCallBacks[UBound($gaCallBacks) - 1][2] = $iMethod
ReDim $gaCallBacks[UBound($gaCallBacks) + 1][3]
Return UBound($gaCallBacks) - 2
EndFunc ;==>_IsPressed_CallBackRegister
; #FUNCTION# ====================================================================================================================
; Name ..........: _IsPressed_CallBackUnRegisterOld
; Description ...: Unregisters a hotkey by the hotkey code.
; Syntax ........: _IsPressed_CallBackUnRegisterOld($sHexKey)
; Parameters ....: $sHexKey - keycode as hex, like _IsPressed.
; Return values .: None
; Author ........: chesstiger
; Modified ......:
; Remarks .......: If you have two functions on one hotkey, this function will just remove one of them -> DEPRECATED
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _IsPressed_CallBackUnRegisterOld($sHexKey)
AdlibUnRegister("__IsPressed_CallBackHandler")
For $i = 0 To UBound($gaCallBacks) - 1 ;Find Match Index
If $gaCallBacks[$i][0] = $sHexKey Then
$iMatchIndex = $i
ExitLoop
EndIf
Next
For $i = $iMatchIndex To UBound($gaCallBacks) - 2
$gaCallBacks[$i][0] = $gaCallBacks[$i + 1][0]
$gaCallBacks[$i][1] = $gaCallBacks[$i + 1][1]
$gaCallBacks[$i][2] = $gaCallBacks[$i + 1][2]
Next
$gaCallBacks[UBound($gaCallBacks) - 2][0] = ""
$gaCallBacks[UBound($gaCallBacks) - 2][1] = ""
$gaCallBacks[UBound($gaCallBacks) - 2][2] = ""
ReDim $gaCallBacks[UBound($gaCallBacks) - 1][3]
AdlibRegister("__IsPressed_CallBackHandler", $giIntervalMS)
EndFunc ;==>_IsPressed_CallBackUnRegister
; #FUNCTION# ====================================================================================================================
; Name ..........: _IsPressed_CallBackUnRegister
; Description ...: Unregisters a hotkey.
; Syntax ........: _IsPressed_CallBackUnRegister($iHotkeyID)
; Parameters ....: $iHotkeyID - Return value of _IsPressed_CallBackRegister
; Return values .: None
; Author ........: chesstiger
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _IsPressed_CallBackUnRegister($iHotkeyID)
For $i = $iHotkeyID To UBound($gaCallBacks) - 2
$gaCallBacks[$i][0] = $gaCallBacks[$i + 1][0]
$gaCallBacks[$i][1] = $gaCallBacks[$i + 1][1]
$gaCallBacks[$i][2] = $gaCallBacks[$i + 1][2]
Next
ReDim $gaCallBacks[UBound($gaCallBacks) - 1][3]
EndFunc
; #FUNCTION# ====================================================================================================================
; Name ..........: _IsPressed_SetCheckInterval
; Description ...: Set the interval for hotkey checking.
; Syntax ........: _IsPressed_SetCheckInterval($iMS)
; Parameters ....: $iMS - Check interval time in MS
; Return values .: None
; Author ........: chesstiger
; Modified ......:
; Remarks .......: Do not use too small values. This will be CPU intensive.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _IsPressed_SetCheckInterval($iMS)
AdlibUnRegister("__IsPressed_CallBackHandler")
AdlibRegister("__IsPressed_CallBackHandler", $iMS)
$giIntervalMS = $iMS
EndFunc ;==>_IsPressed_SetCheckInterval
;INTERN
Func __IsPressed_CallBackHandler($aExcpHeader = 0) ;recursive
If Not IsDeclared("aExcpHeader") Then
Local $aExceptions[1]
Else
$aExceptions = $aExcpHeader
EndIf
For $i = 0 To UBound($gaCallBacks) - 1 ;Last element is always empty
$bSkip = False
For $iExcp = 1 To UBound($aExceptions) - 1 ;FEE
If $i = $aExceptions[$iExcp] Then
$bSkip = True
EndIf
Next
If __IsPressed($gaCallBacks[$i][0], $ghUser32) And Not $bSkip Then
Switch $gaCallBacks[$i][2]
Case $IPC_NORMAL ;Normal _IsPressed
Call($gaCallBacks[$i][1], $gaCallBacks[$i][0], $IPC_NORMAL)
Case $IPC_DOWN ;DOWN
Call($gaCallBacks[$i][1], $gaCallBacks[$i][0], $IPC_DOWN)
Do
Sleep(10)
Until Not __IsPressed($gaCallBacks[$i][0], $ghUser32)
Case $IPC_UP ;UP
Do
Sleep(10)
Until Not __IsPressed($gaCallBacks[$i][0], $ghUser32)
Call($gaCallBacks[$i][1], $gaCallBacks[$i][0], $IPC_UP)
Case $IPC_DOWN + $IPC_UP
$iLastItem = _ArrayAdd($aExceptions, $i)
Call($gaCallBacks[$i][1], $gaCallBacks[$i][0], $IPC_DOWN)
$iRemoveCallback = _IsPressed_CallBackRegister($gaCallBacks[$i][0], $gaCallBacks[$i][1], $IPC_UP)
$iUpItem = _ArrayAdd($aExceptions, UBound($gaCallBacks) - 2)
While __IsPressed_CallBackHandler($aExceptions) <> 5
Sleep($giIntervalMS)
WEnd
Call($gaCallBacks[$i][1], $gaCallBacks[$i][0], $IPC_UP)
_ArrayDelete($gaCallBacks, $iRemoveCallback)
_ArrayDelete($aExceptions, $iUpItem)
_ArrayDelete($aExceptions, $iLastItem)
EndSwitch
EndIf
If Not __IsPressed($gaCallBacks[$i][0], $ghUser32) And $bSkip Then
Return 5
EndIf
Next
EndFunc ;==>__IsPressed_CallBackHandler
;INTERN
Func __IsPressed_Shutdown()
DllClose($ghUser32)
EndFunc ;==>__IsPressed_Shutdown
Func __IsPressed($sHexKey, $vDLL = 'user32.dll')
; From Misc.au3 by ezzetabi and Jon
; For function header see Misc.au3
Local $a_R = DllCall($vDLL, "short", "GetAsyncKeyState", "int", '0x' & $sHexKey)
If @error Then Return SetError(@error, @extended, False)
Return BitAND($a_R[0], 0x8000) <> 0
EndFunc ;==>__IsPressed
Example
#include "IsPressedCallback.au3"
#include <GDIPlus.au3>
Local $aKeycodes[6] = ["51", "57", "45", "52", "54", "5A"] ;QWERTZ
Local $aKeynames[6] = ["Q", "W", "E", "R", "T", "Z"] ;QWERTZ
Local $iPressColor = 0xff0000ff
Local $iReleaseColor = 0xffff0000
_GDIPlus_Startup()
Opt("GUIOnEventMode", True)
Opt("TrayIconDebug", True)
$hGUI = GUICreate("QWERTZ-Keyboard", 50 * 6, 50)
GUISetOnEvent(-3, "_Exit")
GUISetState()
;GDI+ Init
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBufferBMP = _GDIPlus_BitmapCreateFromGraphics(50 * 6, 50, $hGraphics)
$hBuffer = _GDIPlus_ImageGetGraphicsContext($hBufferBMP)
Local $aBrushes[UBound($aKeycodes)]
[/autoit] [autoit][/autoit] [autoit]For $i = 0 To UBound($aKeycodes) - 1
$aBrushes[$i] = _GDIPlus_BrushCreateSolid($iReleaseColor)
_IsPressed_CallbackRegister($aKeycodes[$i], "_ChangeColor", $IPC_DOWN + $IPC_UP)
Next
While True
_Draw()
WEnd
Func _ChangeColor($sKey, $iEvent)
Switch $iEvent
Case $IPC_DOWN
$iNewColor = $iPressColor
Case $IPC_UP
$iNewColor = $iReleaseColor
EndSwitch
For $i = 0 To UBound($aKeycodes) - 1
If $sKey = $aKeycodes[$i] Then
_GDIPlus_BrushSetSolidColor($aBrushes[$i], $iNewColor)
EndIf
Next
_Draw()
EndFunc ;==>_ChangeColor
Func _Draw()
_GDIPlus_GraphicsClear($hBuffer, 0xffffffff)
For $i = 0 To UBound($aKeycodes) - 1
_GDIPlus_GraphicsFillRect($hBuffer, 50 * $i, 0, 50, 50, $aBrushes[$i])
_GDIPlus_GraphicsDrawString($hBuffer, $aKeynames[$i], 50 * $i, 0, "Arial", 34)
Next
_GDIPlus_GraphicsDrawImageRect($hGraphics, $hBufferBMP, 0, 0, 50 * 6, 50)
EndFunc ;==>_Draw
Func _Exit()
_GDIPlus_DisposeAll()
_GDIPlus_Shutdown()
Exit
EndFunc ;==>_Exit
Func _GDIPlus_DisposeAll()
;Common GDI+ Dispose Function created by CleanGDI+.au3
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_BitmapDispose($hBufferBMP)
_GDIPlus_GraphicsDispose($hBuffer)
For $i = 0 To UBound($aBrushes) - 1
_GDIPlus_BrushDispose($aBrushes[$i])
Next
EndFunc ;==>_GDIPlus_DisposeAll
lg