#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=GuiScroll_Demo.exe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include-once

;~ #include <GuiButton.au3>
;~ #include <GUIConstantsEx.au3>
#Include <StaticConstants.au3>
;~ #include <StructureConstants.au3>
;~ #include <WindowsConstants.au3>
;~ #include <Array.au3>
;~ #include <WinAPI.au3>
;~ #include <GUIScrollBars.au3>
;~ #include <ScrollBarConstants.au3>
#include <ListViewConstants.au3>
#include <Array.au3>
#include <GuiEdit.au3>
#include "GuiScroll_alt.au3" ; -> http://autoit.de/index.php?page=Thread&postID=162464#post162464

Global $g_idMemo,$hScrollPl
Global Const $tagTOUCHINPUT = "LONG x; LONG y; HANDLE hSource; DWORD dwID; DWORD dwFlags; DWORD dwMask; DWORD dwTime; ULONG_PTR dwExtraInfo; DWORD cxContact; DWORD cyContact"
Global $iMemo = 0
Global $y = -1
Global $g_iMouseButtons, $g_iDigitizer

Global $g_iSendRepeat = 7 ; Wie oft soll die ScrollMessage gesendet werden?

; Diese Konstanten sind leider noch nicht in Autoit deklariert... sonst wären sie in WindowsConstants.au3 zu finden.
Global Const $SM_DIGITIZER         = 0x5E ; 94
Global Const $TABLET_CONFIG_NONE   = 0x00
Global Const $NID_INTEGRATED_TOUCH = 0x01
Global Const $NID_EXTERNAL_TOUCH   = 0x02
Global Const $NID_INTEGRATED_PEN   = 0x04
Global Const $NID_EXTERNAL_PEN     = 0x08
Global Const $NID_MULTI_INPUT      = 0x40
Global Const $NID_READY            = 0x80

; Specifies that hWnd prefers noncoalesced touch input.
Global Const $TWF_FINETOUCH = 0x00000001

; Setting this flag disables palm rejection which reduces delays for getting WM_TOUCH messages. This is useful if you want as quick of a response as possible when a user touches your application.
; By default, palm detection is enabled and some WM_TOUCH messages are prevented from being sent to your application. This is useful if you do not want to receive WM_TOUCH messages that are from palm contact.
Global Const $TWF_WANTPALM  = 0x00000002

Global $hScrollPl_b = 400; Hoehe Scrollfenster
Global $hScrollPl_a = 650; Max Scroll
Global $hScrollPl_c = $hScrollPl_a - $hScrollPl_b; Scrollbereich


startGui()

