PushTheButton, ermöglicht Mausklick auf sonst nicht erreichbare Grafiken UPDATE 1.36

  • Hallo,
    in letzter Zeit habe ich von einigen Anfragen gelesen, bei denen nach der Möglichkeit zum Mausklick auf nicht per ControlClick() erreichbare "Buttons" gefragt wurde.
    Beispiele sind Buttons auf Webseiten, oder ganz einfach ein Icon irgendwo auf dem Desktop.
    Wie kann man trotzdem auf diese Elemente klicken?
    Das Prinzip ist einfach. Der zu klickende Button (Bildausschnitt) wird "fotografiert" und abgespeichert. Soll dieser Button nun per Script geklickt werden, dann navigiert man z.B. im Browser auf die entsprechende Webseite und sucht auf dem Screen nach dem abgespeicherten Bild.
    Alles das macht PushTheButton.
    Enthalten ist eine größenveränderliche "Bildschirmlupe" zum genauen Bestimmen des zu findenden Buttons und eine Testfunktion.
    Man kann mit PushTheButton die Bildausschnitte einfach erstellen und diese in eigenen Scripten weiterverwenden. Auch die Funktionen zur Suche vom Bild im Bild sind soooo langsam nicht. :D
    Tip: Um die Größe des Auswahlfensters schnell zu verändern, sollte man erst (per Mausrad oder den +-Tasten auf dem NumBlock) zoomen und dann erst mit Ctrl-Alt-Pfeiltasten die Fenstergrösse verändern.

    Mittlerweile werden auch animierte Buttons gefunden....z.B. dieser kleine Kerl^^
    http://img1.abload.de/img/_ptb_01p33m.jpg

    WICHTIG! Um eine schnelle Suche zu gewährleisten muss in der obersten Zeile des Zoomfensters mehr als eine Farbe sichtbar sein, wenn gespeichert wird!
    IMPORTANT! It is significant for a quick search that in the top line of the Zoomwindow is more than only one colour if the Zoomwindow is to be saved


    Andy


    //Edit 6/11/2011
    Kleiner Bug behoben, großes Danke an peethebee!
    Weiterer Bug von mir gefunden, bisher nicht gefixt: Wenn gleichzeitig mit der Suchfunktion von PushTheButton eine Datei geöffnet ist, die denselben Namen wie der gespeicherte zu suchende "Button" hat, dann KANN ein Fehler auftreten. Also besser nicht den Button speichern, dann z.B. Irfanview den gespeicherten Button anzeigen lassen und anschliessend die Suchfunktion starten.


    //EDIT 19/10/2009
    - English Help available, change language at the traymenu
    - mehrsprachige Hilfe, Sprache im Traymenu einstellbar
    - Fensterhandling verändert
    - INI-Datei hinzugefügt für Sprache und Programm-Einstellungen


    //EDIT 27/09/2009
    Neue Version 1.33 :
    - die Fenstergröße ist nun mit der Maus veränderbar (Fensterrand unten und rechts und die "Ziehecke" unten rechts, diese Funktion ist noch "optimierbar"^^)
    - die Suchgeschwindigkeit der Bitmaps ist extrem erhöht (ca. Faktor 8-10), wenn die prospeed.dll im Verzeichnis des Scriptes liegt. (es gibt auch noch andere dll´s wie z.B. von prog@ndy um Bitmaps zu suchen).
    Ich habe von der prospeed.dll nur zwei Funktionen verwendet, und zwar die schnelle Suche bzw den Vergleich von Bytes im Speicher. Daher auch die Struktur-Ungetüme im Script, denn
    die ansonsten superschnellen AutoIt-Stringbefehle haben einige sehr heftige Geschwindigkeitseinbußen ab einer bestimmten Größe von Strings.
    Wenn mir jemand den Grund dafür nennen könnte, wäre ich dankbar. Ich dachte bisher, die Strings würden in "normalen" Bytearrays abgelegt und sind somit schnell zu scannen...oder ist Assembler doch wesentlich schneller als C? *grins*
    Ansonsten werden die "normalen" AutoIt-Funktionen zur Suche verwendet, zum Testen sind auch diese schnell genug^^, die prospeed.dll ist also NICHT zwingend erforderlich!
    - Betrieb mit mehreren Monitoren ist nun möglich, THX an Funkey!
    - man kann nun einen Dateinamen zum Speichern des "Buttons" angeben.
    - ausgelagert wurde die Funktion _PtB_clickBMP(), welche die Suche in (sichtbaren) Fenstern erlaubt, incl. aller möglichen Mausclicks auf die gesuchte Bitmap. Siehe die Demo in der Downloaddatei.
    - neu hinzugekommen ist der Moviemode, es ist nun möglich ANIMIERTE Buttons abzuspeichern (Bilderfolge Picname_0001.Bmp usw) und natürlich auch wiederzufinden...
    - im Traymenu können nun einige Parameter eingestellt werden, z.B. der Mausversatz, um ein "highlighten" von Buttons beim Mouseover zu vermeiden

    TODO:
    Die Buttons sollen komplett aus der GUI verschwinden, Kontextmenu ftw, auch eine "richtige" Hilfe soll es geben
    Speichern/Lesen der Bitmaps wahlweise auch in den gängigen Formaten JPG, TIf usw. ist wohl nur eine Kleinigkeit
    Bisher ist mir noch keine seriöse (hehe) Anwendung einer "unscharfen" Suche begegnet, das kann aber ohne großen Aufwand implementiert werden


    Das komplette Script ist downzuloaden, u.a. findet man dort auch eine DEMO, welche "eigenmächtig" den Startbutton auf XP-Systemen findet^^
    In der Demo sind auch die verwendeten Such-Funktionen, welche man natürlich in eigenen Programmen verwenden kann.

    autoit.de/wcf/attachment/14530/

    Anhang:
    Für die interessierten zum Thema: Suche vom Bild im Bild

    Spoiler anzeigen

    Ich wende zwei Verfahren an, um den Bildausschnitt zu finden. Das jeweils günstigste (schnellste) Verfahren wird schon zum Zeitpunkt der Auswahl des Bildausschnitts getroffen! Daher ist die Suche auch mit gewöhnlichen AutoIt-Befehlen ziemlich schnell.
    Beim Abspeichern des Bildausschnitts wird für jede Pixelfarbe im Auschnitt die Anzahl der Pixelfarben auf dem Screen gespeichert. Das Pixel mit der wenigsten Anzahl Farben auf dem Screen wird der "Hotspot".
    Je nach Anzahl der Farben dieses Hotspots wird nun ein Verfahren der Bildersuche gewählt.

    Wenn es nur sehr wenige Pixel mit der Farbe des Hotspots auf dem Screen gibt, dann wähle ich die -Pixelsuche
    Ja, das altbekannte Pixelsearch() kommt zum Einsatz. Das "Hotspot"-Pixel wird im gesamten Bildschirminhalt gesucht, und der Bereich rund um das gefundene Pixel wird mittels PixelChecksum() mit dem Bildausschnitt verglichen.

    Wenn aber die Farbe des Hotspots sehr oft auf dem Bildschirm vorkommt (z.B. schwarzer Text auf weißem Hintergrund), dann bietet sich die -Bitmapsuche an. Dafür hole ich etwas weiter aus^^
    Im großen und ganzen sind die (24Bit-Windows BMP)-Bitmapdaten aufgrund ihrer Struktur (Freud lässt grüßen^^, DllStruct ist dein Freund) sehr einfach zu behandeln. Die Bitmapdaten liegen als Folge von Bytes vor, wobei jeweils 3 Bytes die Grundfarben für ein Pixel darstellen. Jedes Pixel wird also durch einen Blau-, Grün-, und Rot-Anteil dargestellt.
    Die Bitmapdaten kann man sich als String mit der Länge Bildbreite*Bildhöhe*3 (3 Farbbits pro Pixel) vorstellen.
    Also sieht der "Pixelstring" einer Bitmap etwa so aus: $Bitmap="BGRBGRBGRBGR....", wobei B der Blauanteil, G der Grünanteil und R der Rotanteil EINES Pixels ist.
    Jede der einzelnen Farben kann 256 Abstufungen enthalten (ein Byte = 8 Bit). Um jetzt ein (oder auch mehrere aufeinanderfolgende) Pixel innerhalb der Bitmap zu finden, muss man nur im $Bitmap-String nach der Folge der 3 Farbbits suchen. Das geht in AutoIt sehr fix mit dem StringInstr()-Befehl.
    Man unterteilt also den Bildausschnitt in "Bildzeilen", und sucht nun per StringInstr() in der gesamten Screen-Bitmap eine Übereinstimmung der ersten Zeile. Wenn eine Übereinstimmung gefunden wurde und die 2.Ausschnittzeile GENAU unter der Fundstelle liegt (das ist die Position im String, welche 3*Bildbreite "dahinter" liegt) und die nächste und die nächste usw. alle übereinstimmen, dann hat man den Bildausschnitt gefunden.
    Das funktioniert natürlich nur dann sehr schnell, wenn die "oberste" Zeile des Bildausschnitts nicht sehr oft im gesamten Bildschirm vorkommt.
    Beispiel dazu: Monochrombildschirm, X ist weiss, O ist schwarz
    Wir haben den gesamten Bildschirminhalt
    XXXXXXXXXXXX
    XXXXXXXXXXXX
    XXXXXXTXTXXX
    XXXXXXTXTXXX
    Es soll auf den folgenden "Button" geklickt werden (im Bildschirm in den untersten beiden Zeilen)
    TXT
    TXT

    wenn ich nun als Bildausschnitt z.B.
    XXTXTXX ;erste zeile
    XXTXTXX ;zweite Zeile
    auswähle, dann wird die erste Zeile sofort (per stringinstr()) im Gesamtbildschirm gefunden, die Prüfung auf die 2. Zeile ergibt den Treffer, der Button ist schnell gefunden

    ABER
    wenn als Bildausschnitt
    XXX ;erste Zeile
    TXT ;zweite Zeile
    gewählt wird, dann dauert die Suche sehr lange. Denn wir erhalten sehr viele Treffer für die erste Zeile des Ausschnitts im Screen und müssen immer eine Zeile darunter nachschauen, ob dort auch die zweite Zeile übereinstimmt.

    Also ist die Suchgeschwindigkeit direkt proportional zur Intelligenz dessen, der den Bildausschnitt auswählt^^. In der Regel findet aber die Testroutine den Ausschnitt in einigen Hundertstel-(!) bis maximal Zehntelekunden.
    Die Suchroutine in PushTheButton scrollt sogar im aktuellen (Browser-)Fenster nach unten, um in der bis dahin "unsichtbaren" Bildschirmdarstellung den Button zu finden

  • nice ^^ ô.Ô
    da hat sich ja jemand richtig mühe gemacht...^^
    649 zeilen ;D
    und das programm ist echt nice !

    • Offizieller Beitrag

    1A Arbeit :thumbup:

    Besonders gelungen finde ich die Bildschirmlupe. Sieht echt Klasse aus. Dein Script kann ich bestimmt mal gebrauchen. Was dagegen wenn ich es (teilweise) in meinen Scripten verwende?
    Dein Script hat Potential :thumbup:

  • Hi,
    natürlich kann man das Script und/oder Teile davon frei verwenden!
    Es ist ja selbst nur ein "kleiner" Teil aus einem meiner Projekte.
    Testet mal bitte, ob das Lupenfenster stark flackert, wenn man den $moviemode=1 setzt (Zeile 24). Dann kann man bei voller Vergrößerung die animierten Smilies hier im Forum erst richtig bewundern^^

    Zitat

    da hat sich ja jemand richtig mühe gemacht...


    Die meiste Mühe hat gemacht, das Script so umzubasteln, daß es nicht jeder "Pixelsearcher" ohne weiteres einsetzen kann. Die Bildschirmlupe ist schon stark eingeschränkt, die gibt es auch in rund^^, als "richtige" Lupe! Mit Griff und allem drum und dran....
    bis denne
    Andy

  • Hallo RogerS und Funkey,

    Zitat

    Leider bleibt die Lupe stehen, wenn man mit der Maus auf einen zweiten Monitor wechselt.

    Ihr habt ja beide dieses "Problem". Ich vermute es liegt daran, daß das BitBlt d.h. die Kopie des Bildschirminhalts von Monitor 2 nicht funktioniert, ich arbeite daran. Hat wohl damit zu tun, daß bei mehreren Monitoren die Macros

    [autoit]

    @DesktopWidth und @DesktopHeight

    [/autoit]

    die richtigen Werte nicht zurückgeben. Könntet ihr das mal prüfen bitte? Ggf gibt es sogar schon einen "roundabout" von dem ihr wisst, vielen Dank vorab.

    Da offensichtlich Interesse besteht, habe ich das Script (wieder) bedienerfreundlicher gemacht und auch die Geschwindigkeit massiv erhöht (Update erfolgt bald). Auf einem normalschnellen Rechner werden zzt 8-10 "Screenshots" pro Sekunde nach einer enthaltenen Bitmap gescannt, also fast Echtzeit :D:D hehe...

    Das einzige Problem ist eine von MS unwahrscheinllich "lahmar***ig" programmierte API-Funktion, vielleicht ist das auch absichtlich so gemacht, wobei generell seitens der Anwender von GDI+ über mangelnde Performance der Funktionen gelästert wird (obwohl "langsam" auch damit zu tun hat, welchen Algorithmus man verwendet. C++ ist auch nur dann schnell, wenn man keine langsamen API-Funktionen aufruft^^ )
    AutoIt ist jedenfalls bei weitem schnell genug, es liegt einzig an der Geschwindigkeit von GdipCreateBitmapFromHBITMAP innerhalb der GDI+.dll. Die braucht selbst auf einem 2,5Ghz-Rechner 100ms für ein Fullscreen-Bitmap, ein bitblt (Verschieben von Grafikspeicherblöcken innerhalb des Graka- oder Hauptspeichers) ist 50fach schneller!
    So wie ich das verstanden habe, werden mit GdipCreateBitmapFromHBITMAP die Daten ja aus dem Speicher der Grafikkarte in den Hauptspeicher kopiert. DAS ist der eigentliche Flaschenhals, daher verwenden Programme wie VNC dazu eigene Treiber :wacko:

  • Das funktioniert:

    [autoit]

    $VirtualDesktopWidth = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 78) ;sm_virtualwidth
    $VirtualDesktopWidth = $VirtualDesktopWidth[0]
    $VirtualDesktopHeight = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 79) ;sm_virtualheight
    $VirtualDesktopHeight = $VirtualDesktopHeight[0]

    [/autoit]

    Edit: Kanns nicht testen, hab jetzt nur einen Bildschirm :(

    Spoiler anzeigen
    [autoit]

    #include <StructureConstants.au3>
    #include <ScrollBarConstants.au3>
    #include <GuiScrollBars.au3>
    #include <GuiStatusBar.au3>
    #include <GUIConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <Misc.au3>
    #include <string.au3>
    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <ScreenCapture.au3>

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

    Opt("WinTitleMatchMode", 4)
    Opt('GUICloseOnESC', 1)
    Opt('GUIOnEventMode', 1)
    Opt("MouseCoordmode", 1)
    Opt("PixelCoordmode", 1)

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

    ;************Variablen und Konstanten
    Global Const $version = "1.9"
    Global Const $BitmapFullscreen = @ScriptDir & "\FULLSCREEN.bmp"
    Global Const $BitmapSearchArea = @ScriptDir & "\SEARCHAREA.bmp"
    Global Const $maxanzahlpixel = 50 ;wenn mehr pixel, dann bitmapsuche ansonsten pixelsuche
    Const $moviemode = 0 ;Modus, um auch bewegten Hintergrund im Zoomfenster darzustellen 1=EIN(Zoomfenster könnte flimmern) 0=AUS
    Const $c24RGBFullMatch = 1 ;Load as 24 bits and full match
    Global $ZoomWindowFactor = 20, $maxBxHzoomfaktor = 25
    Global $MagZoom = 1, $MagHeight = $ZoomWindowFactor * 8, $MagWidth = $ZoomWindowFactor * 16
    Global $dll[3], $DeskHDC, $GUIHDC, $versatz = 0, $aliste[1][1]
    Global $steps = 1, $run = 0, $hwindow, $zoompressed = 0, $zoom = 0, $exitflag = 0, $x, $y, $anleitungflag = 0, $check = 0
    Global $testfile = "ptb.txt", $Anzahl_bestpixel = 0, $xpos = 1, $ypos = 1, $mausaltx = 100, $mausalty = 100
    Global $xcentersquare, $ycentersquare, $imgBytes = 3
    Local $calcHWND, $pos, $aWinPos, $aWinCSize
    Local $pBitmap, $BitmapData, $pixelFormat
    Local $aStatusbar_Text[5] = [" Ver " & $version, "RGB:", "x/y", "Zoom", "BxH Zoom"], $aStatusbar_Parts[5] = [55, 130, 220, 275, -1]
    $dll[1] = DllOpen("user32.dll")
    $dll[2] = DllOpen("gdi32.dll")

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

    Local $VirtualDesktopWidth = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 78) ;sm_virtualwidth
    Global $DesktopWidth = $VirtualDesktopWidth[0]
    Local $VirtualDesktopHeight = DLLCall("user32.dll", "int", "GetSystemMetrics", "int", 79) ;sm_virtualheight
    Global $DesktopHeight = $VirtualDesktopHeight[0]

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

    ;************Hauptfenster*********
    _GDIPlus_Startup()
    $gui = GUICreate("PushTheButton by Andy@AutoIt.de", $MagWidth + 20, $MagHeight + 100, -1, -1, -1, $WS_EX_TOOLWINDOW)
    $StatusBar = _GUICtrlStatusBar_Create($gui, $aStatusbar_Parts, $aStatusbar_Text)
    $button_finden = GUICtrlCreateButton("Test: Gespeicherten Button finden", 1, 1, 180, 30)
    $button_anleitung = GUICtrlCreateButton("Anleitung zeigen", 1, 1, 110, 30)
    If Not FileExists($testfile) Then ;wenn kein file besteht, erst eins anlegen lt Beschreibung
    GUICtrlSetState($button_finden, BitOR($GUI_DISABLE, $GUI_HIDE))
    EndIf

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

    ;*************Fenster Anleitung anzeigen
    $anleitung = GUICreate("Anleitung zu PushTheButton", 500, 160, -1, -1, -1, $WS_EX_TOOLWINDOW)
    $label1 = GUICtrlCreateLabel( _
    "- Zum (Browser)-Fenster navigieren, in dem der gesuchte Button geklickt werden soll" & @CRLF & _
    "- Mauscursor auf den zu drückenden Button/Text platzieren" & @CRLF & _
    "- falls Button ""highlighted"" mit CTRL+ALT+u Mausversatz einsetzen (50 Pixel nach oben)" & @CRLF & _
    "- mit Numpad+ und Numpad- oder dem Mausrad um den Mauscursor herum zoomen" & @CRLF & _
    "- Pfeiltasten hoch, runter, links, rechts um Mauscursor optimal zu positionieren" & @CRLF & _
    "- Ctrl+Alt+Pfeiltasten hoch, runter, links, rechts um die Zoomfenstergröße anzupassen" & @CRLF & _
    "- wenn Mauscursor an optimaler Position, dann CTRL+ALT+m drücken um Buttondaten zu speichern" & @CRLF & _
    "- es wird der Bereich im Zoomfenster in einer Bilddatei gespeichert" & @CRLF & _
    "- zum Testen den Finden-Button aktivieren um nach dem gespeicherten Bereich zu suchen, es wird ggf." & @CRLF & _
    " automatisch nach unten gescrollt und der Mauscursor wird an die gefundene Position gesetzt", 10, 10)

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

    ;*************Zoom-Fenster im Fenster
    Local $titlepic = "Zoom"
    Global $pic = GUICreate($titlepic, $MagWidth, $MagHeight, 10, 10, $ws_popup + $ws_border, $WS_EX_TOPMOST, $gui);, $WS_POPUP, $WS_EX_TOPMOST)
    ;global $pic=GUICtrlCreateGraphic(10,10,160,160)
    Global $hWnd = WinGetHandle($titlepic)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)

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

    ;**************Hotkeys, Message- und Eventhandler
    HotKeySet("^!u", "_Hotkey_u") ;versatz ein/aus
    HotKeySet("{ESC}", "_exitflag") ;wenn ESC gedrückt, dann flag zum beenden der aktuellen Funktion setzen
    HotKeySet("^!m", "_FindBestPixel") ;suche nach der seltensten pixelfarbe
    GUISetOnEvent($GUI_EVENT_CLOSE, "OnAutoItExit", $gui)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_anleitung", $anleitung)
    GUICtrlSetOnEvent($button_finden, "_bereichfinden") ;Pixel auf dem Bildschirm finden
    GUICtrlSetOnEvent($button_anleitung, "_anleitung")
    GUIRegisterMsg($WM_MOVE, '_Dock') ;wenn fenster bewegt wird, child mitbewegen
    GUIRegisterMsg(0x020A, "_ZoomMousewheel") ;wenn Mousewheel bewegt wird, zoomen
    WinSetOnTop($pic, '', 1) ;Zoom immer im Vordergrund
    WinSetOnTop($gui, '', 1) ;Gui immer im Vordergrund
    WinSetOnTop($anleitung, '', 1) ;Gui immer im Vordergrund
    $DeskHDC = DllCall($dll[1], "int", "GetDC", "hwnd", 0) ;handle zum DeviceContext um mit gdi+ zu arbeiten
    $GUIHDC = DllCall($dll[1], "int", "GetDC", "hwnd", $pic)
    _Zoom() ;zoomfenster darstellen
    _Dock() ;dockt das Zoomfenster in/an das Hauptgenster
    _MoveWindows() ;alle Fenster an ihren Platz bringen
    _Show_Windows() ;alle Fenster zeigen
    _ctrl_alt_up() ;

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

    ;************Hauptprogramm
    While 1
    If Not WinActive($gui) Then ;falls gui nicht oberstes Fenster, dann
    Sleep(100)
    WinActivate($gui) ;immer im vordergrund halten
    EndIf
    Sleep(50) ;wartezeit für zoom()
    _zoomen(0) ;mit +- zoomen und mit den pfeiltasten den mauscursor bewegen
    If $moviemode Then _refresh() ;um bewegten hintergrund auch bewegt im fenster darzustellen
    WEnd

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

    ;***********Funktionen

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

    Func _GUIClose()
    Exit
    EndFunc ;==>_GUIClose

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

    Func _Anleitung()
    If BitAND(WinGetState($anleitung), 2) Then ;anleitungsfenster sichtbar
    $anleitungflag = 0
    GUICtrlSetData($button_anleitung, "Anleitung zeigen")
    GUISetState(@SW_HIDE, $anleitung) ;Fenster verstecken
    Else
    $anleitungflag = 1
    GUICtrlSetData($button_anleitung, "Anleitung verbergen")
    GUISetState(@SW_SHOW, $anleitung) ;Fenster zeigen
    $winposgui = WinGetPos($gui)
    $winposanleitung = WinGetPos($anleitung)
    If $winposgui[0] > $DesktopWidth - $winposgui[2] - $winposanleitung[2] Then ;wenn Anleitungsfenster über den Rand ragt...
    WinMove($gui, "", $DesktopWidth - $winposgui[2] - $winposanleitung[2], $winposgui[1]);...dann Fenster nach links schieben
    EndIf
    EndIf
    EndFunc ;==>_anleitung

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

    Func _Dock() ;dockt das zoomfenster an/in die GUI
    $winposgui = WinGetPos($gui)
    ;WinMove($pic, "", $winposgui[0] + $winposgui[2] - $MagWidth - 20, $winposgui[1] + 30)
    WinMove($anleitung, "", $winposgui[0] + $winposgui[2], $winposgui[1])
    WinMove($pic, "", $winposgui[0] + 10, $winposgui[1] + 30)
    EndFunc ;==>_dock

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

    Func _Bereichfinden() ;sucht nach dem gespeicherten Bild auf dem Desktop
    _hide_windows() ;gui verstecken
    $start = TimerInit()
    $a = _Buttonfinden() ;auf dem Screen den Button suchen, ggf so lange im aktuellen Fenster nach unten scrollen bis gefunden
    If @error Then ;nicht gefunden
    $t = TimerDiff($start) / 1000
    ConsoleWrite("Nicht gefunden! Suchzeit: " & StringFormat("%.3f", $t) & " Sekunden" & @LF)
    MsgBox(0, "PushTheButton INFO!", "Gespeicherte Daten wurden NICHT in diesem Fenster gefunden!")
    Else
    $t = TimerDiff($start) / 1000
    ConsoleWrite("Gefunden in: " & StringFormat("%.3f", $t) & " Sekunden" & @LF)
    MouseMove($a[0], $a[1], 1) ;mausposition zum hotspot
    MsgBox(0, "Gefunden in " & StringFormat("%.3f", $t) & " Sekunden", "x/y= " & $a[0] & " / " & $a[1] & @CRLF & $check)
    EndIf
    _show_windows()
    EndFunc ;==>_bereichfinden

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

    Func _Buttonfinden() ;rückgabe x- und y-position des gefundenen hotspots in einem array [0]und[1]
    Local $gefunden = 0
    $exitflag = 0 ;flag, ob ESC gedrückt wurde
    FileOpen("ptb.txt", 1) ;daten lesen
    If @error Then
    MsgBox(0, "Fehler!", "Keine Datei mit Informationen zur Suche gefunden")
    Return -1
    EndIf
    $check = FileReadLine("ptb.txt", 1) ;pixelchecksum
    $pixel = FileReadLine("ptb.txt", 2) ;pixelfarbe in hex RGB
    $Anzahl_bestpixel = Number(FileReadLine("ptb.txt", 3)) ;niedrigste Anzahl der gesuchten Pixel
    $px = FileReadLine("ptb.txt", 4) ;x-Versatz des Hotspots innerhalb des pics
    $py = FileReadLine("ptb.txt", 5) ;y-Versatz des Hotspots innerhalb des pics
    $dx = FileReadLine("ptb.txt", 6) ;breite in pixel
    $dy = FileReadLine("ptb.txt", 7) ;hoehe in pixel
    FileClose("ptb.txt")

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

    If $Anzahl_bestpixel > $maxanzahlpixel Then ;wenn wenige passende farbige pixel auf dem Bildschirm sind...
    ConsoleWrite("Verfahren mit Bitmapsuche gewählt" & @CRLF) ;dann strings suchen (Bitmap2 in Bitmap1 suchen)
    $start = TimerInit()
    Do
    If $exitflag Then ExitLoop ;esc gedrückt
    $alt = PixelChecksum(200, 200, $DesktopWidth, $DesktopHeight) ;bildschirminhalt sichern
    $tresult = _findbmp($BitmapFullscreen, $BitmapSearchArea, $c24RGBFullMatch) ;suchen per stringfunktion in der Bitmap
    If $tresult = 0 Then ;nicht gefunden
    _pagedown() ;runterscrollen
    $tooltip = ToolTip("Suche läuft: Scollen...", $DesktopWidth / 2, $DesktopHeight / 2 + 50)
    Sleep(200) ;wartezeit, bis gescrollt wurde
    $neu = PixelChecksum(200, 200, $DesktopWidth, $DesktopHeight) ;bildschirminhalt nach dem scrollen
    EndIf
    Until $tresult <> 0 Or $alt = $neu ;solange bis true oder nicht mehr weiter zu scrollen
    ToolTip("") ;tooltip löschen
    If $tresult <> 0 Then $gefunden = 1
    Else ;wenn es nur wenige Pixel in der angegebenen Farbe gibt, ist diese Variante mit pixelsearxch schneller
    ConsoleWrite("Verfahren mit Pixelsuche gewählt" & @CRLF)
    Do
    $alt = PixelChecksum(200, 200, $DesktopWidth, $DesktopHeight) ;bildschirminhalt sichern
    Local $x = 0, $y = 0
    While 1
    $pix = PixelSearch($x, $y, $DesktopWidth, $DesktopHeight, Dec($pixel)) ;pixelfarbe suchen
    If @error Or $exitflag Then ExitLoop ;nicht gefunden oder esc gedrückt, dann pagedown
    ;msgbox(0,"pix gefunden an",$pix[0]&" "&$pix[1])
    While 1
    $x = $pix[0] ;x- und y-koordinaten des gefundenen pixels (hotspot)
    $y = $pix[1]
    $prozent = ($y * $DesktopWidth + $x) * 100 / $DesktopWidth / $DesktopHeight
    $tooltip = ToolTip(StringFormat("Suche läuft : %.0f%%", $prozent), $DesktopWidth / 2, $DesktopHeight / 2)
    Local $p1x = $x - $px, $p1y = $y - $py ;umrechnen der hotspotkoordinaten für checksum
    Local $p2x = $p1x + $dx - 1, $p2y = $p1y + $dy - 1
    ; msgbox(0,"pixel mit farbe "&$pixel,$p1x&" "&$p1y&@crlf&$p2x&" "&$p2y&@crlf&PixelChecksum($p1x,$p1y,$p2x,$p2y))
    If PixelChecksum($p1x, $p1y, $p2x, $p2y) = $check Then ;wenn pixelchecksum gleich der gespeicherten pixelchecksum ist, dann gefunden
    $gefunden = 1
    ExitLoop
    EndIf
    $x += 1 ;ein pixel weiter in der zeile
    $pix = PixelSearch($x, $y, $DesktopWidth, $y, Dec($pixel)) ;pixel suchen
    If @error Or $exitflag Then ExitLoop ;wenn in der zeile kein pixel mehr, dann raus
    WEnd
    If $gefunden = 1 Then ExitLoop
    $x = 0 ;neue spalte
    ;msgbox(0,"nächste zeile",0)
    $y += 1 ;neue zeile
    WEnd
    If $exitflag Or $gefunden = 1 Then ExitLoop ;esc gedrückt oder gefunden
    _pagedown() ;runterscrollen
    $tooltip = ToolTip("Suche läuft: Scollen...", $DesktopWidth / 2, $DesktopHeight / 2)
    Sleep(200)
    $neu = PixelChecksum(200, 200, $DesktopWidth, $DesktopHeight)
    Until $alt = $neu ;solange, bis nicht mehr gescrollt werden kann
    EndIf
    $exitflag = 0
    ToolTip("")
    If $gefunden = 0 Then ;gesuchte Pixel nicht gefunden
    SetError(1)
    Return -1
    Else ;gefunden
    SetError(0)
    Dim $koord[2] = [$x, $y]
    Return $koord ;array mit den hotspot-koordinaten zurückgeben
    EndIf
    EndFunc ;==>_Buttonfinden

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

    Func _Hotkey_u() ;versetzt den cursor um 50 pixel nach oben um highlighten zu verhindern
    If $versatz = -50 Then
    $versatz = 0
    MouseMove(MouseGetPos(0), MouseGetPos(1) + 50)
    Else
    $versatz = -50
    MouseMove(MouseGetPos(0), MouseGetPos(1) - 50)
    EndIf
    EndFunc ;==>_Hotkey_u

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

    Func _Exitflag() ;wenn ESC gedrückt, dann Flag setzen
    $exitflag = 1
    EndFunc ;==>_exitflag

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

    Func _Zoomen($zoom) ;zoomfaktor per +-Tasten oder Mausrad oder Ctrl-Alt-Pfeiltasten einstellen
    If _IsPressed("6B", $dll[1]) Or $zoom = 1 Then ;numpad + oder mausrad
    $MagZoom += 2
    If $MagZoom > $ZoomWindowFactor Then $MagZoom = $ZoomWindowFactor
    EndIf
    If _IsPressed("6D", $dll[1]) Or $zoom = 2 Then ;numpad - oder mausrad
    If $MagZoom > 3 Then ;wenn zoom <3 dann kleineren zoomfaktor wählen
    $MagZoom -= 1
    Else
    $MagZoom -= 0.5
    EndIf
    If $MagZoom < 1 Then $MagZoom = 1
    EndIf
    If _IsPressed("25", $dll[1]) Then ;Pfeiltaste links
    If _IsPressed("12", $dll[1]) And _IsPressed("11", $dll[1]) Then ;ctrl+alt+links
    _ctrl_alt_left() ;zoomfenster verkleinern
    Else
    MouseMove(MouseGetPos(0) - 1, MouseGetPos(1), 1)
    EndIf
    EndIf
    If _IsPressed("26", $dll[1]) Then ;Pfeiltaste hoch
    If _IsPressed("12", $dll[1]) And _IsPressed("11", $dll[1]) Then ;ctrl+alt+hoch
    _ctrl_alt_up()
    Else
    MouseMove(MouseGetPos(0), MouseGetPos(1) - 1, 1)
    EndIf
    EndIf
    If _IsPressed("27", $dll[1]) Then ;Pfeiltaste rechts
    If _IsPressed("12", $dll[1]) And _IsPressed("11", $dll[1]) Then ;ctrl+alt+rechts
    _ctrl_alt_right()
    Else
    MouseMove(MouseGetPos(0) + 1, MouseGetPos(1), 1)
    EndIf
    EndIf
    If _IsPressed("28", $dll[1]) Then ;Pfeiltaste runter
    If _IsPressed("12", $dll[1]) And _IsPressed("11", $dll[1]) Then ;ctrl+alt+runter
    _ctrl_alt_down()
    Else
    MouseMove(MouseGetPos(0), MouseGetPos(1) + 1, 1)
    EndIf
    EndIf
    If _mauspostostatusbar() Or _iskeypressed() Or $zoom = 1 Or $zoom = 2 Then _Zoom() ;nur wenn maus bewegt wurde, zoomfenster upgraden
    $hWnd = WinGetHandle($titlepic)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) ;zoomfenster refresh
    ;msgbox(0,"zoom:",_GDIPlus_ImageGetWidth($hwnd))
    _GUICtrlStatusBar_SetText($StatusBar, "Zoom: " & $MagZoom, 3, 0)
    _GUICtrlStatusBar_SetText($StatusBar, Round($MagWidth / $MagZoom) & " " & Round($MagHeight / $MagZoom), 4, 0)
    EndFunc ;==>_zoomen

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

    Func _Zoom() ;Zoomfenster
    If MouseGetPos(0) < $MagWidth / 2 / $MagZoom Then ;linker rand
    $xcentersquare = (((MouseGetPos(0) + 1) * $MagZoom) - $MagZoom / 2) - 9
    If MouseGetPos(0) < 19 / 2 / $MagZoom Then
    $xcentersquare = 0
    EndIf
    $xpos = (MouseGetPos(0) - Int(($MagWidth / $MagZoom) / 2))
    If $xpos < 0 Then $xpos = 0
    ; _GUICtrlStatusBar_SetText($StatusBar, "", 3, 0)
    Else
    $xpos = (MouseGetPos(0) - Int(($MagWidth / $MagZoom) / 2))
    $xcentersquare = $MagWidth / 2 - ($ZoomWindowFactor / 2)
    ; _GUICtrlStatusBar_SetText($StatusBar, $xcentersquare&" "&$magwidth/$magzoom, 3, 0)
    If Mod($MagWidth / $MagZoom, 2) = 0 And $MagZoom > (3 / 4 * $ZoomWindowFactor) Then $xcentersquare = $MagWidth / 2
    EndIf
    If MouseGetPos(1) - $versatz < $MagHeight / 2 / $MagZoom Then ;oberer rand
    $ycentersquare = (((MouseGetPos(1) + 1) * $MagZoom) - $MagZoom / 2) - 9
    If MouseGetPos(1) < 19 / 2 / $MagZoom Then
    $ycentersquare = 0
    EndIf
    $ypos = (MouseGetPos(1) - $versatz - Int(($MagHeight / $MagZoom) / 2))
    If $ypos < 0 Then $ypos = 0
    Else
    $ypos = (MouseGetPos(1) - $versatz - Int($MagHeight / $MagZoom / 2))
    $ycentersquare = $MagHeight / 2 - ($ZoomWindowFactor / 2)
    ; _GUICtrlStatusBar_SetText($StatusBar, $xcentersquare&" "&$magwidth/$magzoom, 3, 0)
    If Mod($MagHeight / $MagZoom, 2) = 0 And $MagZoom > (3 / 4 * $ZoomWindowFactor) Then $ycentersquare = $MagHeight / 2
    EndIf
    If MouseGetPos(0) > $DesktopWidth - $MagWidth / $MagZoom Then ;rechter rand
    $xpos = (MouseGetPos(0) - Int(($MagWidth / $MagZoom)) / 2)
    $xcentersquare = $MagWidth / 2 - ($ZoomWindowFactor / 2)
    ;_GUICtrlStatusBar_SetText($StatusBar, $xcentersquare&" "&$magwidth/$magzoom, 4, 0)
    If MouseGetPos(0) > $DesktopWidth - $MagWidth / 2 / $MagZoom Then
    $xpos = $DesktopWidth - $MagWidth / $MagZoom
    $xcentersquare = $MagWidth - (($DesktopWidth - MouseGetPos(0)) * $MagZoom) + $MagZoom / 2 - ($ZoomWindowFactor / 2) - 1
    EndIf
    If $xcentersquare > $MagWidth - $ZoomWindowFactor Then $xcentersquare = $MagWidth - $ZoomWindowFactor
    EndIf
    If MouseGetPos(1) - $versatz > $DesktopHeight - $MagHeight / $MagZoom Then ;unterer rand
    $ypos = (MouseGetPos(1) - $versatz - Int(($MagHeight / $MagZoom)) / 2)
    $ycentersquare = $MagHeight / 2 - ($ZoomWindowFactor / 2)
    If MouseGetPos(1) - $versatz > $DesktopHeight - $MagHeight / 2 / $MagZoom Then
    $ypos = $DesktopHeight - $MagHeight / $MagZoom
    $ycentersquare = $MagHeight - (($DesktopHeight - (MouseGetPos(1) - $versatz)) * $MagZoom) + $MagZoom / 2 - ($ZoomWindowFactor / 2) - 1
    EndIf
    If $ycentersquare > $MagHeight - ($ZoomWindowFactor / 2) Then $ycentersquare = $MagHeight - ($ZoomWindowFactor / 2)
    EndIf
    _refresh()
    EndFunc ;==>_Zoom

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

    Func _Refresh() ;zoomwindow refreshen
    DllCall($dll[2], "int", "StretchBlt", "int", _
    $GUIHDC[0], "int", _ ;handle zielfenster
    0, "int", _ ;x Koordinate zielfenster
    0, "int", _ ;y Koordinate zielfenster
    $MagWidth * $MagZoom, "int", _ ;breite in logischen einheiten (zoom)
    $MagHeight * $MagZoom, "int", _ ;hoehe in logischen einheiten (zoom)
    $DeskHDC[0], "int", _ ;handle quellfenster
    $xpos, "int", _ ;x-position quelle
    $ypos, "int", _ ;y-position quelle
    $MagWidth, "int", _ ;Breite in log einheiten quelle
    $MagHeight, "long", _ ;höhe in log einheiten quelle
    $SRCCOPY) ;verknuepfungsverfahren quelle /ziel
    _GDIPlus_GraphicsDrawRect($hGraphic, $xcentersquare, $ycentersquare, 19, 19) ;markiert bei vollem zoom den hotspot
    _GDIPlus_GraphicsDrawLine($hGraphic, $xcentersquare + 9, 0, $xcentersquare + 9, $ycentersquare)
    _GDIPlus_GraphicsDrawLine($hGraphic, $xcentersquare + 9, $ycentersquare + 19, $xcentersquare + 9, $MagHeight)
    _GDIPlus_GraphicsDrawLine($hGraphic, 0, $ycentersquare + 9, $xcentersquare, $ycentersquare + 9)
    _GDIPlus_GraphicsDrawLine($hGraphic, $xcentersquare + 19, $ycentersquare + 9, $MagWidth, $ycentersquare + 9)
    EndFunc ;==>_refresh

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

    Func OnAutoItExit()
    DllCall($dll[1], "int", "ReleaseDC", "int", $DeskHDC[0], "hwnd", 0)
    DllCall($dll[1], "int", "ReleaseDC", "int", $GUIHDC[0], "hwnd", $gui)
    DllClose($dll[1])
    DllClose($dll[2])
    Exit (0)
    EndFunc ;==>OnAutoItExit

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

    Func _Pagedown() ;wenn jemand weiß wie der ERFOLGTE Scrollevent abgefragt werden kann, bitte melden!
    ;msgbox(0,$sb_pagedown,"scroll",1)
    Send("{PGDN}")
    ;_GUIScrollBars_ScrollWindow($hWindow, 0,100)
    EndFunc ;==>_pagedown

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

    Func _MausposToStatusbar() ;Farbe und Koordinate an der Mauszeigerposition in die Statusbar
    $a = MouseGetPos()
    If Abs($a[0] - $mausaltx) <> 0 Or Abs($a[1] - $mausalty) <> 0 Or $zoom = 1 Or $zoom = 2 Then ;wenn maus oder mausrad bewegt
    $mausaltx = $a[0]
    $mausalty = $a[1]
    $col = Hex(PixelGetColor($a[0], $a[1] - $versatz), 6)
    _GUICtrlStatusBar_SetText($StatusBar, "RGB:" & $col, 1, 0) ;farbe
    _GUICtrlStatusBar_SetText($StatusBar, StringFormat("x:%6d y:%6d", $a[0], $a[1] - $versatz), 2, 0) ;mauspos
    Return 1;statusbar nur beschreiben, wenn Mauscursor sich bewegt hat
    EndIf
    Return 0
    EndFunc ;==>_mauspostostatusbar

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

    Func _ZoomMousewheel($hWnd, $msg, $l, $r) ;abfrage mausrad
    If $l = 0xFF880000 Then ; Mouse wheel up
    _zoomen(1)
    Else ; Mouse wheel down
    _zoomen(2)
    EndIf
    EndFunc ;==>_ZoomMousewheel

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

    Func _Show_Windows() ;alle GUI-Fenster zeigen
    GUISetState(@SW_SHOW, $gui)
    GUISetState(@SW_SHOW, $pic)
    If $anleitungflag = 1 Then GUISetState(@SW_SHOW, $anleitung)
    $hWnd = WinGetHandle($titlepic)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd) ;zoomfenster refresh
    EndFunc ;==>_show_windows

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

    Func _Hide_Windows() ;alle GUI-Fenster verstecken
    GUISetState(@SW_HIDE, $gui)
    GUISetState(@SW_HIDE, $pic)
    GUISetState(@SW_HIDE, $anleitung)
    EndFunc ;==>_hide_windows

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

    Func _FindBestPixel() ;pixel mit der wenigsten Anzahl Farben auf dem Bildschirm suchen
    _hide_windows()
    $MagWidth = (Round($MagWidth / $MagZoom)) * $MagZoom
    $MagHeight = (Round($MagHeight / $MagZoom)) * $MagZoom
    $t = TimerInit()
    $exitflag = 0
    Local $anzahl = 0, $max = 0, $prozent = 0
    Local $dx = ($MagWidth / $MagZoom) ;breite area
    Local $dy = ($MagHeight / $MagZoom) ;höhe area
    ;$p = MouseGetPos()
    Local $p1x = $xpos, $p1y = $ypos
    Local $p2x = $xpos + $dx - 1, $p2y = $ypos + $dy - 1
    $check = PixelChecksum($p1x, $p1y, $p2x, $p2y)
    _ScreenCapture_Capture($BitmapSearchArea, $p1x, $p1y, $p2x + 1, $p2y + 1, False)
    $aret = _analysepic($BitmapSearchArea) ;array, findet die farbe mit den wenigsten pixeln, den hotspot x+y
    ; $info=guigetcursorinfo()
    FileOpen("ptb.txt", 2)
    FileWriteLine("ptb.txt", $check) ;checksum
    FileWriteLine("ptb.txt", $aret[3]) ;pixelfarbe hotspot
    FileWriteLine("ptb.txt", $aret[0]) ;anzahl der Farben
    FileWriteLine("ptb.txt", $aret[1]) ;versatz des hotspot x
    FileWriteLine("ptb.txt", $aret[2]) ;versatz des hotspot y
    FileWriteLine("ptb.txt", $dx) ;breite pic
    FileWriteLine("ptb.txt", $dy) ;höhe pic
    FileClose("ptb.txt")
    ;msgbox(0,"Zeile gespeichert",0)
    GUICtrlSetState($button_finden, $GUI_show + $gui_enable)
    _GUICtrlStatusBar_SetText($StatusBar, ' Pixel gespeichert', 3, 0)
    _show_windows()
    MouseMove($xpos + $aret[1], $ypos + $aret[2] + $versatz)
    EndFunc ;==>_FindBestPixel

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

    ;untersucht, ob Bitmap2 in Bitmap1 enthalten ist
    ;Originalfunc by JunkEW , modified by Andy@ http://www.autoit.de finds the exact match at screen
    Func _FindBMP($BMP1, $BMP2, $MatchType = $c24RGBFullMatch)
    Dim $BMP1Data = "", $BMP1Width = 0, $BMP1Height = 0, $BMP1LineWidth = 0;
    Dim $BMP2Data = "", $BMP2Width = 0, $BMP2Height = 0, $BMP2LineWidth = 0
    Local $searchFor, $line, $iPos = 1
    ; Load the bitmap to search in
    _GetImage($BMP1, $BMP1Data, $BMP1Width, $BMP1Height, $BMP1LineWidth, $imgBytes)
    $BMP1Data = BinaryToString($BMP1Data)
    _GetImage($BMP2, $BMP2Data, $BMP2Width, $BMP2Height, $BMP2LineWidth, $imgBytes)
    $BMP2Data = BinaryToString($BMP2Data)
    If $BMP2Height = 0 Then
    SetError(1, 0, 0)
    Return False
    EndIf
    Local $searchFor1 = StringMid($BMP2Data, 1, ($BMP2Width * $imgBytes)) ;1. pixel-zeile in der bitmap2 (string)
    $iPos = StringInStr($BMP1Data, $searchFor1, 2, 1) ;1. fundstelle des strings in Bitmap2
    ;zeilenweises vergleichen der beiden bitmaps, ist bitmap2 in bitmap1 enthalten?
    While 1
    Local $flag = 0
    If $iPos <> 0 Then
    If ($iPos - 1) / $imgBytes = Int(($iPos - 1) / $imgBytes) Then ;;prüfen ob ipos am anfang eines farbbits steht
    $prozent = $iPos / 3 * 100 / $DesktopWidth / $DesktopHeight
    $tooltip = ToolTip(StringFormat("Suche läuft : %.0f%%", $prozent) & @CRLF & "Zeile " & Int($iPos / $imgBytes / $DesktopWidth), $DesktopWidth / 2, $DesktopHeight / 2)
    For $s = 2 To $BMP2Height ;zeilenweise das suchbild mit dem screen vergleichen
    $searchFor = StringMid($BMP2Data, 1 + (($s - 1) * $BMP2LineWidth), $BMP2Width * $imgBytes) ; s-te zeile aus dem ausschnitt
    $line = StringMid($BMP1Data, $iPos + (($s - 1) * $BMP1LineWidth), $BMP2Width * $imgBytes) ;zeile "unter" der gefundenen zeile im screen
    If $searchFor <> $line Then ;zeilen nicht gleich,
    $flag = 1
    ExitLoop ;exit for/next
    EndIf
    Next
    If $flag = 0 Then ;alle Zeilen haben übereingestimmt, Bitmap gefunden
    $x = Mod(($iPos - 1) / $imgBytes, $DesktopWidth)
    $y = Int(($iPos - 1) / $imgBytes / $DesktopWidth)
    Return 1
    $bMatchPossible = True
    $matchedLines = $BMP2Height
    ExitLoop ;exit while/wend
    EndIf
    $iPos = StringInStr($BMP1Data, $searchFor1, 2, 1, $iPos + $imgBytes)
    If $iPos = 0 Then ExitLoop ;nicht gefunden
    Else ;ipos ist innerhalb eines farbbits und nicht am anfang
    $iPos = StringInStr($BMP1Data, $searchFor1, 2, 1, $iPos + 1)
    If $iPos = 0 Then ExitLoop
    EndIf
    Else
    ExitLoop
    EndIf
    WEnd
    SetError(1, 0, 0)
    Return 0 ;
    EndFunc ;==>findBMP

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

    ;aus einer Datei oder einem Screenshot die Pixeldaten im BGR-Format in einen String schreiben
    ;Originalfunc by JunkEW , modified by Andy@ http://www.autoit.de finds the exact match at screen
    Func _GetImage($BMPFile, ByRef $BMPDataStart, ByRef $Width, ByRef $Height, ByRef $Stride, $imgBytes = 3)
    Local $Scan0, $pixelData, $hbScreen, $pBitmap, $pBitmapCap, $handle
    ; Load the bitmap to search in
    If $BMPFile = $BitmapFullscreen Then
    $hbScreen = _ScreenCapture_Capture("", 0, 0, -1, -1, False)
    $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
    ;try to get a handle
    $handle = WinGetHandle($BMPFile)
    If @error Then
    ;Assume its an unknown handle so correct filename should be given
    $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
    Else
    $hbScreen = _ScreenCapture_CaptureWnd("", $handle, 0, 0, -1, -1, False)
    $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    EndIf
    EndIf
    ;_GDIPlus_BitmapLockBits gibt $tagGDIPBITMAPDATA-Struktur zurück
    $BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
    If @error Then MsgBox(0, "", "Error locking region " & @error)
    $Stride = DllStructGetData($BitmapData, "Stride");Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
    $Width = DllStructGetData($BitmapData, "Width");Image width - Number of pixels in one scan line of the bitmap.
    $Height = DllStructGetData($BitmapData, "Height");Image height - Number of scan lines in the bitmap.
    $pixelFormat = DllStructGetData($BitmapData, "PixelFormat");Pixel format - Integer that specifies the pixel format of the bitmap
    $Scan0 = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.
    $pixelData = DllStructCreate("ubyte lData[" & (Abs($Stride) * ($Height)) & "]", $Scan0)
    $BMPDataStart = DllStructGetData($pixelData, "lData") ;string, in dem die pixeldaten im BGR-Format stehen

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

    _GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
    _GDIPlus_ImageDispose($pBitmap)
    _WinAPI_DeleteObject($pBitmap)
    EndFunc ;==>GetImage

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

    Func _ctrl_alt_up() ;fenster verkleinern
    $MagHeight = (Round($MagHeight / $MagZoom)) * $MagZoom - $MagZoom
    If $MagHeight < $ZoomWindowFactor * 3 Then $MagHeight = $ZoomWindowFactor * 3
    _movewindows()
    EndFunc ;==>_ctrl_alt_up

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

    Func _ctrl_alt_down() ;fenster vergrößern
    $MagHeight = (Round($MagHeight / $MagZoom)) * $MagZoom + $MagZoom
    If $MagHeight > $ZoomWindowFactor * $maxBxHzoomfaktor Then $MagHeight = $ZoomWindowFactor * $maxBxHzoomfaktor
    _movewindows()
    EndFunc ;==>_ctrl_alt_down

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

    Func _ctrl_alt_left()
    $MagWidth = (Round($MagWidth / $MagZoom)) * $MagZoom - $MagZoom
    If $MagWidth < $ZoomWindowFactor * 3 Then $MagWidth = $ZoomWindowFactor * 3
    _movewindows()
    EndFunc ;==>_ctrl_alt_left

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

    Func _ctrl_alt_right()
    $MagWidth = (Round($MagWidth / $MagZoom)) * $MagZoom + $MagZoom
    If $MagWidth > $ZoomWindowFactor * $maxBxHzoomfaktor Then $MagWidth = $ZoomWindowFactor * $maxBxHzoomfaktor
    _movewindows()
    EndFunc ;==>_ctrl_alt_right

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

    Func _movewindows() ;alle Fenster vergrössern/verkleinern und die Button-Position anpassen
    _GUICtrlStatusBar_ShowHide($StatusBar, @SW_HIDE) ;statusbar nicht sichtbar, damit sie nicht die buttons "überschreibt"
    If $MagWidth < $ZoomWindowFactor * 16 Then WinMove($gui, "", Default, Default, $ZoomWindowFactor * 16 + 20, $MagHeight + 100)
    If $MagWidth >= $ZoomWindowFactor * 16 Then WinMove($gui, "", Default, Default, $MagWidth + 20, $MagHeight + 100)
    _GUICtrlStatusBar_Resize($StatusBar)
    _GUICtrlStatusBar_ShowHide($StatusBar, @SW_SHOW)
    WinMove($titlepic, "", Default, Default, $MagWidth, $MagHeight)
    $a = WinGetPos($gui)
    GUICtrlSetPos($button_anleitung, 7, $a[3] - 80)
    GUICtrlSetPos($button_finden, $a[2] - 193, $a[3] - 80)
    _dock()
    EndFunc ;==>_movewindows

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

    Func _iskeypressed() ;wenn einer der $allowed-Keys gedrückt ist, rückgabe 1 sonst 0
    $allowed = "6B;6D;25;26;27;28;11;12" ;siehe Hilfe zu _ispressed()
    Global $aKey = StringSplit($allowed, ";", 2)
    For $i = 0 To UBound($aKey) - 1
    If _IsPressed($aKey[$i]) Then Return 1
    Next
    Return 0
    EndFunc ;==>_iskeypressed

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

    Func _AnalysePic($file) ;rückgabe: nach anzahl sortiertes 2-dimensionales array[farbe][anzahl]
    Dim $BMP1Data = "", $BMP1Width = 0, $BMP1Height = 0, $BMP1LineWidth = 0, $imgBytes = 3, $RGB = ""
    Dim $BMP2Data = "", $BMP2Width = 0, $BMP2Height = 0, $BMP2LineWidth = 0
    Local $listindex = 0, $flag = 0, $maxanzahl = 10000000, $prozent = 0
    Dim $aret[4] ;anzahl, posx, posy, color
    Dim $aliste[1]
    _GetImage($BitmapFullscreen, $BMP1Data, $BMP1Width, $BMP1Height, $BMP1LineWidth, $imgBytes)
    $BMP1Data = BinaryToString($BMP1Data)
    ; Load the bitmap to find
    _GetImage($file, $BMP2Data, $BMP2Width, $BMP2Height, $BMP2LineWidth, $imgBytes)
    $BMP2Data = BinaryToString($BMP2Data)
    $t = TimerInit()
    For $h = 0 To $BMP2Height - 1 ;pic durchsuchen
    If $exitflag = 1 Then ExitLoop
    For $b = 0 To $BMP2Width - 1
    $pos = $h * $BMP2LineWidth + ($b * 3 + 1)
    $prozent += 100 / $BMP2Height / $BMP2Width
    $tooltip = ToolTip(StringFormat("Analyse läuft : %.0f%%", $prozent) & @CRLF & "Niedrigste Pixelanzahl " & $maxanzahl & @CRLF & Int(TimerDiff($t) / 1000) & " Sekunden", $DesktopWidth / 2, $DesktopHeight / 2)
    $color = StringMid($BMP2Data, $pos, 3) ;farbe 3 byte, kein hexcode
    $flag = 0
    For $i = 1 To UBound($aliste) - 1
    If $color = $aliste[$i] Then ;farbe im array vorhanden, nächste
    $flag = 1
    ExitLoop
    EndIf
    Next
    If $flag = 0 Then ; keine farbe gefunden im array, neue farbe anlegen
    $listindex += 1
    ReDim $aliste[$listindex]
    $aliste[$listindex - 1] = $color ;farbe
    $anzahl = _pixeltextsearch($BMP1Data, $BMP1LineWidth, $color) ;anzahl color-pixel
    If $anzahl < $maxanzahl Then
    $maxanzahl = $anzahl
    $aret[0] = $anzahl
    $aret[1] = $b ;hotspot x
    $aret[2] = $h ;hotspot y
    $aret[3] = Hex(Asc(StringMid($color, 3, 1)), 2) & Hex(Asc(StringMid($color, 2, 1)), 2) & Hex(Asc(StringMid($color, 1, 1)), 2)
    If $anzahl < 10 Then ;wenn nur 10 Pixel auf dem Bildschirm diese Farbe haben, dann return
    ToolTip("")
    Return $aret
    EndIf
    EndIf
    EndIf
    Next
    Next
    ToolTip("")
    ; _arraydisplay($aret)
    Return $aret
    EndFunc ;==>_analysepic

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

    Func _pixeltextsearch($bmp_data, $bmpstride, $searchcolor); im bmpdata die rgb finden, searchcolor sind die 3 RGB-byte als string
    Local $pos = 0, $anz = 0
    ;~ stringreplace($bmp_data,$searchcolor,$searchcolor,-1,1)
    ;~ return @extended
    If StringInStr($bmp_data, $searchcolor, 1, 500) = 0 Then ;wenn weniger wie 500/3(byte) mal die Farbe vorhanden ist, dann
    Do
    $pos = StringInStr($bmp_data, $searchcolor, 1, 1, $pos + 3) ;schnelle variante ohne prüfung auf bytegrenzen
    $anz += 1
    Until $pos = 0
    Else
    $anz = 500
    EndIf
    Return $anz
    EndFunc ;==>_pixeltextsearch

    [/autoit]
  • Sehr fein, wird sofort in die nächste Version übernommen, die sollte am Wochenende fertig sein ^^

  • Neue Version, siehe ersten Post!

  • Hallo!
    Erstmal muß ich sagen, das du das echt fein geregelt hast!! Funzt gut bei mir!
    Da ich dein Script momentan in Benutzung habe, hab ich mal ne Frage an dich: Hast du schon das Scrollen innerhalb von Browsern realisiert?!? Weil bei meiner XP Maschiene muss ich immer manuell innberhalb der Seite einen Scroller nach unten verschieben bevor der zu klickende Button sichtbar wird. Dann wird er ja auch geklickt, aber da es für eine Automatisierung ist wird diese auch nicht überwacht...
    Und ist es so richtig das ich immer '_GDIPlus_Startup' und '_GDIPlus_Shutdown' Manuell ausführen muss, da es sonst nicht richtig läuft?!?

    Grüsse!

  • Hi,

    Zitat

    Hast du schon das Scrollen innerhalb von Browsern realisiert?!?

    In den ersten hier geposteten Versionen war es noch enthalten, ich hatte es rausgenommen weil ich es a) den Browsergame-Fernsteuerungen nicht allzuleicht machen wollte ;) , und b) die Abfrage "Seitenende" nicht besonders zuverlässig in allen Fällen funktionierte (bei allen Browsern).

    Zitat

    Weil bei meiner XP Maschiene muss ich immer manuell innberhalb der Seite einen Scroller nach unten verschieben bevor der zu klickende Button sichtbar wird.

    Simple Lösung: ein SEND pgdn, nachdem das Browserfenster mit der neuen Seite geöffnet wurde 8)
    Ich hatte schon mit div. Scroll-udf´s herumexperimentiert, wie gesagt, Browser sind da manchmal bissl eigen...besonders mit der Rückmeldung, ob das pgdn ausgeführt wurde. Man könnte natürlich abfragen, ob sich der Seiteninhalt geändert hat ;) .

    Allerdings sind meine Anwendungen noch nicht zeitkritisch, solange das Programm schneller ist als jeder Mensch der im 3-Schichtbetrieb 8h lang auf den Monitor stiert, habe ich keinen Handlungsbedarf.

    Zitat

    Und ist es so richtig das ich immer '_GDIPlus_Startup' und '_GDIPlus_Shutdown' Manuell ausführen muss,

    Die Beispiele sollten alle laufen, ich habe hier schon lange nicht mehr geupdatet, der "Bedarf" scheint nicht sehr gross zu sein, wenn man nicht die gängigen "bösen" Begriffe in den Postings hier im Forum spammt :rofl:

  • Hallo,
    wahrscheinlich gibt es ein mir nicht bekanntes Problem mit der Prospeed.dll (welches System?).Ggf funktioniert diese nicht auf 64Bitsystemen.
    Du kannst aber auch mit etwas Verzicht auf Geschwindigkeit die prospeed.dll im Verzeichnis löschen. Dann läuft reiner AutoItcode, auch unter 64Bit.

  • Doch die prospeed funkioniert auf Win7x64! Hab ich ja selber hier... Hasst du vielleicht die prospeed.dll in ein anderes Verzeichnis gelegt??? Hatte ich auch gemacht und schlauerweise die Pfade angepasst; aber Pustekuchen, geht nicht!

    Grüsse!

    Einmal editiert, zuletzt von Techmix (24. Januar 2011 um 00:46)

  • naja, die beiden verwendeten Prospeed-Funktionen sind derart simpel, die kann ich bei Bedarf in 10-20 Zeilen Asm unterbringen.
    Ggf sogar in eine mini-Dll packen. Da geht was :D
    Wobei die Geschwindigkeit auch mit "native" AutoItcode ausreichend sein sollte, jedenfalls für "normale" Anwendungen :D

  • Moin!
    Ich nutze ja immer noch PTB, um ein PopUp schliessen zu können (Auf meinem 'Server' das Teamview Pop). Also habe ich mir einen PopUp Closer geschrieben der alle 2,5 Sekunden prüft ob das PopUp jetzt da ist oder nicht. So und dieses Script ist iwann Brutal abgestürzt mit der Meldung 'Error allocating Memory' (oder so)... Ich fing an mich zu fragen warum, und habe den Fehler Rekonstruiert.
    Nach etwa 2 Tagen Laufzeit hatte mein Script 980MB verbrauch im Taskmanger!! Also, wenn ich den Befehl '_PtB_ClickBMP' aufrufe und alles durch ist, behällt er immer 16KB Speicher bei; es wird also nicht der ganze Speicher wieder freigegeben. Und eben diese 16KB Speicher machens auf Dauer; alle 2,5 Sekunden 16KB macht übern Daumen in der Stunde 23MB Speicher die nicht wieder Freigegeben werden!

    Spoiler anzeigen
    [autoit]

    Func __PopUpCloser()
    ; TeamViewer-PopUp
    _GDIPlus_Startup()
    $a = _PtB_ClickBMP(@ScriptDir & "\Data\EP_SearchImg\TeamViewerPopUp.bmp", "", "left", 0)
    if IsArray($a) then
    MouseMove($a[0]+346, $a[1]+76, 0)
    MouseDown("left")
    MouseUp("left")
    EndIf
    _GDIPlus_Shutdown()

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

    ; Antivir-PopUp
    if ProcessExists("avnotify.exe") then ProcessClose("avnotify.exe")
    EndFunc

    [/autoit]


    Das ist der PopUp-Closer. Ich hatte schon versucht für '$hWin' andere Parameter anzugeben; ändert aber nichts am Speicherverbrauch.

    Ist dir dieses Problem auch aufgefallen?!?
    Weißt du eine Lösung dafür?

    Grüsse von
    Techmix!

    P.S:
    Ich hatte vermutet das es vielleicht an den GDI Funktionen liegen könnte, konnte aber nichts wirklich finden...

  • Ich verwende von Zeit zu Zeit diese Funktion, um den Speicher bei hungrigen Programmen wieder freizugeben:

    [autoit]

    Func _ReduceMemory($i_PID = -1)

    If $i_PID <> -1 Then
    Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
    Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
    DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
    Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf

    Return $ai_Return[0]
    EndFunc;==> _ReduceMemory()

    [/autoit]