• Offizieller Beitrag

    Ich brauchte gerade mal eine Funktion zum anzeigen von Bildern. Diese soll die Bilder (nach Möglichkeit) komplett (100%) in einem Fenster anzeigen. Wenn die Bilder eine höhere Auflösung haben als der Monitor, dann sollen sie entsprechend (proportional) runterskaliert werden.
    So weit habe ich das auch schon fertig (deshalb hier in Skripte). :)
    Es gibt nur noch ein Problem mit dem neuzeichnen, wenn man ein anderes Fenster darüber bewegt. An sich ja kein Problem, das kann man ja mit WM_PAINT lösen (einfach neuzeichnen lassen), aber und jetzt kommt das Schwierige, ich möchte das gern als UDF haben.
    Der GUIRegister-Aufruf muss also von der Funktion "_ShowImage" aus erfolgen. Allerdings sind die Variablen ja lokal (möchte gern auf globale Variablen verzichten) und jetzt weiß ich nicht, wie ich das sonst lösen kann. Jemand eine Idee?

    Problem erledigt! Jetzt funktioniert auch das neuzeichnen. :)

    Spoiler anzeigen
    [autoit]


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

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

    #cs
    Beispiel - Anfang
    #ce
    Opt('GUIOnEventMode', 1)
    GUICreate('Beispiel', 600, 400)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_End')
    GUICtrlCreateButton('Zeige Bild...', 20, 20, 160, 35)
    GUICtrlSetOnEvent(-1, '_Show')
    GUISetState()
    While Sleep(50)
    WEnd

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

    Func _End()
    Exit
    EndFunc ;==>_End

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

    Func _Show()
    Local $sPath
    $sPath = FileOpenDialog('Bilddatei auswählen', @WorkingDir, 'Images (*.jpg;*.bmp;*.png)', 3)
    If Not @error Then _ShowImage($sPath)
    EndFunc ;==>_Show
    #cs
    Beispiel - Ende
    #ce

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

    ;===============================================================================
    ; Function Name: _ShowImage($sImgFile)
    ; Description:: Zeigt ein Bild in einem separaten Fenster an.
    ; Parameter(s): $sImgFile = Pfad zu dem Bild
    ; Requirement(s): #include <GDIPlus.au3>
    ; #include <GUIConstantsEx.au3>
    ; #include <WindowsConstants.au3>
    ; Return Value(s): wenn die Datei nicht existiert wird @error auf "1" gesetzt
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ShowImage($sImgFile)
    If Not FileExists($sImgFile) Then Return SetError(1, 0, 0)
    Local $hGui, $hBitmap, $hGraphic, $aWinPos, $iFrameWidth, $iFrameHeight, $iImgWidth, $iImgHeight, $iFactor
    Local $iOldOpt = Opt('WinTitleMatchMode', 4)
    Local $aTaskbarPos = WinGetPos('classname=Shell_TrayWnd')
    Opt('WinTitleMatchMode', $iOldOpt)
    $iOldOpt = Opt('GUIOnEventMode', 0)
    Local $iGuiWidth = 300, $iGuiHeight = 300
    $hGui = GUICreate('Calc Frame', $iGuiWidth, $iGuiHeight, -1, -1, BitOR($WS_SYSMENU, $WS_CAPTION))
    _GDIPlus_Startup()
    $hBitmap = _GDIPlus_BitmapCreateFromFile($sImgFile)
    $aWinPos = WinGetPos($hGui)
    GUIDelete($hGui)
    $iFrameWidth = $aWinPos[2] - $iGuiWidth
    $iFrameHeight = $aWinPos[3] - $iGuiHeight + 10
    $iImgWidth = _GDIPlus_ImageGetWidth($hBitmap)
    $iImgHeight = _GDIPlus_ImageGetHeight($hBitmap)
    $iFactor = $iImgWidth / $iImgHeight
    While $iImgHeight > ($aTaskbarPos[1] - $iFrameHeight)
    $iImgHeight -= 1
    $iImgWidth -= $iFactor
    WEnd
    While $iImgWidth > (@DesktopWidth - $iFrameWidth)
    $iImgHeight -= 1
    $iImgWidth -= $iFactor
    WEnd
    $iImgWidth = Int($iImgWidth)
    ConsoleWrite($iImgWidth & ' x ' & $iImgHeight & ' ' & $iFrameWidth & ' x ' & $iFrameHeight & @CR)
    $hGui = GUICreate('Show Image', $iImgWidth, $iImgHeight, -1, -1, BitOR($WS_SYSMENU, $WS_CAPTION))
    GUISetState()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)
    _RedrawImage($hGraphic, $hBitmap, $iImgWidth, $iImgHeight)
    GUIRegisterMsg($WM_PAINT, '_WM_PAINT')
    While True
    $aMsg = GUIGetMsg(1)
    If $aMsg[1] = $hGui And $aMsg[0] = $GUI_EVENT_CLOSE Then ExitLoop
    WEnd
    GUIRegisterMsg($WM_PAINT, '')
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    GUIDelete($hGui)
    Opt('GUIOnEventMode', $iOldOpt)
    EndFunc ;==>_ShowImage

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

    Func _WM_PAINT($hWnd, $Msg, $wParam, $lParam)
    If $hWnd = WinGetHandle('Show Image') Then _RedrawImage()
    Return $GUI_RUNDEFMSG
    EndFunc ;==>_WM_PAINT

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

    Func _RedrawImage($par1 = 0, $par2 = 0, $par3 = 0, $par4 = 0)
    Local Static $hGraphic, $hBitmap, $iImgWidth, $iImgHeight
    If $par1 <> 0 Then
    $hGraphic = $par1
    $hBitmap = $par2
    $iImgWidth = $par3
    $iImgHeight = $par4
    EndIf
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iImgWidth, $iImgHeight)
    EndFunc ;==>_RedrawImage

    [/autoit]
  • Hi

    du könntest in der Schleife auf WM_Paint abfragen!

    theoretisch sollte das so in etwa gehen, jedoch bekomm ich keine WM_Paint Messages rein!?

    [autoit]

    $PM_NOREMOVE = 0x00
    $PM_NOYIELD = 0x02
    $PM_QS_PAINT = 0x20
    $hUser32Dll = DllOpen("user32.dll")
    $msgStruct = DllStructCreate("hwnd Handle;uint message;wparam wParam;lparam lParam;dword Time;ptr Point")
    ...While...
    DllCall($hUser32Dll, "int", "PeekMessage", "ptr", DllStructGetPtr($msgStruct), "hwnd", 0, "int", 0, "int", 0, "int", $PM_QS_PAINT)
    If DllStructGetData($msgStruct, 2) = $WM_PAINT Then _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iImgWidth, $iImgHeight)

    [/autoit]

    Wenn man $PM_QS_PAINT weglässt, dann bekommt man auch nur die Mausmessages!
    Da muß jetzt wohl ein Profi ran ;)

    mfgE

  • Folgende idee:

    Du erstellst eine Local Static Variable für den handle in der WM Paint funktion.
    Wenn die _ShowImage funktion aufgerufen wird, übergibst du den Handle einmal an die Static Variable in WM_PAINT. Danach bleibt dieser Wert gespeichert.

    Siehe hier wo ich das ganze mal mit beispiel gemacht hatte:
    http://www.autoitbot.de/off-topic-auto…atic-variablen/

  • Die Idee mit den Static Variablen finde ich sehr gut! :thumbup:

    Hab das gleich mal ausprobiert:

    Spoiler anzeigen
    [autoit]

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

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

    #cs
    Beispiel - Anfang
    #ce
    Opt('GUIOnEventMode', 1)
    Global $hGui = GUICreate('Beispiel', 600, 400)
    GUISetOnEvent($GUI_EVENT_CLOSE, '_End')
    GUICtrlCreateButton('Zeige Bild...', 20, 20, 160, 35)
    GUICtrlSetOnEvent(-1, '_Show')
    GUISetState()

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

    _GDIPlus_Startup()
    Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)

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

    GUIRegisterMsg($WM_PAINT, "WM_PAINT")

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

    While Sleep(50)
    WEnd

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

    Func _End()
    Exit
    EndFunc ;==>_End

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

    Func _Show()
    Local $sPath
    $sPath = FileOpenDialog('Bilddatei auswählen', @WorkingDir, 'Images (*.jpg;*.bmp;*.png)', 3)
    If Not @error Then _ShowImage($sPath)
    EndFunc ;==>_Show
    #cs
    Beispiel - Ende
    #ce

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

    ;===============================================================================
    ; Function Name: _ShowImage($sImgFile)
    ; Description:: Zeigt ein Bild in einem separaten Fenster an.
    ; Parameter(s): $sImgFile = Pfad zu dem Bild
    ; Requirement(s): #include <GDIPlus.au3>
    ; #include <GUIConstantsEx.au3>
    ; #include <WindowsConstants.au3>
    ; Return Value(s): wenn die Datei nicht existiert wird @error auf "1" gesetzt
    ; Author(s): Oscar (http://www.autoit.de)
    ;===============================================================================
    Func _ShowImage($sImgFile)
    If Not FileExists($sImgFile) Then Return SetError(1, 0, 0)
    Local $hGui, $hBitmap, $hGraphic, $aWinPos, $iFrameWidth, $iFrameHeight, $iImgWidth, $iImgHeight, $iFactor
    Local $iOldOpt = Opt('WinTitleMatchMode', 4)
    Local $aTaskbarPos = WinGetPos('classname=Shell_TrayWnd')
    Opt('WinTitleMatchMode', $iOldOpt)
    $iOldOpt = Opt('GUIOnEventMode', 0)
    Local $iGuiWidth = 300, $iGuiHeight = 300
    $hGui = GUICreate('Calc Frame', $iGuiWidth, $iGuiHeight, -1, -1, BitOR($WS_SYSMENU, $WS_CAPTION))
    Local $bGdiStarted = False
    Switch $ghGDIPDll
    Case 0
    _GDIPlus_Startup()
    Case Else
    $bGdiStarted = True
    EndSwitch
    $hBitmap = _GDIPlus_BitmapCreateFromFile($sImgFile)
    $aWinPos = WinGetPos($hGui)
    GUIDelete($hGui)
    $iFrameWidth = $aWinPos[2] - $iGuiWidth
    $iFrameHeight = $aWinPos[3] - $iGuiHeight + 10
    $iImgWidth = _GDIPlus_ImageGetWidth($hBitmap)
    $iImgHeight = _GDIPlus_ImageGetHeight($hBitmap)
    $iFactor = $iImgWidth / $iImgHeight
    While $iImgHeight > ($aTaskbarPos[1] - $iFrameHeight)
    $iImgHeight -= 1
    $iImgWidth -= $iFactor
    WEnd
    While $iImgWidth > (@DesktopWidth - $iFrameWidth)
    $iImgHeight -= 1
    $iImgWidth -= $iFactor
    WEnd
    $iImgWidth = Int($iImgWidth)
    ConsoleWrite($iImgWidth & ' x ' & $iImgHeight & ' ' & $iFrameWidth & ' x ' & $iFrameHeight & @CR)
    $hGui = GUICreate('Show Image', $iImgWidth, $iImgHeight, -1, -1, BitOR($WS_SYSMENU, $WS_CAPTION))
    If @OSVersion = "WIN_XP" Then WinSetTrans($hGui,"",0xFF)
    GUISetState()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGui)

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

    Local $Struct = DllStructCreate("ptr;ptr;dword;dword;hwnd;ptr")
    DllStructSetData($Struct, 1, $hGraphic)
    DllStructSetData($Struct, 2, $hBitmap)
    DllStructSetData($Struct, 3, $iImgWidth)
    DllStructSetData($Struct, 4, $iImgHeight)
    DllStructSetData($Struct, 5, $hGui)
    Local $wProcNew = DllCallbackRegister("__ShowImage_Proc", "ptr", "hwnd;uint;long;ptr")
    Local $wProcOld = _WinAPI_SetWindowLong(WinGetHandle($hGui), $GWL_WNDPROC, DllCallbackGetPtr($wProcNew))
    DllStructSetData($Struct, 6, $wProcOld)
    __ShowImage_Proc(-1, 0, $Struct, 0)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iImgWidth, $iImgHeight)
    While True
    $aMsg = GUIGetMsg(1)
    ;If $aMsg[0] = $GUI_EVENT_PRIMARYDOWN Then _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iImgWidth, $iImgHeight)
    If $aMsg[1] = $hGui And $aMsg[0] = $GUI_EVENT_CLOSE Then ExitLoop
    WEnd
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_SetWindowLong($hGui, $GWL_WNDPROC, $wProcOld)
    DllCallbackFree($wProcNew)
    If Not $bGdiStarted Then _GDIPlus_Shutdown()
    GUIDelete($hGui)
    Opt('GUIOnEventMode', $iOldOpt)
    EndFunc ;==>_ShowImage

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

    Func __ShowImage_Proc($hWnd, $uMsg, $wParam, $lParam)
    Local Static $hGraphic, $hBitmap, $iImgWidth, $iImgHeight, $hGui, $wProcOld
    Switch $hWnd
    Case -1 ; Variablen mit Daten befüllen
    $hGraphic = DllStructGetData($wParam, 1)
    $hBitmap = DllStructGetData($wParam, 2)
    $iImgWidth = DllStructGetData($wParam, 3)
    $iImgHeight = DllStructGetData($wParam, 4)
    $hGui = DllStructGetData($wParam, 5)
    $wProcOld = DllStructGetData($wParam, 6)
    Return
    Case $hGui
    If $uMsg = $WM_PAINT Or $uMsg = $WM_ERASEBKGND Then _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iImgWidth, $iImgHeight)
    EndSwitch
    Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $uMsg, $wParam, $lParam)
    EndFunc ;==>__ShowImage_Proc

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

    Func WM_Paint($hWnd, $uMsg, $wParam, $lParam)
    If $hWnd = $hGui Then _GDIPlus_GraphicsDrawLine($hGraphic, Random(0, 600, 1), Random(100, 400, 1), Random(0, 600, 1), Random(100, 400, 1))
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_Paint

    [/autoit]

    so kommt man auch nicht mit schon registrierten WM_PAINT Funtionen in Konflikt

    mfgE

    • Offizieller Beitrag

    Ah, die Idee mit den Static-Variablen ist gut. Damit geht das! Danke, SEuBo! :thumbup:
    Habe das Skript angepasst (siehe Post #1).

    Jetzt klappt das neuzeichnen, wenn man mit einem anderen Fenster drüberfährt. Allerdings "ruckt" es noch etwas, wenn man das Fenster mit dem Bild etwas ausserhalb des Bildschirms bewegt und dann wieder zurück.
    Falls dafür noch jemand eine Lösung kennt?

    Edit:  eukalyptus: Dein Skript funktioniert bei mir nicht. Da stürzt AutoIt ab (AutoIT3.exe ended.rc:-1073741819) wenn ich ein Bild lade.

  • Zum Flacken: vielleicht hilft

    [autoit]

    If @OSVersion = "WIN_XP" Then WinSetTrans($hGui,"",0xFF)

    [/autoit]

    des weiteren sollte es so aussehen:

    [autoit]

    If $hWnd > -1 Then Return _WinAPI_CallWindowProc($wProcOld, $hWnd, $uMsg, $wParam, $lParam)

    [/autoit]


    sonst wird das schon beim Variablensetzen aufgerufen!


    Edit verdammt! jetzt stürzt es bei mir auch ab
    war wohl nicht so gut ^^