Jump to content

GUI Zoom, img move whitin a GUI [Solved]


Acce
 Share

Recommended Posts

1 hour ago, UEZ said:

I'm wondering how you get these effects when the lines are commented out. :huh2:

To answer your question, when the 5 lines are commented out, this is the line that will generate the vertical stretching effect, as seen in the pic above :

GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

Now if we comment out this line too, the vertical stretching will disappear... but any zoom won't display the full image anymore, everything seems to be linked !

Edited by pixelsearch
Link to comment
Share on other sites

@UEZ : good news :)
Problems seem to be solved after replacing the 5 lines you mentioned :

If _CompareSize() <> 0 Then
    _GDIPlus_ImageDispose($hImage_resized)
    $hImage_resized = _GDIPlus_ImageResize($hImage, $iX, $iY)
    If @error Then _Quit("_GDIPlus_ImageResize #2", $sFileName, @error, @extended)
EndIf

With that single line :

_CompareSize()

This will force $iX & $iY when needed. The return value was useful when the function was initially called at the beginning of the script, to resize the original file if necessary. But here, the return value isn't useful anymore.

I'm gonna amend the script already posted, fingers crossed !
If you still got a crash (I doubt it as you didn't have a crash without the 5 lines) then I'll add the dummy control.

Thanks for your help.

 

Link to comment
Share on other sites

U guys mind taking a look at my version?

Now I have been able to make the scroll work as well as the zoom function. There are a few issues somehow it scrolls opposite of what i want for example when i click and drag downwards the image goes down this is a bit award same behavior when puling either direction 

Also I have not been able to figure out how to calculate the edges for the image when its in "zoom" state . Here is my lates version:

#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <Misc.au3>
HotKeySet("{ESC}", "Terminate")
Global Const $dll = DllOpen("user32.dll")
Global $sx, $z = 5, $sy, $mc2, $f, $scroll_x = 0, $scroll_y,$current_iPos_y, $RQGUI_POS[3] = [280, 325, 0]
Global $g_iIDC = -1, $g_iNewIDC = 0
Global $aDim
Global $g_aArray = StringSplit("Hand|AppStarting|Arrow|Cross|Help|IBeam|Icon (obsolete)|No|" & _
        "Size (obsolete)|SizeAll|SizeNESW|SizeNS|SizeNWSE|SizeWE|UpArrow|Wait|None", "|", 2) ; The flag parameter is set to flag = 2 as we don't require the total count of the array.
    ; --- Create GUI ---
$hGUI = GUICreate('MyGUI', @DesktopWidth-200, @DesktopHeight-200 , 100, 100, $WS_POPUP)
GUICtrlSetBkColor($hGUI, 0x000000)
    $GUI_Pos = WinGetPos($hGUI)
    
consolewrite("GUI Height = " & $GUI_Pos[3] & @lf)
consolewrite("GUI Width = " & $GUI_Pos[2] & @lf)
    GUISetState()
    _GDIPlus_Startup()
$hcartridge = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\images\" & "test1.jpg")
Global $aDim = _GDIPlus_ImageGetDimension($hcartridge)
consolewrite("!Img width = " & $aDim[0] & @lf)
$iWidth = _GDIPlus_ImageGetWidth($hcartridge)
$iHeight = _GDIPlus_ImageGetHeight($hcartridge)
    ConsoleWrite("!img $iHeight= " & $iHeight & @lf)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
ConsoleWrite(_GDIPlus_ImageGetHeight & @lf)
    
GUIRegisterMsg($WM_MOUSEWHEEL, "_Mousewheel")
    ; --- Create GUI ---
Global $fZoom = 1
Global $iMinZoom = 1
Global $iMaxZoom = 20
Global $imgwidth = $iWidth
Global $imgheight = $iHeight
    
_GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hcartridge, 0, 0, $aDim[0], $aDim[1], _
        ($aDim[0] - $aDim[0] * $fZoom) / 2, ($aDim[1] - $aDim[1] * $fZoom) / 2, _
        $aDim[0] * $fZoom, $aDim[1] * $fZoom)
    
Func _Mousewheel($hWnd, $iMsg, $wParam, $lParam)
    Switch $wParam
        Case 0xFF880000 ;mouse wheel up
            if $fZoom > $iMinZoom Then
            $fZoom -= 0.05
            $imgwidth = $iWidth * $fZoom
            $imgheight = $iHeight * $fZoom
            ConsoleWrite("Zoom= " & $fZoom & " img.width:" & $imgwidth & " img.height: " & $imgheight & @lf)
_GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hcartridge, $scroll_x, $scroll_y, $aDim[0], $aDim[1], _
        ($aDim[0] - $aDim[0] * $fZoom) / 2, ($aDim[1] - $aDim[1] * $fZoom) / 2, _
        $aDim[0] * $fZoom, $aDim[1] * $fZoom)
        EndIf
        Case 0x00780000
               $fZoom += 0.05
               $imgwidth = $iWidth * $fZoom
               $imgheight = $iHeight * $fZoom
                   ConsoleWrite("Zoom= " & $fZoom & " img.width:" & $imgwidth & " img.height: " & $imgheight & @lf)
               ConsoleWrite($imgwidth & @lf)
              _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hcartridge, $scroll_x, $scroll_y, $aDim[0], $aDim[1], _
              ($aDim[0] - $aDim[0] * $fZoom) / 2, ($aDim[1] - $aDim[1] * $fZoom) / 2, _
               $aDim[0] * $fZoom, $aDim[1] * $fZoom)
            ;ConsoleWrite($fZoom & @lf)
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_Mousewheel
    
 Do
     $mc2 = MouseGetPos()
         If $g_iIDC = $g_iNewIDC Then
            $g_iIDC = -1
            GUISetCursor($g_iIDC)
        EndIf
      While _IsPressed("01", $dll)
        If $g_iNewIDC <> $g_iIDC Then
            $g_iIDC = $g_iNewIDC
            GUISetCursor($g_iIDC)
        EndIf
          GUICtrlSetCursor(-1, 4)
        $mc3 = MouseGetPos()
          If $mc2[0] <> $mc3[0] Or $mc2[1] <> $mc3[1] Then
            $scroll_x = ($sx + ($mc3[0] - $mc2[0]) / ($z ^ 2 / 16))
            $scroll_y = ($sy + ($mc3[1] - $mc2[1]) / ($z ^ 2 / 16))
    
         if $scroll_y < 1 Then $scroll_y = 0
         if $scroll_x < 1 Then $scroll_x = 0
         if $scroll_y >  ($iHeight - $GUI_Pos[3]) Then
            $scroll_y =  ($iHeight - $GUI_Pos[3])
         EndIf
         if $scroll_x > ($imgwidth - $GUI_Pos[2]) Then
               $scroll_x =  ($imgwidth - $GUI_Pos[2])
         EndIf
         consolewrite("GUI Width = " & $GUI_Pos[2] & @lf)
          ConsoleWrite("Zoom= " & $fZoom & " img.width:" & $imgwidth & " img.height: " & $imgheight & @lf)
         consolewrite($scroll_x & @lf)
            _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hcartridge, $scroll_x, $scroll_y, $aDim[0], $aDim[1], _
        ($aDim[0] - $aDim[0] * $fZoom) / 2, ($aDim[1] - $aDim[1] * $fZoom) / 2, _
        $aDim[0] * $fZoom, $aDim[1] * $fZoom)
           $current_iPos_y = $scroll_y
          EndIf
            Sleep(20)
      Wend
     $sx = $scroll_x
     $sy = $scroll_y
      Until GUIGetMsg() = $GUI_EVENT_CLOSE
      _GDIPlus_GraphicsDispose($hGraphic)
    DllClose($dll)
    
Func Terminate()
    Exit
EndFunc   ;==>Terminate

The zoom function seams to work like I want . 

Link to comment
Share on other sites

Hi Acce :)

First of all, I downloaded the freeware you mentioned : FastStone Image Viewer 7.5 (2020-03-10) in its portable version.

It's a very interesting program (thanks !) and I checked its scrolling & zoom behavior because you would like the same behavior as you explained it in your 1st post.

I succeeded to do that in the 2nd script below and it matches  what you asked to UEZ yesterday, quote :

On 8/28/2020 at 8:12 PM, Acce said:

If somehow it would be possible to have your code load the image in full size into the little window obviously the img would be larger then the window which is what I want so I can scroll/push it around  it should stop when it comes to the jpg edges like x 0 should not be allowed to be moved further than 0 in the window,  same goes with all the edges

This 2nd script is based on the 1st script I posted yesterday, but this time the image (GUI2) got a $WS_CHILD style which is a big help for your request, plus some changes in the WM_WINDOWPOSCHANGING() function.

You will be able to scroll/push around when the image (GUI2) is wider or higher (or both) than GUI1, just like with FastStone Viewer. And the edges of the image will be checked when necessary.

With my small expertise, I don't think I can do more but I like the result and it was an interesting challenge.

Please try it with a jpg of yours (just rename the jpg accordingly to the script name)
Good luck and have a great week-end :)

#include <GDIPlus.au3>
#include <GUIConstants.au3>
#include <MsgBoxConstants.au3>

HotKeySet("{ESC}", "_Exit")

Global $iZoom = 1.05 ; change the value if needed
Global $hGUI1 = 0, $hGUI2 = 0, $hImage = 0, $hBitmap = 0
Global $iLeft2, $iTop2, $iWidth2, $iHeight2

; $hGUI1 = GUICreate("", @DesktopWidth - 200, @DesktopHeight - 200, -1, -1, $WS_POPUP, $WS_EX_COMPOSITED)
$hGUI1 = GUICreate("Image draggable, zoomable, expandable", @DesktopWidth - 200, @DesktopHeight - 200, -1, -1, -1, $WS_EX_COMPOSITED)

$aClientSize = WinGetClientSize($hGUI1)
$iWidth1 = $aClientSize[0]
$iHeight1 = $aClientSize[1]

;====================================================
_GDIPlus_Startup()

$sFileName = StringTrimRight(@ScriptFullPath, 4) & ".jpg" ; .au3/.a3x/.exe => .jpg
If Not FileExists($sFileName) Then _Quit("File not found", $sFileName, 0, 0)

$hImage = _GDIPlus_ImageLoadFromFile($sFileName)
If @error Then _Quit("_GDIPlus_ImageLoadFromFile", $sFileName, @error, @extended)

$iX = _GDIPlus_ImageGetWidth($hImage)
$iY = _GDIPlus_ImageGetHeight($hImage)

$iX_Ori = $iX
$iY_Ori = $iY

$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
If @error Then _Quit("_GDIPlus_BitmapCreateHBITMAPFromBitmap", $sFileName, @error, @extended)

