Doppelklick als Event abfragen

    • Offizieller Beitrag

    Hi,

    ich habe nach einer Lösung gesucht auch für Controls, die keine Msg bei Doppelklick abgeben (wie z.B. Inputs) dieses Ereignis direkt auswertbar zu machen.
    Natürlich sollte es allgemeingültig sein und nicht mit anderen Messages kollidieren. Entstanden ist diese UDF: "DoubleClick_Event.au3"

    Nach dem Erstellen eines Controls wird mit der Funktion _GUI_DoubleClick_Register($_hGui, $_cCtrl) dieses Control für den Doppelklick registriert und ein Dummy-Control zurückgegeben, das bei Doppelklick auf das registrierte Control aus der UDF heraus "befeuert" wird und per GuiGetMsg() oder GUICtrlSetOnEvent() abgefragt werden kann.
    Es können Controls auf verschiedenen GUI registriert werden.

    DoubleClick_Event.au3 (v0.1)
    [autoit]

    #Region - TimeStamp
    ; 2013-03-09 19:53:02 v 0.1
    #EndRegion - TimeStamp

    [/autoit] [autoit][/autoit] [autoit]

    #include-once
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>
    OnAutoItExitRegister('OnAutoItExit')

    [/autoit] [autoit][/autoit] [autoit]

    Global Const $HC_ACTION = 0
    Global $hStub_MouseProc = DllCallbackRegister("_MouseProc", "long", "int;wparam;lparam")
    Global $hmod = _WinAPI_GetModuleHandle(0)
    Global $hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($hStub_MouseProc), $hmod)

    [/autoit] [autoit][/autoit] [autoit]

    Func _MouseProc($nCode, $wParam, $lParam)
    If ($nCode < 0) Or ($nCode <> $HC_ACTION) Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
    If $wParam = $WM_LBUTTONUP Then __GUI_DoubleClick_MouseUp()
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func OnAutoItExit()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hStub_MouseProc)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Global $__aDblClkCtrl[1][3] = [[0]] ; [0][0]=Anzahl Ctrl, [[GUI-Hwnd,Control-ID,Dummy-ID]]

    [/autoit] [autoit][/autoit] [autoit]

    ;===============================================================================
    ; Function Name....: _GUI_DoubleClick_Register
    ; Description......: Registriert ein Control auf einer GUI für Doppelklick-Event
    ; .................: und gibt eine Ctrl-ID zurück die bei Doppelklick befeuert wird.
    ; .................: Abfragbar über GuiGetMsg() und GUICtrlSetOnEvent()
    ; Parameter(s).....: $_hGui GUI-Handle, auf dem das Control sich befindet
    ; .................: $_cCtrl Control für das Doppelklicks abgefragt werden sollen
    ; Requirement(s)...: none
    ; Return Value(s)..: Erfolg: Dummy-Ctrl, das bei Doppelklick ausgelöst wird
    ; .................: Fehler: "0" set @error =1 bereits registriert
    ; Author(s)........: BugFix ( [email='bugfix@autoit.de'][/email] )
    ;===============================================================================
    Func _GUI_DoubleClick_Register($_hGui, $_cCtrl)
    Local $iRegHwnd = 0, $iRegCtrl = 0
    If $__aDblClkCtrl[0][0] > 0 Then
    For $i = 1 To $__aDblClkCtrl[0][0]
    If $__aDblClkCtrl[$i][0] = $_hGui Then $iRegHwnd = 1
    If $__aDblClkCtrl[$i][0] = $_hGui And $__aDblClkCtrl[$i][1] = $_cCtrl Then $iRegCtrl = 1
    Next
    EndIf
    If $iRegHwnd = 1 And $iRegCtrl = 1 Then Return SetError(1,0,0)
    $__aDblClkCtrl[0][0] += 1
    ReDim $__aDblClkCtrl[$__aDblClkCtrl[0][0] +1][3]
    $__aDblClkCtrl[$__aDblClkCtrl[0][0]][0] = $_hGui
    $__aDblClkCtrl[$__aDblClkCtrl[0][0]][1] = $_cCtrl
    Local $hPrevious = GUISwitch($_hGui)
    Local $iID = GUICtrlCreateDummy()
    $__aDblClkCtrl[$__aDblClkCtrl[0][0]][2] = $iID
    GUISwitch($hPrevious)
    Return $iID
    EndFunc ;==>_GUI_DoubleClick_Register

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func __GUI_DoubleClick_MouseUp()
    Local Static $iDblClickSpeed = RegRead("HKEY_CURRENT_USER\Control Panel\Mouse", "DoubleClickSpeed")
    Local Static $iClickDown = 0, $iTime, $iCtrlSingle
    Local $iClicked = 0
    Local $hWndCurr = WinGetHandle(WinGetTitle("[ACTIVE]"))
    If @error Then Return $iClickDown = 0
    Local $aInfo = GUIGetCursorInfo($hWndCurr)
    If @error Then Return $iClickDown = 0
    For $i = 1 To $__aDblClkCtrl[0][0]
    If $__aDblClkCtrl[$i][0] = $hWndCurr And $__aDblClkCtrl[$i][1] = $aInfo[4] Then
    $iClicked = $i
    ExitLoop
    EndIf
    Next
    If $iClicked = 0 Then Return $iClickDown = 0
    $iClickDown += 1
    If $iClickDown = 1 Then
    $iTime = TimerInit()
    $iCtrlSingle = $aInfo[4]
    Else
    If ($iCtrlSingle <> $aInfo[4]) Or (TimerDiff($iTime) >= $iDblClickSpeed) Then
    $iTime = TimerInit()
    $iCtrlSingle = $aInfo[4]
    Return $iClickDown = 1
    EndIf
    If TimerDiff($iTime) <= $iDblClickSpeed Then _
    DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $__aDblClkCtrl[$iClicked][0], "uint", 273, "wparam", $__aDblClkCtrl[$iClicked][2], "lparam", 0)
    $iClickDown = 0
    EndIf
    EndFunc ;==>__GUI_DoubleClick_MouseUp

    [/autoit]
    Bsp.-Skript
    [autoit]

    #include "DoubleClick_Event.au3"

    [/autoit] [autoit][/autoit] [autoit]

    $Gui1 = GUICreate('Test Doppelklick-Event GUI-1')
    $in1 = GUICtrlCreateInput('', 10, 20, 80, 20)
    $in2 = GUICtrlCreateInput('', 10, 50, 80, 20)
    $in3 = GUICtrlCreateInput('', 10, 80, 80, 20)
    $inDbl1 = _GUI_DoubleClick_Register($Gui1, $in1)
    $inDbl2 = _GUI_DoubleClick_Register($Gui1, $in2)
    $inDbl3 = _GUI_DoubleClick_Register($Gui1, $in3)
    $btChange1 = GUICtrlCreateButton('Zeige GUI_2', 10, 160, 100, 20)

    [/autoit] [autoit][/autoit] [autoit]

    $Gui2 = GUICreate('Test Doppelklick-Event GUI-2')
    $in4 = GUICtrlCreateInput('', 10, 20, 80, 20)
    $in5 = GUICtrlCreateInput('', 10, 50, 80, 20)
    $in6 = GUICtrlCreateInput('', 10, 80, 80, 20)
    $inDbl4 = _GUI_DoubleClick_Register($Gui2, $in4)
    $inDbl5 = _GUI_DoubleClick_Register($Gui2, $in5)
    $inDbl6 = _GUI_DoubleClick_Register($Gui2, $in6)
    $btChange2 = GUICtrlCreateButton('Zeige GUI_1', 10, 160, 100, 20)

    [/autoit] [autoit][/autoit] [autoit]

    GUISetState(@SW_SHOW, $Gui1)

    [/autoit] [autoit][/autoit] [autoit]

    While True
    Switch GUIGetMsg()
    Case -3
    Exit
    Case $btChange1
    GUISetState(@SW_SHOW, $Gui2)
    GUISetState(@SW_HIDE, $Gui1)
    Case $btChange2
    GUISetState(@SW_SHOW, $Gui1)
    GUISetState(@SW_HIDE, $Gui2)
    Case $inDbl1
    ConsoleWrite('Doppel-Klick GUI-1 Input_1' & @LF)
    Case $inDbl2
    ConsoleWrite('Doppel-Klick GUI-1 Input_2' & @LF)
    Case $inDbl3
    ConsoleWrite('Doppel-Klick GUI-1 Input_3' & @LF)
    Case $inDbl4
    ConsoleWrite('Doppel-Klick GUI-2 Input_4' & @LF)
    Case $inDbl5
    ConsoleWrite('Doppel-Klick GUI-2 Input_5' & @LF)
    Case $inDbl6
    ConsoleWrite('Doppel-Klick GUI-2 Input_6' & @LF)
    EndSwitch
    WEnd

    [/autoit]
  • ich weiß nicht ob es an deinem skript oder meinem pc liegt aber komischerweise hängt sich die gui wenn ich sie mit der maus auf der gui schließe immer für 2-3 sekunden auf. entferne ich die double clck register funktioniert das schließen ohne verzögerung.

    ich benutze winxp 32bit sp3

  • ich habe mal ein timer in die exit funktion eingebaut da dauert es auch nur 26ms

    Spoiler anzeigen
    [autoit]

    Func OnAutoItExit()
    $timer = TimerInit()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hStub_MouseProc)
    ConsoleWrite(TimerDiff($timer)&@CRLF)
    EndFunc

    [/autoit]

    es ist auch so das ich die maus in den 2-3 sekunden beim schließen nicht bewegen kann. vieleicht liegts an winxp oder so.

    ps: ich mein 0.26ms

    • Offizieller Beitrag

    So, ich habe den "Zeitfresser" entdeckt. Es ist der Return-Hook in der Mouse-Procedure.
    Je nach System dauert dies unterschiedlich lang. Auf meinem Virtual-XP etwa 0,7 bis 0,8 s, auf Win7 nur 0,001 s.
    Bau mal den Timer, wie folgt ein um zu testen:

    [autoit]


    ;=======================================================
    Global $TEST_Timer
    ;=======================================================

    [/autoit][autoit][/autoit][autoit]

    Func _MouseProc($nCode, $wParam, $lParam)
    If ($nCode < 0) Or ($nCode <> $HC_ACTION) Then Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
    If $wParam = $WM_LBUTTONUP Then __GUI_DoubleClick_MouseUp()
    ;=======================================================
    $TEST_Timer = TimerInit()
    ;=======================================================
    Return _WinAPI_CallNextHookEx($hHook, $nCode, $wParam, $lParam)
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func OnAutoItExit()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hStub_MouseProc)
    ;=======================================================
    ConsoleWrite(StringFormat("Time to close: %.3fs", TimerDiff($TEST_Timer)/1000) & @LF)
    ;=======================================================
    EndFunc

    [/autoit]
  • bei mir kommt Time to close: 0.000s raus.
    dauert leider immer noch 3 sekunden bis sich das fenster schließt und ich die maus wieder bewegen kann :(.
    vieleicht liegts an meinem system. trozdem danke