Func startGui()
	$Gui = GUICreate("", 850, 700, -1, -1)
	$up = GUICtrlCreateButton("UP", 10, 10, 80, 40)
	$down = GUICtrlCreateButton("DOWN", 100, 10, 80, 40)
	GUICtrlCreateLabel("Schliessen mit ESC", 550, 10, 120, 40)

	;GUICtrlCreateLabel("y = ",580, 30)
	;$iMemo = GUICtrlCreateLabel("",550, 30)
	$iMemo = GUICtrlCreateEdit("", 530, 50, 300, 600, $WS_VSCROLL)
	_GUICtrlEdit_SetLimitText($iMemo, 0x80000000)

	GUIRegisterMsg($WM_MOUSEWHEEL, "_Scrollbars_WM_MOUSEWHEEL")
	$hScrollPl = GUICreate("$hScrollPl", 500, $hScrollPl_b, 10, 100, BitOR($WS_POPUP, $WS_GROUP, $WM_VSCROLL, $WS_CLIPSIBLINGS), $WS_EX_MDICHILD, $Gui)
	GUISetBkColor(0xffffff)
	Scrollbar_Create($hScrollPl, $SB_VERT, 500)
	Scrollbar_Step(10, $hScrollPl, $SB_VERT)
	_GUIScrollBars_SetScrollInfoMax($hScrollPl, $SB_VERT, $hScrollPl_a); also: 650 minus 400 Hoehe = 250 scroll

	$hDLL = DllCall("User32.dll", "BOOL", "RegisterTouchWindow", "HWND", $hScrollPl, "ULONG", 2) ; hier nach Entstehung von $hScrollPl
	GUIRegisterMsg($WM_TOUCH, "_Scrollbars_WM_TOUCH2")

	$art = GUICtrlCreateLabel("", 1, 1) ; Label für folgenden Focus...
	$hListV = GUICtrlCreateListView("1|2", 100, 100, 300, 200, BitOR($LVS_REPORT, $LVS_NOCOLUMNHEADER, $LVS_SHOWSELALWAYS))

	GUISetState(@SW_SHOW, $Gui)
	GUISetState(@SW_SHOW, $hScrollPl)
	GUICtrlSetState($art, $GUI_FOCUS); Focus auf Label von $hScrollPl
	GUISwitch($Gui)
	;GUISetState(@SW_SHOW, $Gui)


	_Memo(@CRLF & "Vertical" & @CRLF & "--------------------------------------")
	_Memo("nPage....                     : " & _GUIScrollBars_GetScrollInfoPage($hScrollPl, $SB_VERT))
	_Memo("nPos.....                     : " & _GUIScrollBars_GetScrollInfoPos($hScrollPl, $SB_VERT))
	_Memo("nMin.....                     : " & _GUIScrollBars_GetScrollInfoMin($hScrollPl, $SB_VERT))
	_Memo("nMax.....                     : " & _GUIScrollBars_GetScrollInfoMax($hScrollPl, $SB_VERT))
	_Memo("nTrackPos                     : " & _GUIScrollBars_GetScrollInfoTrackPos($hScrollPl, $SB_VERT))

	;_GUIScrollBars_Init($hScrollPl)
	;_GUIScrollBars_SetScrollInfoPos($hScrollPl,$SB_VERT,100)
	;_GUIScrollBars_ScrollWindow($hScrollPl,0,200); bewegt nur das Fenster - nicht die Scrollbar

	;Scrollbar_Scroll($hScrollPl, $SB_VERT, 250); scrollt um ...


    While 1
        $iMsg3 = GUIGetMsg()
        Switch $iMsg3
			Case $GUI_EVENT_CLOSE
				DllClose($hDLL)
                Exit
            Case $up
                MsgBox(0, "Info", "Button up gedrückt",1)
                GUICtrlSetState($art, $GUI_FOCUS); Focus auf Label von $hScrollPl
				Scrollbar_Scroll($hScrollPl, $SB_VERT, $hScrollPl_c); scrollt um ...
				MsgBox(0,"ScrollBarPosition", _GUIScrollBars_GetScrollInfoPos($hScrollPl,$SB_VERT),2)
            Case $down
                MsgBox(0, "Info", "Button down gedrückt",1)
                GUICtrlSetState($art, $GUI_FOCUS); Focus auf Label von $hScrollPl
				Scrollbar_Scroll($hScrollPl, $SB_VERT, 0)
				MsgBox(0,"ScrollBarPosition", _GUIScrollBars_GetScrollInfoPos($hScrollPl,$SB_VERT),2)
        EndSwitch
    WEnd
EndFunc   ;==>startGui