$hGUI2 = GUICreate("", $iX, $iY, -1, -1, $WS_CHILD, -1, $hGUI1)
$idPic = GUICtrlCreatePic("", 0, 0, $iX, $iY, -1, $GUI_WS_EX_PARENTDRAG)
GUICtrlSetResizing(-1, $GUI_DOCKAUTO)

$hPrevImage = GUICtrlSendMsg($idPic, 0x0172, 0, $hBitmap) ; STM_SETIMAGE = 0x0172, $IMAGE_BITMAP = 0
_WinAPI_DeleteObject($hPrevImage); Delete Prev image if any (help file)

;====================================================
GUISetState(@SW_SHOW, $hGUI1)
GUISetState(@SW_SHOW, $hGUI2)

GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")

; 1st WinMove will update 4 global variables in WM_WINDOWPOSCHANGING() : $iLeft2, $iTop2, $iWidth2, $iHeight2
; These 4 variables will be used later in WM_MOUSEWHEEL() to calculate accurate $iNewLeftCoord & $iNewTopCoord
WinMove($hGUI2, "", ($iWidth1 - $iX) / 2, ($iHeight1 - $iY) / 2, $iX, $iY) ; possible negative coords

ToolTip($iX_Ori & " / " & $iY_Ori & "  -->  " & Int($iX) & " / " & Int($iY), _
    @DesktopWidth / 2, 9, "", 0, 2) ; 9 (good position), 0 = no icon, 2 = center tip at x,y

While 1
    $aMsg = GUIGetMsg($GUI_EVENT_ARRAY)

    Switch $aMsg[1]
        Case $hGUI1
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    _Exit()
            EndSwitch

        Case $hGUI2
            Switch $aMsg[0]
                Case $GUI_EVENT_CLOSE
                    _Exit()

            EndSwitch
    EndSwitch
WEnd

;====================================================
Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam

    Sleep(10) ; useful to prevent freezing on slow computers & big images & big repeated zooms

    If BitShift($wParam, 16) > 0 Then
        $iX *= $iZoom
        $iY *= $iZoom
        Local $iNewLeftCoord = $iLeft2 - ($iWidth2 * $iZoom - $iWidth2) / 2
        Local $iNewTopCoord = $iTop2 - ($iHeight2 * $iZoom - $iHeight2) / 2
    Else
        $iX /= $iZoom
        $iY /= $iZoom
        Local $iNewLeftCoord = $iLeft2 - ($iWidth2 / $iZoom - $iWidth2) / 2
        Local $iNewTopCoord = $iTop2 - ($iHeight2 / $iZoom - $iHeight2) / 2
    EndIf

    WinMove($hGUI2, "", $iNewLeftCoord, $iNewTopCoord, $iX, $iY)

    ToolTip($iX_Ori & " / " & $iY_Ori & "  -->  " & Int($iX) & " / " & Int($iY), _
        @DesktopWidth / 2, 9, "", 0, 2) ; 9 (good position), 0 = no icon, 2 = center tip at x,y

    ; Return $GUI_RUNDEFMSG ; (?)

EndFunc   ;==>WM_MOUSEWHEEL

;====================================================
Func WM_WINDOWPOSCHANGING($hWnd, $iMsg, $wParam, $lParam)
    #forceref $iMsg, $wParam

    If $hWnd = $hGUI2 Then
        Local $stWinPos = DllStructCreate("uint;uint;int;int;int;int;uint", $lParam)
        $iLeft2 = DllStructGetData($stWinPos, 3)
        $iTop2 = DllStructGetData($stWinPos, 4)
        $iWidth2 = DllStructGetData($stWinPos, 5)
        $iHeight2 = DllStructGetData($stWinPos, 6)
        Local $iRight2 = $iLeft2 + $iWidth2
        Local $iBottom2 = $iTop2 + $iHeight2

;~      ConsoleWrite("$iLeft2 = " & $iLeft2 & @TAB & "$iTop2 = " & $iTop2 & @TAB & _
;~          "$iWidth2 = " & $iWidth2 & @TAB & "$iHeight2 = " & $iHeight2 & @TAB & _
;~          "$iRight2 = " & $iRight2 & @TAB & "$iBottom2 = " & $iBottom2 & @lf)

        If $iWidth2 <= $iWidth1 Then ; image (GUI2) fits horizontally within GUI1 => centered & non draggable (hozizontally)
            DllStructSetData($stWinPos, 3, ($iWidth1 - $iWidth2) / 2) ; left border
        Else ; image (GUI2) larger than GUI1 => draggable (horizontally) => left & right borders of GUI2 to be checked
            Select
                Case $iLeft2 > 0 ; $iLeft2 coord relative to GUI1 because of GUI2 $WS_CHILD style (+++)
                    DllStructSetData($stWinPos, 3, 0) ; left border
                Case $iRight2 < $iWidth1 ; $iRight2 coord relative to GUI1 because etc...
                    DllStructSetData($stWinPos, 3, $iWidth1 - $iWidth2) ; left border again
            EndSelect
        EndIf

        If $iHeight2 <= $iHeight1 Then ; image (GUI2) fits vertically within GUI1 => centered & non draggable (vertically)
            DllStructSetData($stWinPos, 4, ($iHeight1 - $iHeight2) / 2) ; top border
        Else ; image (GUI2) higher than GUI1 => draggable (vertically) => top & bottom borders of GUI2 to be checked
            Select
                Case $iTop2 > 0 ; $iTop2 coord relative to GUI1 because of GUI2 $WS_CHILD style (+++)
                    DllStructSetData($stWinPos, 4, 0) ; top border
                Case $iBottom2 < $iHeight1 ; $iBottom2 coord relative to GUI1 because etc...
                    DllStructSetData($stWinPos, 4, $iHeight1 - $iHeight2) ; top border again
            EndSelect
        EndIf
    EndIf

    ; Return $GUI_RUNDEFMSG ; (?)

