Fremdes Fenster mit GDI+ bearbeiten

  • Ist es möglich, in einem Fenster eines anderen Programms zu zeichnen?

    Ich habe das Beispielscript von der GDI+-UDF abgeändert, passiert ist allerdings nichts.

    Einmal editiert, zuletzt von Lava (6. Januar 2010 um 15:57)

  • na klar ist das möglich...

    Spoiler anzeigen
    [autoit]

    #include <WindowsConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <WinAPI.au3>

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

    $PID=run(@SystemDir&"\calc.exe") ;PID holen
    winwaitactive("Rechner") ;warten bis rechner aktiv

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

    _GDIPlus_Startup()
    $hwnd=wingethandle("Rechner") ;handle des fensters holen
    $breite=_WinAPI_GetWindowWidth($hWnd) ;breite & Hoehe des Fensters holen
    $hoehe=_WinAPI_GetWindowheight($hWnd)
    global $graphics=_GDIPlus_GraphicsCreateFromHwnd($hwnd);"leinwand" erstellen

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

    global $hBitmap = _GDIPlus_BitmapCreateFromFile(@SystemDir & "\oobe\images\mslogo.jpg");bild holen
    _GDIPlus_GraphicsDrawImage($graphics, $hBitmap, 0, 50);bild zeichnen
    _GDIPlus_GraphicsFillEllipse($graphics,100,100,50,50);kreis zeichnen
    _GDIPlus_GraphicsDrawEllipse($graphics,10,10,80,80);kreis zeichnen

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

    adlibregister("PAINT",100) ;jede 100 ms die grafik auffrischen

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

    do
    until not WinExists("Rechner") ;solange, bis rechner beendet wird
    ;aufräumen
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_ImageDispose($hbitmap)
    _GDIPlus_Shutdown()
    exit

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

    Func PAINT() ;sorgt dafür, daß bei jedem neuzeichnen des Fensters auch die grafiken mitgezeichnet werden
    _GDIPlus_GraphicsDrawImage($graphics, $hBitmap, 0, 50)
    _GDIPlus_GraphicsFillEllipse($graphics,100,100,50,50)
    _GDIPlus_GraphicsDrawEllipse($graphics,10,10,80,80)
    EndFunc ;==>MY_WM_PAINT

    [/autoit]
  • Ein Schönheitsfehler hat dein Skript, nämlich 100% CPU Last ;)

    Einfach Zeile 25 mit dieser ersetzten: until not WinExists("Rechner") * Sleep(30)

    Ciao,
    UEZ :P

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • ah ok.

    Problematisch ist es ja dann, wenn das Programm den Bildschirm sehr häufig aktualisiert.
    Auch wenn man so oft wie möglich drüberzeichnet lässt sich ein Flimmern nicht ganz verhindern.

    Ich denke da ist dann nichts zu machen, oder täusche ich mich?

  • Hmm hab das Problem, dass die adlibregister-Funktion nicht funktioniert.
    Ich habe die neuste Version und es auch mehrmals mit der beta versucht.

    Spoiler anzeigen

    Grundkenntnisse in: C++, JavaScript
    Sehr gute Kenntnisse: PHP, JAVA, C und näturlich AutoIt


    Klaviatur, Anhang UDF, GDI+ Mühle

    Zitat

    "Wenn einen um 20h der Pizzadienst anruft und fragt, ob man's nur vergessen hat und ob man das gleiche
    möchte wie immer -- dann sollte man sein Bestellverhalten evtl überdenken"

  • ah ok.

    Problematisch ist es ja dann, wenn das Programm den Bildschirm sehr häufig aktualisiert.
    Auch wenn man so oft wie möglich drüberzeichnet lässt sich ein Flimmern nicht ganz verhindern.

    Ich denke da ist dann nichts zu machen, oder täusche ich mich?

    Du täuscht dich nicht! Warum willst du in ein anderes Programm hinein zeichnen?

    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Schade.

    Es geht um ein Spiel, dort lese ich Spielernamen mit einer Art OCR aus.
    Bei bestimmten Personen sollen dann Markierungen angebracht werden, zB ein roter Kreis.

  • Das Problem ist, dass das Zeichnen in das Spiel asynchron läuft und es zwangsmäßig flimmert. Auch in Andy's Beispiel flimmert der gefüllte Kreis, wenn du mit der Maus drüber fährst!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Zitat

    Auch in Andy's Beispiel flimmert der gefüllte Kreis, wenn du mit der Maus drüber fährst!

    Ja, das kommt zwangsläufig durch die "drunterliegenden" Tasten, welche dann kurzzeitig erscheinen.
    Ich wollte das per WM_Paint (Fenster(teile) neuzeichnen) abfangen, leider hab ich in meinem Programm garkeine GUI um das zu registrieren^^. In Vista/Win7 gibt es eine Funtion, um den Fensterrefresh doublezubuffern, damit wärs dann einfach. Hab aber nur XP...

    GGf könnte man auch den Bereich, den die "Zeichnung" überdeckt, vom refreshen ausnehmen, ähnlich wie beim Beispiel zu

    [autoit]

    _WinAPI_CombineRgn()

    [/autoit]

    . Wenn man dort das Fenster TOPMOST macht und dann den transparenten Modus auswählt, kann man von den Buttons halb verdeckte Schalter der darunterliegenden GUI betätigen, ohne daß irgendetwas flimmert.

  • Ich habe das mit einem zweiten Fenster mal weiter verfolgt.

    Es wird so erstellt:

    [autoit]

    GUICreate("Unsichtbarar Titel", $width, $height, $left, $top, $WS_POPUP, bitor($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW))
    GUISetState()

    [/autoit]

    Das Problem: Wenn GUISetState aufgerufen wird, ist das neue Fenster das aktive Fenster, und das ist schlecht.
    Gibt es eine Möglichkeit, das Fenster sichtbar zu machen, ohne dass es aktiv wird?

  • Ich habe einfach jeden wichtigen Buchstaben abgespeichert. Eine DLL bekommt dann die Such-Koordinaten und vergleicht dann Pixel für Pixel.

    Edit: Mein Aufruf sieht jetzt so aus:

    [autoit]

    GUICreate("Unsichtbarar Titel", $width, $height, $left, $top, bitor($WS_POPUP, $WS_VISIBLE), bitor($WS_EX_TOPMOST, $WS_EX_TOOLWINDOW))

    [/autoit]

    Wenn ich das Fenster nicht mehr sehen will, verschiebe ich es ins Nirvana. So gehts natürlich auch.

    Einmal editiert, zuletzt von Lava (6. Januar 2010 um 15:57)