Func _Scrollbars_WM_TOUCH2($hWnd, $Msg, $wParam, $lParam)
	#forceref $hWnd, $Msg

	Local Static $idwID, $iX, $iY
	Local Enum $eID, $eX, $eY

	Local $iTouchPoints = BitAND($wParam, 0xFFFF) ; Anzahl der Berührungspunkte, an der das Display berührt wurde, als diese Message erstellt wurde.

	; Es wird nur gescrollt, wenn $iTouchPoints = 1 ist - du darfst das Dispay also nur mit einem Finger berühren, wenn du scrollen willst!
	If $iTouchPoints = 1 Then
		Local $aTouchInput[$iTouchPoints]

		Local $iBuffer = DllStructCreate("BYTE buffer[" & $iTouchPoints * 40 & "]")

		Local $tTouchInfo = DllStructCreate($tagTOUCHINPUT, DllStructGetPtr($iBuffer))
		Local $pTouchInfo = DllStructGetPtr($tTouchInfo)
		Local $iStructSize = DllStructGetSize($tTouchInfo)

		For $i = 0 To $iTouchPoints - 1 Step 1
			$aTouchInput[$i] = DllStructCreate($tagTOUCHINPUT, $pTouchInfo + $i * 40)
		Next

		Local $aRet = DllCall("User32.dll", "BOOL", "GetTouchInputInfo", "HANDLE", $lParam, "UINT", $wParam, "ULONG_PTR", $pTouchInfo, "int", DllStructGetSize($tTouchInfo))

		Local $aPoints[$iTouchPoints][3] ; $idwID, $iX/100, $iY/100
		$aPoints[0][$eID] = DllStructGetData($aTouchInput[0], "dwID")
		$aPoints[0][$eX]  = DllStructGetData($aTouchInput[0], "x") / 100
		$aPoints[0][$eY]  = DllStructGetData($aTouchInput[0], "y") / 100

		Local $iDirectionX, $iDirectionY
		If $idwID <> $aPoints[0][$eID] Then ; dann neue ID und Startpunkte merken und auf nächste Message warten
			$idwID = $aPoints[0][$eID]
			$iX    = $aPoints[0][$eX]
			$iY    = $aPoints[0][$eY]
		Else
			$iDirectionX = $iX = $aPoints[0][$eX] ? '' : $iX = $aPoints[0][$eX] ? $SB_LINERIGHT : $SB_LINELEFT ; Wenn $iDirectionX <> '' ist, dann müssen wir horizontal scrollen!
			$iX = $aPoints[0][$eX] ; neue Position merken
			$iDirectionY = $iY = $aPoints[0][$eY] ? '' : $iY > $aPoints[0][$eY] ? $SB_LINEDOWN : $SB_LINEUP ; Wenn  $iDirection <> '' ist, dann müssen wir vertikal scrollen!
			$iY = $aPoints[0][$eY] ; neue Position merken
			For $i = 1 To $g_iSendRepeat ; Diese Schleife regelt die Scrollgeschwindigkeit... je mehr Durchläufe, desto schneller.
				If $iDirectionX Then _SendMessage($hWnd, $WM_HSCROLL, $iDirectionX) ; horizontal scrollen (rechts, links)
				If $iDirectionY Then _SendMessage($hWnd, $WM_VSCROLL, $iDirectionY) ; vertikal scrollen (oben, unten)
			Next
		EndIf
	EndIf
EndFunc   ;==>_Scrollbars_WM_TOUCH