EndFunc   ;==>WM_WINDOWPOSCHANGING

;====================================================
Func _Quit($sError_title, $sError_msg, $iKeep_error, $iKeep_extended) ; bad error

    MsgBox($MB_TOPMOST, "Error : " & $sError_title, _
        $sError_msg & @CRLF & @CRLF & _
        "@error = " & $iKeep_error & "    @extended = " & $iKeep_extended)
    _Exit()

EndFunc ; _Quit()

; ====================================================
Func _Exit()

    ToolTip("")
    _GDIPlus_ImageDispose($hImage)
    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_Shutdown()
    GUIDelete($hGUI2)
    GUIDelete($hGUI1)
    Exit

EndFunc ; _Exit()

 

Edited by pixelsearch
2020-08-31 : no more flickering, thanks $WS_EX_COMPOSITED
Link to comment
Share on other sites

Thanks a lot for your effort in helping me pixelsearch I have almost had a break through myself ., But calculating the edges have been a bit of a nightmare for me. Looking forward to test your version :) Have a nice weekend yourself there might be a question or two later , hope you dont mind :)

Edit just ran it now and it looks like you nailed it with your version . Im just a bit afraid that your version is to powerful for me to comprehend , Yikes Very nice work indeed ,

Only thing that I would want is that the  img should never be allowed to be smaller then the window , where would I edit that ? in the version I made I had a few lines like this 

if $fZoom > $iMinZoom Then

if $fZoom < $iMaxZoom Then

Also the img i loaded had dimension of 1920*915 but for some reason it didn't fill the window completely 

Edited by Acce
Link to comment
Share on other sites

