Jump to content

Help needed: image viewer (with zoom and translate)


matwachich
 Share

Recommended Posts

Hello, for my project, I need to display pictures stored on a centralized MySQL DB. There could be multiple display windows opened at the same time, si I try to make a custom static control to do this.

Here is my code:

#NoTrayIcon
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <Math.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WinAPIRes.au3>
#include <Memory.au3>

Enum _
    $WM_USER_PIC_INIT = $WM_USER, _
    $WM_USER_PIC_SETIMAGE, _
    $WM_USER_PIC_GETIMAGE

_GDIPlus_Startup()
OnAutoItExitRegister(_GDIPlus_Shutdown)

$hGUI = GUICreate("Test", 657, 521, -1, -1, $WS_OVERLAPPEDWINDOW)
$iStatic = GUICtrlCreateLabel("", 8, 32, 640, 480)
$hStatic = GUICtrlGetHandle(-1)
GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)

ConsoleWrite($hGUI & " > " & _WinAPI_GetClientWidth($hGUI) & "," & _WinAPI_GetClientHeight($hGUI) & @CRLF)
ConsoleWrite($hStatic & " > " & _WinAPI_GetClientWidth($hStatic) & "," & _WinAPI_GetClientHeight($hStatic) & @CRLF)

$B_rotL = GUICtrlCreateButton("RG", 8, 0, 35, 25)
GUICtrlSetResizing(-1, $GUI_DOCKTOP+$GUI_DOCKLEFT+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
$B_rotR = GUICtrlCreateButton("RD", 48, 0, 35, 25)
GUICtrlSetResizing(-1, $GUI_DOCKTOP+$GUI_DOCKLEFT+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)

$B_flipH = GUICtrlCreateButton("MH", 96, 0, 35, 25)
GUICtrlSetResizing(-1, $GUI_DOCKTOP+$GUI_DOCKLEFT+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
$B_flipV = GUICtrlCreateButton("MV", 136, 0, 35, 25)
GUICtrlSetResizing(-1, $GUI_DOCKTOP+$GUI_DOCKLEFT+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)

$B_cropR = GUICtrlCreateButton("CR", 184, 0, 35, 25)
GUICtrlSetResizing(-1, $GUI_DOCKTOP+$GUI_DOCKLEFT+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)
$B_cropF = GUICtrlCreateButton("CF", 224, 0, 35, 25)
GUICtrlSetResizing(-1, $GUI_DOCKTOP+$GUI_DOCKLEFT+$GUI_DOCKWIDTH+$GUI_DOCKHEIGHT)

_WinAPI_SetWindowSubclass($hStatic, DllCallbackGetPtr(DllCallbackRegister(_wmHandler, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")), 0)
_SendMessage($hStatic, $WM_USER_PIC_INIT)

GUISetState()

_SendMessage($hStatic, $WM_USER_PIC_SETIMAGE, _GDIPlus_ImageLoadFromFile("test image.jpg"), 1)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit

        Case $B_rotL
            $hImg = _SendMessage($hStatic, $WM_USER_PIC_GETIMAGE)
            $hNewImg = _GDIPlus_ImageClone($hImg)
            _GDIPlus_ImageRotateFlip($hNewImg, 3)
            _SendMessage($hStatic, $WM_USER_PIC_SETIMAGE, $hNewImg, 1)
        Case $B_rotR
            $hImg = _SendMessage($hStatic, $WM_USER_PIC_GETIMAGE)
            $hNewImg = _GDIPlus_ImageClone($hImg)
            _GDIPlus_ImageRotateFlip($hNewImg, 1)
            _SendMessage($hStatic, $WM_USER_PIC_SETIMAGE, $hNewImg, 1)

        Case $B_flipH
            $hImg = _SendMessage($hStatic, $WM_USER_PIC_GETIMAGE)
            $hNewImg = _GDIPlus_ImageClone($hImg)
            _GDIPlus_ImageRotateFlip($hNewImg, 4)
            _SendMessage($hStatic, $WM_USER_PIC_SETIMAGE, $hNewImg, 1)
        Case $B_flipV
            $hImg = _SendMessage($hStatic, $WM_USER_PIC_GETIMAGE)
            $hNewImg = _GDIPlus_ImageClone($hImg)
            _GDIPlus_ImageRotateFlip($hNewImg, 6)
            _SendMessage($hStatic, $WM_USER_PIC_SETIMAGE, $hNewImg, 1)
    EndSwitch
WEnd

Func _getData($hWnd, $sTag)
    Return DllStructCreate($sTag, _WinAPI_GetProp($hWnd, "DATA"))
EndFunc

Func _wmHandler($hWnd, $iMsg, $wParam, $lParam, $iSubclassID, $pUserData)
    Static $s_tagCUSTOMPIC = "handle image;" ; will contain other control internal state

    Switch $iMsg
        Case $WM_USER_PIC_INIT
            Local $pData = _MemGlobalAlloc(DllStructGetSize(DllStructCreate($s_tagCUSTOMPIC)), $GPTR)
            Local $tData = DllStructCreate($s_tagCUSTOMPIC, $pData)
            $tData.zoom = 1

            GUICtrlSetCursor(_WinAPI_GetDlgCtrlID($hWnd), 0)

            _WinAPI_SetProp($hWnd, "DATA", $pData)

        Case $WM_DESTROY
            Local $pData = _WinAPI_RemoveProp($hWnd, "DATA")

            Local $tData = DllStructCreate($s_tagCUSTOMPIC, $pData)
            If $tData.image Then _GDIPlus_ImageDispose($tData.image)

            _MemGlobalFree($pData)

        Case $WM_USER_PIC_SETIMAGE ; HIMAGE, FreeOld (bool)
            Local $tData = _getData($hWnd, $s_tagCUSTOMPIC)

            Local $hOldImg = $tData.image
            $tData.image = $wParam

            _WinAPI_RedrawWindow($hWnd)

            If $hOldImg And $lParam Then
                _GDIPlus_ImageDispose($hOldImg)
                Return 0
            Else
                Return $hOldImg
            EndIf

        Case $WM_USER_PIC_GETIMAGE
            Return _getData($hWnd, $s_tagCUSTOMPIC).image

        ; =========================================================================================
        Case $WM_PAINT
            Local $tData = _getData($hWnd, $s_tagCUSTOMPIC)

            Local $tPS = DllStructCreate($tagPAINTSTRUCT)
            Local $hDC = _WinAPI_BeginPaint($hWnd, $tPS)

            Local $hGfx = _GDIPlus_GraphicsCreateFromHDC($hDC)
            _drawImage( _
                $hGfx, $tData.image, _
                _WinAPI_GetClientWidth($hWnd), _WinAPI_GetClientHeight($hWnd) _
            )
            _GDIPlus_GraphicsDispose($hGfx)

            _WinAPI_EndPaint($hWnd, $tPS)
    EndSwitch
    Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc

Func _drawImage($hGfx, $hImg, $iGfxW, $iGfxH)
    If Not $hImg Then
        _GDIPlus_GraphicsClear($hGfx, 0xFFFFFFFF)
        Return
    EndIf

    Local $iImgW = _GDIPlus_ImageGetWidth($hImg), $iImgH = _GDIPlus_ImageGetHeight($hImg)

    Local $iScaleX = $iGfxW / $iImgW, $iScaleY = $iGfxH / $iImgH
    Local $iBaseScale = _Min($iScaleX, $iScaleY)

    ConsoleWrite("ScaleX = " & $iGfxW & " / " & $iImgW & " = " & $iScaleX & @CRLF)
    ConsoleWrite("ScaleX = " & $iGfxH & " / " & $iImgH & " = " & $iScaleY & @CRLF)

    $hMtx = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixScale($hMtx, $iBaseScale, $iBaseScale)
    If $iScaleX > $iScaleY Then
        _GDIPlus_MatrixTranslate($hMtx, ($iGfxW / 2) - (($iImgW * $iBaseScale) / 2), 0)
    ElseIf $iScaleY > $iScaleX Then
        _GDIPlus_MatrixTranslate($hMtx, 0, $iGfxH / 2)
    EndIf
    _GDIPlus_GraphicsSetTransform($hGfx, $hMtx)

    _GDIPlus_GraphicsDrawImageRectRect($hGfx, $hImg, 0, 0, $iImgW, $iImgH, 0, 0, $iImgW, $iImgH)

    _GDIPlus_MatrixDispose($hMtx)

    Return
EndFunc

Func _WinAPI_SetProp($hWnd, $sProp, $pData)
    Return DllCall("user32.dll", "bool", "SetPropW", "hwnd", $hWnd, "wstr", $sProp, "ptr", $pData)[0]
EndFunc

Func _WinAPI_GetProp($hWnd, $sProp)
    Return DllCall("user32.dll", "ptr", "GetPropW", "hwnd", $hWnd, "wstr", $sProp)[0]
EndFunc

Func _WinAPI_RemoveProp($hWnd, $sProp)
    Return DllCall("user32.dll", "ptr", "RemovePropW", "hwnd", $hWnd, "wstr", $sProp)[0]
EndFunc

For now, I'm stuck in the _drawImage function: I want to use the Matrix to display the image centered in the control, event when the window is resized.

next, I will try to make some zooming capability and translating the zoomed image.

Any help will be much appreciated.

 

Other option: if someone knows about some already existing library to do this (with WinAPI), I will not reinvent the wheel.

Edited by matwachich
Link to comment
Share on other sites

You could maybe get some inspiration from @LarsJ's "Navigating in an image"

https://www.autoitscript.com/forum/topic/167645-navigating-in-an-image/

/edit, hmm, appears you already know about that thread as you "like"'d a post in it seven years ago 😛 

 

Edited by Werty

Some guy's script + some other guy's script = my script!

Link to comment
Share on other sites

On 2/6/2022 at 1:53 PM, Werty said:

/edit, hmm, appears you already know about that thread as you "like"'d a post in it seven years ago 😛 

didn't remember this one. It exactly what I want to implement in my project!

Thanks :)

I see that I liked a post asking for a simpler version, understandable by beginers. Hope I will understand it better now with my 7 years experience ;)

Edit: it seems after first look that the script is too much complexe for what it does ; exemple: using raw calculations for zooming and image navigation. I'm sure that this can be done simply with GDI+ matrix, but without any experience with them, I'm totally stuck!

Edited by matwachich
Link to comment
Share on other sites

It's easy and very fast using GDI...

HotKeySet("{ESC}", "_exit")
Global $hZoomDC, $hDesktopDC
GUICreate("Zoom", 512, 512, 0, 0, 0x80000000)
GUISetState()
$hZoomDC = DllCall("user32.dll", "handle", "GetDC", "hwnd", WinGetHandle("Zoom"))
$hDesktopDC = DllCall("user32.dll", "handle", "GetDC", "hwnd", 0)



While 1
   DllCall("gdi32.dll", "int", "StretchBlt", "int", $hZoomDC[0], "int", 0, "int", 0, "int", 512, "int", 512, "int", $hDesktopDC[0], "int", MouseGetPos()[0]-128, "int", MouseGetPos()[1]-128, "int",  256, "int",  256, "long", 0x00CC0020)
   Sleep(1)
WEnd

Func _exit()
    DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "handle", $hDesktopDC)
    DllCall("user32.dll", "int", "ReleaseDC", "hwnd", WinGetHandle("Zoom"), "handle", $hZoomDC)
    Exit
EndFunc

Try moving your mouse around, updates instantly, also try with a movie, it's better than the built in magnifier in windows, that is very laggy.

You can figure out the different parameters yourself.

Edited by Werty

Some guy's script + some other guy's script = my script!

Link to comment
Share on other sites

  • 2 weeks later...

OK, so I dropped GDI+ and now I'm with plain GDI (way smoother!)

Here is my code so far

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

_GDIPlus_Startup()
OnAutoItExitRegister(_GDIPlus_Shutdown)

$hImage = _GDIPlus_ImageLoadFromFile("testHD.png")
$hBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_GDIPlus_ImageDispose($hImage)

Global $fOffsetX = 0.5, $fOffsetY = 0.5

$hGUI = GUICreate("Test", 640 + 16, 420 + 16, -1, -1, $WS_OVERLAPPEDWINDOW)
$Pic = GUICtrlCreatePic("", 8, 8, 640, 420)
GUICtrlSetResizing($Pic, $GUI_DOCKBORDERS) ; $GUI_DOCKALL

_WinAPI_SetWindowSubclass(GUICtrlGetHandle($Pic), DllCallbackGetPtr(DllCallbackRegister(_wmHandler, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")), 0)

GUISetState()

Do
Until GUIGetMsg() = -3

_WinAPI_DeleteObject($hBITMAP)


Func _wmHandler($hWnd, $iMsg, $wParam, $lParam, $iSubclassID, $pUserData)
    Switch $iMsg
        Case $WM_PAINT
            Local $tPS = DllStructCreate($tagPAINTSTRUCT)
            Local $hDC = _WinAPI_BeginPaint($hWnd, $tPS)

            ; to keep quality when stretching
            _WinAPI_SetStretchBltMode($hDC, $HALFTONE)

            ; create memory DC
            Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
            _WinAPI_SelectObject($hMemDC, $hBITMAP)

            ; get DC and BITMAP sizes
            Local $iDcW, $iDcH, $iBmpW, $iBmpH
            __guiCtrlPicEx_getDcSize($hDC, $iDcW, $iDcH)
            __guiCtrlPicEx_getBitmapSize($hBITMAP, $iBmpW, $iBmpH)

            ; adjuste
;~          _WinAPI_SetGraphicsMode($hDC, $GM_ADVANCED)
;~          Local $tXFORM = _WinAPI_CreateTransform(1, 0, 0, 1,);, -(($iBmpW/2) - ($iDcW/2)), -(($iBmpH/2) - ($iDcH/2)))
;~          _WinAPI_SetWorldTransform($hDC, $tXFORM)

            ; draw
            _WinAPI_StretchBlt( _
                $hDC, 0, 0, $iDcW, $iDcH, _
                $hMemDC, $fOffsetX * ($iBmpW - $iDcW), $fOffsetY * ($iBmpH - $iDcH), $iDcW, $iDcH, _
                $SRCCOPY _
            )

            ; cleanum
            _WinAPI_DeleteObject($hMemDC)
            _WinAPI_EndPaint($hWnd, $tPS)
    EndSwitch
    Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc

Func __guiCtrlPicEx_getDcSize($hDC, ByRef $iWidth, ByRef $iHeight)
    Local $hWnd = _WinAPI_WindowFromDC($hDC)
    $iWidth = _WinAPI_GetClientWidth($hWnd)
    $iHeight = _WinAPI_GetClientHeight($hWnd)
EndFunc

Func __guiCtrlPicEx_getBitmapSize($hBITMAP, ByRef $iWidth, ByRef $iHeight)
    Local $tBITMAP = DllStructCreate($tagBITMAP)
    _WinAPI_GetObject($hBITMAP, DllStructGetSize($tBITMAP), $tBITMAP)
    $iWidth = $tBITMAP.bmWidth
    $iHeight = $tBITMAP.bmHeight
EndFunc

Now, next step is to correctly handle zooming (scaling) and paning (translating) of the picture, just like any image viewer software.

I just figure out how to make it correctly with all image possibilities (bigger/smaller than the viewport (DC), different aspect ratios...).

I have no experience in this, so I refer to you're help guys!

Thanks :)

 

PS: I use the attached images for simple developpement process

testHD.png

testSD.png

Link to comment
Share on other sites

Ok, I think I got it! :D

Here is my actual experimental code

#NoTrayIcon
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <Math.au3>
#include <Memory.au3>

Enum _
    $__WM_GUIPICEX_INIT = $WM_USER

_GDIPlus_Startup()
OnAutoItExitRegister(_GDIPlus_Shutdown)

$hImage = _GDIPlus_ImageLoadFromFile("testHD.png")
$hBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_GDIPlus_ImageDispose($hImage)

$hGUI = GUICreate("Test", 640 + 16, 420 + 16, -1, -1, $WS_OVERLAPPEDWINDOW)
$Pic = GUICtrlCreatePic("", 8, 8, 640, 420)
GUICtrlSetResizing($Pic, $GUI_DOCKBORDERS) ; $GUI_DOCKALL

_WinAPI_SetWindowSubclass(GUICtrlGetHandle($Pic), DllCallbackGetPtr(DllCallbackRegister(_wmHandler, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")), 0)
_SendMessage(GUICtrlGetHandle($Pic), $__WM_GUIPICEX_INIT)

GUISetState()

Do
Until GUIGetMsg() = -3

_WinAPI_DeleteObject($hBITMAP)


Func _wmHandler($hWnd, $iMsg, $wParam, $lParam, $iSubclassID, $pUserData)
    Static $s_tagGUIPICEX = "handle bitmap; double zoom; int wheelAccum; double offsetX; double offsetY; int dragOrigX; int dragOrigY"

    Switch $iMsg
        Case $__WM_GUIPICEX_INIT
            Local $pData = _MemGlobalAlloc(DllStructGetSize(DllStructCreate($s_tagGUIPICEX)), $GPTR) ; zero inited
            Local $tData = DllStructCreate($s_tagGUIPICEX, $pData)
            $tData.zoom = 1
            $tData.offsetX = 0.5
            $tData.offsetY = 0.5

            _WinAPI_SetProp($hWnd, "DATA", $pData)

        Case $WM_DESTROY
            Local $pData = _WinAPI_RemoveProp($hWnd, "DATA")

            Local $tData = DllStructCreate($s_tagGUIPICEX, $pData)
;~          If $tData.image Then _GDIPlus_ImageDispose($tData.image)

            _MemGlobalFree($pData)

        Case $WM_PAINT
            Local $tData = __guiCtrlPicEx_getInternalData($hWnd, $s_tagGUIPICEX)

            ; begin paint
            Local $tPS = DllStructCreate($tagPAINTSTRUCT)
            Local $hDC = _WinAPI_BeginPaint($hWnd, $tPS)

            ; to keep quality when stretching
            _WinAPI_SetStretchBltMode($hDC, $HALFTONE)

            ; create memory DC
            Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
            _WinAPI_SelectObject($hMemDC, $hBITMAP)

            ; get DC and BITMAP sizes
            Local $iDcW, $iDcH, $iBmpW, $iBmpH
            __guiCtrlPicEx_getDcSize($hDC, $iDcW, $iDcH)
            __guiCtrlPicEx_getBitmapSize($hBITMAP, $iBmpW, $iBmpH)

            ; this is the base display ratio ; used when the image is not zoomed
            Local $fBaseRatio = _Max($iBmpW / $iDcW, $iBmpH / $iDcH)

            ; the actual display ratio is calculated like this
            Local $fRatio = $fBaseRatio / $tData.zoom ; when zoom = 1, then ratio = baseRatio => image is not stretched

            ; now, calculate drawOffset ; between 0 and 1
            Local $fDrawOffsetX, $fDrawOffsetY
            If $fRatio = $fBaseRatio Then
                ; center the image when not zoomed
                $fDrawOffsetX = 0.5
                $fDrawOffsetY = 0.5
            Else
                $fDrawOffsetX = $tData.offsetX
                $fDrawOffsetY = $tData.offsetY
            EndIf

            ; calculate virtual viewport size (will condition the zooming level)
            Local $iVpW = $iDcW * $fRatio
            Local $iVpH = $iDcH * $fRatio

            ; actual draw
            _WinAPI_StretchBlt( _
                $hDC, 0, 0, $iDcW, $iDcH, _ ; always draw the entire DC
                $hMemDC, $fDrawOffsetX * ($iBmpW - $iVpW), $fDrawOffsetY * ($iBmpH - $iVpH), $iVpW, $iVpH, _ ; draw at offset, with viewport size
                $SRCCOPY _
            )

            ; cleanum
            _WinAPI_DeleteObject($hMemDC)
            _WinAPI_EndPaint($hWnd, $tPS)

        Case $WM_LBUTTONDOWN
            _WinAPI_SetCapture($hWnd)

            ; reset drag calculation
            Local $tData = __guiCtrlPicEx_getInternalData($hWnd, $s_tagGUIPICEX)
            $tData.dragOrigX = __guiCtrlPicEx_getXParam($lParam)
            $tData.dragOrigY = __guiCtrlPicEx_getYParam($lParam)

        Case $WM_LBUTTONUP
            _WinAPI_ReleaseCapture()

        Case $WM_MOUSEMOVE
            If DllCall("user32.dll", "hwnd", "GetCapture")[0] = $hWnd Then
                Local $tData = __guiCtrlPicEx_getInternalData($hWnd, $s_tagGUIPICEX)

                ; get movement delta
                Local $iPosX = __guiCtrlPicEx_getXParam($lParam), $iPosY = __guiCtrlPicEx_getYParam($lParam)
                Local $iDeltaX = $iPosX - $tData.dragOrigX, $iDeltaY = $iPosY - $tData.dragOrigY
                $tData.dragOrigX = $iPosX
                $tData.dragOrigY = $iPosY

                ; update display offset
                $tData.offsetX += -$iDeltaX / _WinAPI_GetClientWidth($hWnd)
                $tData.offsetY += -$iDeltaY / _WinAPI_GetClientHeight($hWnd)
                $tData.offsetX = __guiCtrlPicEx_trapNumber($tData.offsetX, 0, 1)
                $tData.offsetY = __guiCtrlPicEx_trapNumber($tData.offsetY, 0, 1)

                ; redraw
                _WinAPI_InvalidateRect($hWnd)
            EndIf

        Case $WM_MOUSEWHEEL
            Local $tData = __guiCtrlPicEx_getInternalData($hWnd, $s_tagGUIPICEX)

            ; get wheel delta
            Local $iDelta = __guiCtrlPicEx_getWheelDelta($wParam)

            ; if rotation direction is changed before reaching threeshold (WHEEL_DELTA = 120), then reset
            If $iDelta > 0 And $tData.wheelAccum < 0 Or $iDelta < 0 And $tData.wheelAccum > 0 Then $tData.wheelAccum = 0

            ; accumulate current delta
            $tData.wheelAccum += $iDelta

            ; when delta reaches threeshold, update zoom level
            If Abs($tData.wheelAccum) >= 120 Then
                $tData.zoom += ($tData.wheelAccum > 0 ? 0.5 : -0.5)
                $tData.zoom = __guiCtrlPicEx_trapNumber($tData.zoom, 1, 10)
                _WinAPI_InvalidateRect($hWnd)
                $tData.wheelAccum = 0
            EndIf
    EndSwitch
    Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc

Func __guiCtrlPicEx_getDcSize($hDC, ByRef $iWidth, ByRef $iHeight)
    Local $hWnd = _WinAPI_WindowFromDC($hDC)
    $iWidth = _WinAPI_GetClientWidth($hWnd)
    $iHeight = _WinAPI_GetClientHeight($hWnd)
EndFunc

Func __guiCtrlPicEx_getBitmapSize($hBITMAP, ByRef $iWidth, ByRef $iHeight)
    Local $tBITMAP = DllStructCreate($tagBITMAP)
    _WinAPI_GetObject($hBITMAP, DllStructGetSize($tBITMAP), $tBITMAP)
    $iWidth = $tBITMAP.bmWidth
    $iHeight = $tBITMAP.bmHeight
EndFunc

Func __guiCtrlPicEx_trapNumber($vNum, $vMin, $vMax)
    If $vNum < $vMin Then $vNum = $vMin
    If $vNum > $vMax Then $vNum = $vMax
    Return $vNum
EndFunc

; we must use these functions and not HiWord/LoWord because mouse pos are signed
Func __guiCtrlPicEx_getXParam($lParam)
    $t = DllStructCreate("dword XY")
    $t.XY = $lParam
    $t2 = DllStructCreate("short X; short Y", DllStructGetPtr($t))
    Return $t2.X
EndFunc
Func __guiCtrlPicEx_getYParam($lParam)
    $t = DllStructCreate("dword XY")
    $t.XY = $lParam
    $t2 = DllStructCreate("short X; short Y", DllStructGetPtr($t))
    Return $t2.Y
EndFunc
Func __guiCtrlPicEx_getWheelDelta($wParam)
    $t = DllStructCreate("dword DW")
    $t.DW = $wParam
    $t2 = DllStructCreate("short keystate; short delta", DllStructGetPtr($t))
    Return $t2.delta
EndFunc

Func __guiCtrlPicEx_getInternalData($hWnd, $sTag)
    Return DllStructCreate($sTag, _WinAPI_GetProp($hWnd, "DATA"))
EndFunc

Func _WinAPI_SetProp($hWnd, $sProp, $pData)
    Return DllCall("user32.dll", "bool", "SetPropW", "hwnd", $hWnd, "wstr", $sProp, "ptr", $pData)[0]
EndFunc

Func _WinAPI_GetProp($hWnd, $sProp)
    Return DllCall("user32.dll", "ptr", "GetPropW", "hwnd", $hWnd, "wstr", $sProp)[0]
EndFunc

Func _WinAPI_RemoveProp($hWnd, $sProp)
    Return DllCall("user32.dll", "ptr", "RemovePropW", "hwnd", $hWnd, "wstr", $sProp)[0]
EndFunc

Every essentials work as expected.

Some polish is needed (better translation speed, getting rid of the black background...), and I will make a UDF.

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...