; Die in Au3Check 1.51 eingeführte Anweisung #uses, wurde ab 1.52 in #forceref umbenannt. Diese hat zwei Aufgaben.
; 1.) Vermeidung von -w 5 Warnungen durch Au3Check.
; 2.) Vermeiden, dass globale Variablen und Funktionen in der Liste der Bezugssymbole erscheinen, wenn eine Funktion z.B. via Call($fn) aufgerufen wird.
Func _Scrollbars_WM_TOUCH($hWnd, $Msg, $wParam, $lParam)
	#forceref $hWnd, $Msg

		Local Static $aDllError = [ _
			[1, 'Die Dll-Datei kann nicht verwendet werden.'], _
			[2, 'unbekannter Rückgabewert "return type".'], _
			[3, 'Funktion wurde nicht in der DLL-Datei gefunden.'], _
			[4, 'Falsche Anzahl von Parametern.'], _
			[5, 'Falscher Parameter.']], _
			$idwID, $iX, $iY

	Local Enum $eID, $eX, $eY

	Local $iTouchPoints = BitAND($wParam, 0xFFFF) ; Anzahl der Berührungspunkte, an der das Display berührt wurde, als diese Message erstellt wurde.

	; Es wird nur gescrollt, wenn $iTouchPoints = 1 ist - du darfst das Dispay also nur mit einem Finger berühren, wenn du scrollen willst!
	If $iTouchPoints = 1 Then
		Local $aTouchInput[$iTouchPoints]

		Local $iBuffer = DllStructCreate("BYTE buffer[" & $iTouchPoints * 40 & "]")

		Local $tTouchInfo = DllStructCreate($tagTOUCHINPUT, DllStructGetPtr($iBuffer))
		Local $pTouchInfo = DllStructGetPtr($tTouchInfo)
		Local $iStructSize = DllStructGetSize($tTouchInfo)

		For $i = 0 To $iTouchPoints - 1 Step 1
			$aTouchInput[$i] = DllStructCreate($tagTOUCHINPUT, $pTouchInfo + $i * 40)
		Next

		Local $aRet = DllCall("User32.dll", "BOOL", "GetTouchInputInfo", "HANDLE", $lParam, "UINT", $wParam, "ULONG_PTR", $pTouchInfo, "int", DllStructGetSize($tTouchInfo))

		If @error Then
			Local $iError = @error, $iIndex = _ArraySearch($aDllError, $iError), $sErrorText = $iIndex = -1 ? 'Unbekannter Fehler' : $aDllError[$iIndex][1]
			_Memo("Error bei DllCall             : " & $iError & ' Errortext = ' & $sErrorText)
			_Memo("_WinAPI_GetLastError()        : " & _WinAPI_GetLastError())
			_Memo("_WinAPI_GetLastErrorMessage() : " & _WinAPI_GetLastErrorMessage())
			_Memo("_ArrayToString($aRet, ', ')   : " & _ArrayToString($aRet, ', '))
		Else
			_Memo("************************************")
			_Memo("Finger Numbers : " & $iTouchPoints)

			Local $aPoints[$iTouchPoints][3] ; $idwID, $iX/100, $iY/100

			For $j = 0 To $iTouchPoints - 1 Step 1
				$aPoints[$j][$eID] = DllStructGetData($aTouchInput[$j], "dwID")
				$aPoints[$j][$eX]  = DllStructGetData($aTouchInput[$j], "x") / 100
				$aPoints[$j][$eY]  = DllStructGetData($aTouchInput[$j], "y") / 100
				_Memo(StringFormat("Points %2i dwID: %3i x: %5s y: %5s" & $j, $aPoints[$j][$eID], $aPoints[$j][$eX], $aPoints[$j][$eY]))
			Next
			_Memo("Position                      : " & _GUIScrollBars_GetScrollInfoPos($hScrollPl,$SB_VERT))

			Local $aPoints[$iTouchPoints][3] ; $idwID, $iX/100, $iY/100
			$aPoints[0][$eID] = DllStructGetData($aTouchInput[0], "dwID")
			$aPoints[0][$eX]  = DllStructGetData($aTouchInput[0], "x") / 100
			$aPoints[0][$eY]  = DllStructGetData($aTouchInput[0], "y") / 100

			Local $iPosY = 0
			Local $iPos = 0
			Local $bY = 0
			Local $iDirectionX = 0
			Local $iDirectionY = 0
			If $idwID <> $aPoints[0][$eID] Then ; dann neue ID und Startpunkte merken und auf nächste Message warten
				$idwID = $aPoints[0][$eID]
				$iX    = $aPoints[0][$eX]
				$iY    = $aPoints[0][$eY]
			Else
				If $iX <> $aPoints[0][$eX] Then ; dann müssen horizontal wir scrollen!
					$iDirection = $iX = $aPoints[0][$eX] ? $SB_LINERIGHT : $SB_LINELEFT
					$iDirectionX = 1
					$iX = $aPoints[0][$eX] ; neue Position merken
				EndIf
				If $iY <> $aPoints[0][$eY] Then ; dann müssen wir vertikal scrollen!
					$bY = $aPoints[0][$eY] - $iY ; positiv wenn nach unten gewischt wird
					_Memo("bY             : " & $bY)
					$iPos = _GUIScrollBars_GetScrollInfoPos($hScrollPl,$SB_VERT)
					_Memo("iPos           : " & $iPos)
					$iPosY = $iPos+$bY
					If $iPosY < 0 Then
						$iPosY = 0
					Endif
					If $iPosY > $hScrollPl_c Then
						$iPosY = $hScrollPl_c
					Endif
					; $iYAmount ...
					; $iYAmount = DllStructGetData($tTEXTMETRIC, "tmHeight") + DllStructGetData($tTEXTMETRIC, "tmExternalLeading")
					; tmHeight Definiert die Höhe (Oberlänge + Unterlänge) der Zeichen.
					; tmExternalLeading Definiert den Durchschuß (Abstand) den die Anwendung zwischen den Zeilen hinzufügt.
					; Da dieser Bereich sich außerhalb der Schrift befindet, enthält er keine Zeichen und wird nicht durch Textausgabe-Aufrufe modifiziert, weder im Modus OPAQUE noch im Modus TRANSPARENT.
					; Der Designer kann dieses Mitglied auf Null setzen.
					_Memo(StringFormat("WM_TOUCH: Das Fenster wird nach %s gescrollt!", $iY < $aPoints[0][$eY] ? 'unten' : 'oben'))
					$iDirection = $iY = $aPoints[0][$eY] ? $SB_LINEDOWN : $SB_LINEUP
					$iDirectionY = 1
					$iY = $aPoints[0][$eY] ; neue Position merken
				EndIf

				For $i = 1 To 7 ; Schleife regelt die Scroll Geschwindigkeit, je mehr Durchläufe desto schneller
					If $iDirectionX = 1 Then Scrollbar_Scroll($hScrollPl,$SB_HORZ, 0)
					If $iDirectionY = 1 Then Scrollbar_Scroll($hScrollPl,$SB_VERT, $iPosY)
				Next
			EndIf
		Endif
	EndIf