I did a lot of rework in the 2nd script above, because $WS_CHILD style in GUI2 may generate negative coords relative to GUI1 (I didn't know that when I scripted it yesterday)

This is very different from the 1st script in the precedent page, where $WS_EX_MDICHILD extended style in GUI2 had its coords relative to screen !

16 hours ago, Acce said:

the img i loaded had dimension of 1920*915 but for some reason it didn't fill the window completely

With the reworked script above, your 1920*915 image will fill the window completely when you load it. The reason why it didn't work is that I displayed the image centered with positive coords, when in fact it requires negative coords when GUI2 size is > GUI1 size

Also another functionality has been improved : when your image size (GUI2) is wider/higher than GUI1, if you drag/push the image (so it's not centered anymore) and after that you zoom again, it will zoom at the good part of the image (and not "back to center" as it was wrongly & quickly scripted)

Maybe UEZ will be kind enough to control the simple formula applied to both variables $iNewLeftCoord and  $iNewTopCoord found in this line of script :

WinMove($hGUI2, "", $iNewLeftCoord, $iNewTopCoord, $iX, $iY)

These 2 variables allow a more accurate zoom region, their values may be negative but the tests I did with different images sizes seem ok. You can see the negative values if you uncomment the ConsoleWrite line in Func WM_WINDOWPOSCHANGING(), for example :

$iLeft2 = -1748 $iTop2 = -1336  $iWidth2 = 4320 $iHeight2 = 3240    $iRight2 = 2572 $iBottom2 = 1904
$iLeft2 = -1964 $iTop2 = -1498  $iWidth2 = 4752 $iHeight2 = 3564    $iRight2 = 2788 $iBottom2 = 2066

Concerning your other request :

16 hours ago, Acce said:

Only thing that I would want is that the  img should never be allowed to be smaller then the window

I'll see what I can do, but it was important first to improve the 2nd script above... before adding other functionalities :)

Edited by pixelsearch
typo
Link to comment
Share on other sites

Thanks again for your help :) your version is really powerful compered to what I wrote , the scroll is much more smooth did you edit your post above with latest changes ? this negative coordinates gives kinda a headache dont it ? lol 

Link to comment
Share on other sites

Hi again I really appreciated the help you have put into this, although im very afraid to use the version you created pixelsearch as that looks so complex and im really unsure how I would be able to continue work on that version , lol 

 

do you mind having a look at the version I have created?  my version is a little more sluggish but works as intended , my version is prime rely based upon work I have found from UAZ , this obviously an inferior version to his code as well. I was kinda hoping to build it like in this post which is something I almost can get my head around.

I have a few questions if you dont mind answer ? 

1. I think I dont ever delete the images in my code , how can that be implemented ?

2 why is this so sluggish compered to what you guys wrote ? 

 

code bellow 

#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <Misc.au3>
    HotKeySet("{ESC}", "Terminate")
    Global $sx, $z = 5, $sy, $mc2, $f, $scroll_x = 0, $scroll_y, $current_iPos_y, $RQGUI_POS[3] = [280, 325, 0]
Global $g_iIDC = -1, $g_iNewIDC = 0, $bg_c = "404040"
Global $aDim
Global $g_aArray = StringSplit("Hand|AppStarting|Arrow|Cross|Help|IBeam|Icon (obsolete)|No|" & _
        "Size (obsolete)|SizeAll|SizeNESW|SizeNS|SizeNWSE|SizeWE|UpArrow|Wait|None", "|", 2) ; The flag parameter is set to flag = 2 as we don't require the total count of the array.
    ; --- Create GUI ---
$hGUI = GUICreate('MyGUI', @DesktopWidth - 200, @DesktopHeight - 200, 100, 100, $WS_POPUP)
GUICtrlSetBkColor($hGUI, 0x000000)
    GUISetState()
    Global Const $dll = DllOpen("user32.dll")
_GDIPlus_Startup()
$hcartridge = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\images\" & "test_img0.jpg")
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    GUIRegisterMsg($WM_MOUSEWHEEL, "_Mousewheel")
    ; --- GUI Dimensions ---
Global $GUI_Pos = WinGetPos($hGUI)
Global $aDim = _GDIPlus_ImageGetDimension($hcartridge)
Global $iWidth = _GDIPlus_ImageGetWidth($hcartridge)
Global $iHeight = _GDIPlus_ImageGetHeight($hcartridge)
Global $fZoom = 1
Global $iMinZoom = 1
Global $iMaxZoom = 20
Global $imgwidth = $iWidth
Global $imgheight = $iHeight
Global $imgxDIFF = 0
Global $imgyDIFF = 0
Global $iGUIWidth = $GUI_Pos[2]
Global $iGUIHeight = $GUI_Pos[3]
    Draw2Graphic()
    Do
    $mc2 = MouseGetPos()
    If $g_iIDC = $g_iNewIDC Then
        $g_iIDC = -1
        GUISetCursor($g_iIDC)
    EndIf
    While _IsPressed("01", $dll)
        If $g_iNewIDC <> $g_iIDC Then
            $g_iIDC = $g_iNewIDC
            GUISetCursor($g_iIDC)
        EndIf
        GUICtrlSetCursor(-1, 4)
        $mc3 = MouseGetPos()
        If $mc2[0] <> $mc3[0] Or $mc2[1] <> $mc3[1] Then
            $scroll_x = ($sx + ($mc3[0] - $mc2[0]) / ($z ^ 2 / 16))
            $scroll_y = ($sy + ($mc3[1] - $mc2[1]) / ($z ^ 2 / 16))
                Draw2Graphic()
            $current_iPos_y = $scroll_y
        EndIf
            Sleep(20)
    WEnd
    $sx = $scroll_x
    $sy = $scroll_y
Until GUIGetMsg() = $GUI_EVENT_CLOSE
_GDIPlus_GraphicsDispose($hGraphic)
DllClose($dll)
    Func Draw2Graphic()
    $iMinScrollx = (($imgxDIFF / 2)) / $fZoom
    $iMinScrolly = ($imgyDIFF) / $fZoom
        If $scroll_y <= -($iMinScrolly) Then $scroll_y = -($iMinScrolly)
    If $scroll_x <= -(($imgxDIFF / 2)) / $fZoom Then $scroll_x = -(($imgxDIFF / 2)) / $fZoom
    ConsoleWrite("$iMinScrolly= " & $iMinScrolly & @LF)
    If $scroll_y >= (($imgheight - $iGUIHeight) / $fZoom) - $iMinScrolly Then
        $scroll_y = (($imgheight - $iGUIHeight) / $fZoom) - $iMinScrolly
    EndIf
    If $scroll_x >= (($imgwidth - $iGUIWidth) / $fZoom) - $iMinScrollx Then
        $scroll_x = (($imgwidth - $iGUIWidth) / $fZoom) - $iMinScrollx
    EndIf
    ConsoleWrite("Min scrolly=" & - (($imgyDIFF / 2)) / $fZoom & @LF)
        ConsoleWrite("GUI Width = " & $GUI_Pos[2] & @LF)
    ConsoleWrite("Zoom= " & $fZoom & " img.width:" & $imgwidth & " img.height: " & $imgheight & " img difference =" & $imgxDIFF & @LF)
    ConsoleWrite("scroll_y = " & $scroll_y & @LF)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hcartridge, $scroll_x, $scroll_y, $aDim[0], $aDim[1], _
            ($aDim[0] - $aDim[0] * $fZoom) / 2, ($aDim[1] - $aDim[1] * $fZoom), _
            $aDim[0] * $fZoom, $aDim[1] * $fZoom)
    ;consolewrite(($aDim[1] - $aDim[1] * $fZoom) / 2)
    ;ConsoleWrite("Max scroll= " & (($imgwidth - $iGUIWidth) / $fZoom) - $iMinScrollx & @LF)
EndFunc   ;==>Draw2Graphic
    Func _Mousewheel($hWnd, $iMsg, $wParam, $lParam)
    Switch $wParam
        Case 0xFF880000 ;mouse wheel up
            If $fZoom > $iMinZoom Then
                $fZoom -= 0.05
                $imgwidth = $iWidth * $fZoom
                $imgheight = $iHeight * $fZoom
                $imgxDIFF = $imgwidth - $iWidth
                $imgyDIFF = $imgheight - $iHeight
                Draw2Graphic()
            EndIf
        Case 0x00780000
            $fZoom += 0.05
            $imgwidth = $iWidth * $fZoom
            $imgheight = $iHeight * $fZoom
            $imgxDIFF = $imgwidth - $iWidth
            $imgyDIFF = $imgheight - $iHeight
            Draw2Graphic()
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_Mousewheel

Func Terminate()
    Exit
EndFunc   ;==>Terminate

 

Any more help would really be appreciated :) 

Edited by Acce
Link to comment
Share on other sites

@Acce : your script worked nicely on my computer, good job :)

Concerning my script above, a big improvement has been done to eliminate totally the flickering while resizing, after I added $WS_EX_COMPOSITED extended style to GUI1, what a great day !

Thanks to Martin in this thread :
He wrote : "Use the extended window style $WS_EX_COMPOSITED and the flickering will go away"

Help file :
"$WS_EX_COMPOSITED : paints all descendants of a window in bottom-to-top painting order using double-buffering."

Script updated above

Link to comment
Share on other sites

Hi thanks again for your reply and kind words 

"He wrote : "Use the extended window style $WS_EX_COMPOSITED and the flickering will go away"

- I have moved to next phase in my project and trying to load an img on top of the background img and it flickers like crazy , so a new window is the way to go yeah ? 

Link to comment
Share on other sites

53 minutes ago, Acce said:

so a new window is the way to go yeah ? 

Probably, but I'm not an expert at all you know.

As you can see in my script, it worked because :
1) GUI2 got a $WS_CHILD style (hello negative coords)
2) The parent window GUI1 got a $WS_EX_COMPOSITED extended style ("paints all descendants of a window [...] using double-buffering.")

I guess that's the reason while the flickering totally disappeared when the child window GUI2 is resized.
Concerning the negative coords when using $WS_CHILD, maybe the function _WinAPI_ClientToScreen() could be helpful to replace GUI2 coordinates with screen coordinates (we know that the parent GUI1 got screen coordinates)

Then, comparing (for example) the left/top position of the child window to the left/top position of the parent window should be friendlier. Maybe I'll experiment it in my script... but as it works nicely now, I'd better not change anything :)

Edited by pixelsearch
typo
Link to comment
Share on other sites

I guess we can close this thread now , many thanks for help and your code , will revisit this a bit later when my skill level is a bit higher would love to be able to edit your version but im not at that level yet , lol :) 

Link to comment
Share on other sites

I cleaned up my GDI+ code and here is the result which seems to work properly.

;Coded by UEZ build 2020-09-03 beta

#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <Screencapture.au3>
#include <WindowsConstants.au3>

_GDIPlus_Startup()

;~ Global Const $hBmp = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Testbitmap.bmp")

Global $hHBitmap = _ScreenCapture_Capture("", 0, 0, 319, 255, 0)
Global Const $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
_WinAPI_DeleteObject($hHBitmap)

Global Const $bg_c = "808080"
Global Const $iW = 800, $iH = 600, $iW2 = $iW / 2, $iH2 = $iH / 2, $zs = 0.025
Global $bW = _GDIPlus_ImageGetWidth($hBmp), $bH = _GDIPlus_ImageGetHeight($hBmp), $bW2 = $bW / 2, $bH2 = $bH / 2
Global Const $hGUI = GUICreate("GDI+ Zoom and Move Image within GUI", $iW, $iH)
GUISetState()

Global $aMPos1, $aMPos2, $iMPx = $iW2 - $bW2, $iMPy = $iH2 - $bH2, $iMPx_p = 0, $iMPy_p = 0, $z = 1.0, $zp = 1.0

Global Const $dll = DllOpen("user32.dll")

Global Const $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global Const $hBuffer_Bmp = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphic)
Global Const $hContext = _GDIPlus_ImageGetGraphicsContext($hBuffer_Bmp)
_GDIPlus_GraphicsSetPixelOffsetMode($hContext, 4)
_GDIPlus_GraphicsSetInterpolationMode($hContext, 5)

Draw2Graphic($iMPx, $iMPy, 1, 1)
GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL")

Do
    $aMPos1 = MouseGetPos()
    While _IsPressed("01", $dll) And WinActive($hGUI)
        $aMPos2 = MouseGetPos()
        $iMPx = $iMPx_p + $aMPos2[0] - $aMPos1[0]
        $iMPy = $iMPy_p + $aMPos2[1] - $aMPos1[1]
        Draw2Graphic($iMPx, $iMPy, $z, $zp)
        Sleep(10)
    WEnd
    $iMPx_p = $iMPx
    $iMPy_p = $iMPy

Until GUIGetMsg() = $GUI_EVENT_CLOSE

_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_BitmapDispose($hBuffer_Bmp)
_GDIPlus_BitmapDispose($hBmp)
_GDIPlus_Shutdown()
GUIDelete()
DllClose($dll)
Exit

Func Draw2Graphic($x, $y, $fZoom, $fZoom_prev)
    _GDIPlus_GraphicsClear($hContext, "0xFF" & $bg_c)
    $x = Min(Max(0, $x), $iW - $bW * $zp - 1)
    $y = Min(Max(0, $y), $iH - $bH * $zp - 1)
    Local Const $iW_New = $bW * $fZoom, $iH_New = $bH * $fZoom
    Local Const $iW_Prev = $bW * $fZoom_prev, $iH_Prev = $bH * $fZoom_prev
    Local Const $dx = ($iW_New - $iW_Prev) / 2, $dy = ($iW_New - $iW_Prev) / 2
    $iMPx -= $dx
    $iMPy -= $dy
    _GDIPlus_GraphicsDrawImageRect($hContext, $hBmp, $x - $dx, $y - $dy, $iW_New, $iH_New)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBuffer_Bmp, 0, 0, $iW, $iH)