EndFunc   ;==>_Scrollbars_WM_TOUCH

; wParam
;     Das höherwertige Wort gibt die Entfernung an, um die das Rad gedreht wird, ausgedrückt in Vielfachen oder Unterteilungen von WHEEL_DELTA, was 120 ist. Ein positiver Wert zeigt an,
;         dass das Rad  vorwärts gedreht wurde, weg von dem Benutzer; Ein negativer Wert zeigt an, dass das Rad rückwärts zum Benutzer gedreht wurde.
;     Das niederwertige Wort gibt an, ob verschiedene virtuelle Tasten gedrückt sind. Dieser Parameter kann einen oder mehrere der folgenden Werte haben.
;         MK_CONTROL	0x0008	The CTRL key is down.
;         MK_LBUTTON	0x0001	The left mouse button is down.
;         MK_MBUTTON	0x0010	The middle mouse button is down.
;         MK_RBUTTON	0x0002	The right mouse button is down.
;         MK_SHIFT		0x0004	The SHIFT key is down.
;         MK_XBUTTON1	0x0020	The first X button is down.
;         MK_XBUTTON2	0x0040	The second X button is down.
; lParam
;     Das niederwertige Wort gibt die X-Koordinate des Zeigers relativ zur oberen linken Ecke des Bildschirms an.
;     Das höherwertige Wort gibt die Y-Koordinate des Zeigers relativ zur oberen linken Ecke des Bildschirms an.
; Return value
;     Wenn eine Anwendung diese Nachricht verarbeitet, sollte sie null zurückgeben.


Func _Scrollbars_WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam
    Local $iDirection, $iDelta = BitShift($wParam, 16) ; Mouse wheel movement

    If BitAND($wParam, 0x0000FFFF) Then ; If Ctrl or Shift pressed move Horz scrollbar
        $iDirection = $SB_LINERIGHT
        If $iDelta > 0 Then $iDirection = $SB_LINELEFT
		_Memo(StringFormat("WM_MOUSEWHEEL: Das Fenster wird nach %s gescrollt!", $iDirection = $SB_LINERIGHT ? 'rechts' : 'links'))
        For $i = 1 To 7
            _SendMessage($hWnd, $WM_HSCROLL, $iDirection)
        Next
    Else ; Move Vert scrollbar
        $iDirection = $SB_LINEDOWN
        If $iDelta > 0 Then $iDirection = $SB_LINEUP
		_Memo(StringFormat("WM_MOUSEWHEEL: Das Fenster wird nach %s gescrollt!", $iDirection = $SB_LINEUP ? 'oben' : 'unten'))
        For $i = 1 To 7 ; Schleife regelt die Scroll Geschwindigkeit, je mehr Durchläufe desto schneller
            _SendMessage($hWnd, $WM_VSCROLL, $iDirection)
        Next

    EndIf
;~     Return $GUI_RUNDEFMSG
EndFunc   ;==>_Scrollbars_WM_MOUSEWHEEL


Func _Memo($sMessage)
	GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
EndFunc   ;==>MemoWrite


Func __StringRepeat($sString, $iRepeat)
	Local $sStr
	For $i = 1 To $iRepeat Step 1
		$sStr &= $sString
	Next
	Return $sStr
EndFunc