EndFunc   ;==>Draw2Graphic

Func Max($a, $b)
    Return ($a > $b) ? $a : $b
EndFunc   ;==>Max

Func Min($a, $b)
    Return ($a < $b) ? $a : $b
EndFunc   ;==>Min

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    Local $iDir = _WinAPI_HiWord($wParam)
    Switch $iDir
        Case $iDir < 0
            If $z - $zs < 8 * $zs Then Return 0
            $zp = $z
            $z -= $zs
            Draw2Graphic($iMPx, $iMPy, $z, $zp)
            Return 0
        Case Else
            If ($z + $zs) * $bW > $iW Or ($z + $zs) * $bH > $iH Then Return 0
            $zp = $z
            $z += $zs
            Draw2Graphic($iMPx, $iMPy, $z, $zp)
            Return 0
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_MOUSEWHEEL

Use mouse wheel to zoom image and press lmb to move image around without leaving the borders.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

U are really good with this UAZ( i read several of you old posts) :) are you able to reprogram it to work like I want with a bigger image, which can be scrolled around based on image dimension? here is humble attempt since i didnt have double buffering in the code I posted earlier I had to rewrite it, but now all the cordinate calculations are off, not really sure why ? 

 

#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <Misc.au3>

; --- Hotkeys ---
HotKeySet("{ESC}", "Terminate")
HotKeySet("^0", "_ResetZoom") ; ctr and 0

; --- Vars ---
Global $sx, $z = 5, $sy, $mc2, $f, $scroll_x = 0, $scroll_y, $current_iPos_y, $RQGUI_POS[3] = [280, 325, 0]
Global $g_iIDC = -1, $g_iNewIDC = 0, $bg_c = "404040"
Global $aDim, $hImage = 0, $iMinScrollx, $iMinScrolly
Global $g_aArray = StringSplit("Hand|AppStarting|Arrow|Cross|Help|IBeam|Icon (obsolete)|No|" & _
        "Size (obsolete)|SizeAll|SizeNESW|SizeNS|SizeNWSE|SizeWE|UpArrow|Wait|None", "|", 2) ; The flag parameter is set to flag = 2 as we don't require the total count of the array.

; --- MAIN GUI ---
$hGUI = GUICreate('MyGUI', @DesktopWidth - 200, @DesktopHeight - 200, 100, 100, $WS_POPUP)
GUICtrlSetBkColor($hGUI, 0x000000)

; GUI width and height
Global $GUI_Pos = WinGetPos($hGUI)
Global $iGUIWidth = $GUI_Pos[2]
Global $iGUIHeight = $GUI_Pos[3]

GUISetState()

; Load GDI+ resources
_GDIPlus_Startup()


;load 1st image
$hBitmapTmp = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\images\" & "background.jpg")
$hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\images\" & "background.jpg")

; --- IMG Dimensions ---
Global $aDim = _GDIPlus_ImageGetDimension($hImage)
Global $iWidth = _GDIPlus_ImageGetWidth($hImage)
Global $iHeight = _GDIPlus_ImageGetHeight($hImage)
Global $fZoom = 1
Global $iMinZoom = 1
Global $iMaxZoom = 20
Global $imgwidth = $iWidth
Global $imgheight = $iHeight
Global $imgxDIFF = 0
Global $imgyDIFF = 0


Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphic)
Global $hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsClear($hBackBuffer)

; draw images into back buffer
_GDIPlus_GraphicsDrawImage($hBackBuffer, $hBitmapTmp, 0, 0)


; Windows messages
GUIRegisterMsg($WM_MOUSEWHEEL, "_Mousewheel")

; Catch key presses
Global Const $dll = DllOpen("user32.dll")



    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hBitmap, $scroll_x, $scroll_y, $aDim[0], $aDim[1], _
            ($aDim[0] - $aDim[0] * $fZoom) / 2, ($aDim[1] - $aDim[1] * $fZoom), _
            $aDim[0] * $fZoom, $aDim[1] * $fZoom)
;Draw2Graphic()
;_loadAssets()
Func _loadAssets()
    $base_x = 500
    $base_y = 300
    $start_x = -$iMinScrollx
    $start_y = -$iMinScrolly
    $ix = $start_x - $scroll_x ; pos 0 on img
    $iy = $start_y - $scroll_y ; pos 0 on img
    $xx = ($ix + $base_x) * $fZoom
    $yy = ($iy + $base_y) * $fZoom


    ; ,x:-1,y:3

    $base = 10
    $Pos_x = 3 * $base

 ; Load the GDI+ bitmap
 $hImage_1 = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\images\" & "x-png-15.png")

 $x = _GDIPlus_ImageGetWidth($hImage_1)
 $y = _GDIPlus_ImageGetHeight($hImage_1)

 $hImage_resized = _GDIPlus_ImageResize($hImage_1, 25, 25)
 _GDIPlus_GraphicsDrawImage($hBackBuffer, $hImage_resized, $xx, $yy)


EndFunc

Do
    $mc2 = MouseGetPos()
    If $g_iIDC = $g_iNewIDC Then
        $g_iIDC = -1
        GUISetCursor($g_iIDC)
    EndIf
    While _IsPressed("01", $dll)
        If $g_iNewIDC <> $g_iIDC Then
            $g_iIDC = $g_iNewIDC
            GUISetCursor($g_iIDC)
        EndIf
        GUICtrlSetCursor(-1, 4)
        $mc3 = MouseGetPos()
        If $mc2[0] <> $mc3[0] Or $mc2[1] <> $mc3[1] Then
            $scroll_x = ($sx + ($mc3[0] - $mc2[0]) / ($z ^ 2 / 16))
            $scroll_y = ($sy + ($mc3[1] - $mc2[1]) / ($z ^ 2 / 16))

            Draw2Graphic()
            $current_iPos_y = $scroll_y
        EndIf

        Sleep(20)
    WEnd
    $sx = $scroll_x
    $sy = $scroll_y
Until GUIGetMsg() = $GUI_EVENT_CLOSE
_GDIPlus_GraphicsDispose($hGraphic)
DllClose($dll)

Func Draw2Graphic()

$hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphic)
$hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsClear($hBackBuffer)
; draw images into back buffer

_GDIPlus_GraphicsDrawImage($hBackBuffer, $hBitmapTmp, 0, 0)
_loadAssets()

    $iMinScrollx = (($imgxDIFF / 2)) / $fZoom
    $iMinScrolly = ($imgyDIFF) / $fZoom

    If $scroll_y <= -($iMinScrolly) Then $scroll_y = -($iMinScrolly)
    If $scroll_x <= -(($imgxDIFF / 2)) / $fZoom Then $scroll_x = -(($imgxDIFF / 2)) / $fZoom
    ;ConsoleWrite("$iMinScrolly= " & $iMinScrolly & @LF)
    If $scroll_y >= (($imgheight - $iGUIHeight) / $fZoom) - $iMinScrolly Then
        $scroll_y = (($imgheight - $iGUIHeight) / $fZoom) - $iMinScrolly
    EndIf
    If $scroll_x >= (($imgwidth - $iGUIWidth) / $fZoom) - $iMinScrollx Then
        $scroll_x = (($imgwidth - $iGUIWidth) / $fZoom) - $iMinScrollx
    EndIf
    ;ConsoleWrite("Min scrolly=" & - (($imgyDIFF / 2)) / $fZoom & @LF)

    ;ConsoleWrite("GUI Width = " & $GUI_Pos[2] & @LF)
    ;ConsoleWrite("Zoom= " & $fZoom & " img.width:" & $imgwidth & " img.height: " & $imgheight & " img difference =" & $imgxDIFF & @LF)
    ;ConsoleWrite("scroll_y = " & $scroll_y & @LF)

    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hBitmap, $scroll_x, $scroll_y, $aDim[0], $aDim[1], _
            ($aDim[0] - $aDim[0] * $fZoom) / 2, ($aDim[1] - $aDim[1] * $fZoom), _
            $aDim[0] * $fZoom, $aDim[1] * $fZoom)

EndFunc   ;==>Draw2Graphic

Func _Mousewheel($hWnd, $iMsg, $wParam, $lParam)
    Switch $wParam
        Case 0xFF880000 ;mouse wheel up
            If $fZoom > $iMinZoom Then
                $fZoom -= 0.1
                $imgwidth = $iWidth * $fZoom
                $imgheight = $iHeight * $fZoom
                $imgxDIFF = $imgwidth - $iWidth
                $imgyDIFF = $imgheight - $iHeight
                Draw2Graphic()
            EndIf
        Case 0x00780000
            $fZoom += 0.1
            $imgwidth = $iWidth * $fZoom
            $imgheight = $iHeight * $fZoom
            $imgxDIFF = $imgwidth - $iWidth
            $imgyDIFF = $imgheight - $iHeight
            Draw2Graphic()
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_Mousewheel

func _ResetZoom()
    $fZoom = 1
    $scroll_x = 0
    $scroll_y = 0
    Global $sx, $z = 5, $sy = 0 , $mc2 = 0 , $f = 0, $scroll_x = 0, $scroll_y = 0, $current_iPos_y = 0, $RQGUI_POS[3] = [280, 325, 0]
    $imgwidth = $iWidth * $fZoom
    $imgheight = $iHeight * $fZoom
    $imgxDIFF = $imgwidth - $iWidth
    $imgyDIFF = $imgheight - $iHeight
    Draw2Graphic()
EndFunc
Func Terminate()
    Exit
EndFunc   ;==>Terminate

 

Link to comment
Share on other sites

  • 2 months later...
On 8/30/2020 at 11:40 PM, pixelsearch said:

Concerning my script above, a big improvement has been done to eliminate totally the flickering while resizing, after I added $WS_EX_COMPOSITED extended style to GUI1, what a great day !

Hi Pixelsearch. I am looking into incorporating image zooming feature into one of my GUIs and your approach is a very easy and elegant way of doing it. But my experiments with your code are not entirely successful (at this stage I am just using my own image, no other changes to your code were made). The problem is that flickering is not entirely gone. Generally the GUI doesn't flicker when I change zoom level whith mouse wheel. But there are two cases the problem still shows up in my experiments. First is when I drag the image whith my left mouse button pressed (but this one is mild). And the second is when I minimize the window to tray and later unfurl it back. After that it starts flickering like hell when I adjust zoom level whith my mose wheel.

Would you or UEZ be so kind as to provide some advice on how it would be possible to get rid of this nasty little problem?   

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...