Jump to content

Smooth display of PNGs with transparency, fade-in/out and AOT


timmy2
 Share

Recommended Posts

l93c.png

After UEZ helped me with the Countdown Timer his techniques seemed perfect for displaying individual images with transparency. One thing led to another and here's the resulting script.

Download the attached zip file and place the 5 PNG files in the same folder as this script. I did not embed the images in the script, to make the script easier to read and so you can see the actual images used.

In my opinion the ultimate next step would be to add the ability to play animated GIFs, still with transparency if that's possible.

Enjoy! (with much gratitude to UEZ for his help)

; Functions coded by UEZ 2013-10-29
; Updated to address issues 2013-10-31
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#NoTrayIcon

_GDIPlus_Startup() ;initiate GDI+

#region
; timmy2's simple demonstration of UEZ's code
;
; display blank chalkboard (there will be no fade-in so use default $iAlpha value of 255)
$aRes1 = DisplayImage( "Wood-framed-chalkboard.png", -1, -1 )
Sleep (500)

; add first two steps
$aRes2 = DisplayImage("step-1.png", -1, -1 )
Sleep(2000)
$aRes3 = DisplayImage("step-2.png", -1, -1 )

; fade in handdrawn circle (therefore start with $iAlpha = 0)
$aPos = WinGetPos($aRes1[0]) ;required because the chalkboard is displayed at screen center, which varies based on resolution (doh!)
$aRes4 = DisplayImage("circle.png",  $aPos[0] + 290, $aPos[1] + 75, 0)
sleep (500)
_Fader($aRes4)
sleep(1000)
_Fader($aRes4, False)
ReleaseResources($aRes4)
sleep(500)


; add third step
$aRes5 = DisplayImage("step-3.png", -1, -1 )
Sleep(2000)

; fade the three steps out in reverse order (faster than defaults)
_Fader($aRes5, False, 255, 5, 5)
ReleaseResources($aRes5)
_Fader($aRes3, False, 255, 5, 5)
ReleaseResources($aRes3)
_Fader($aRes2, False, 255, 5, 5)
ReleaseResources($aRes2)

Sleep(500)

; fade out chockboard
_Fader($aRes1, False, 255, 10, 5)
ReleaseResources($aRes1)
#endregion

_GDIPlus_Shutdown()

Exit

; Display the image at center unless otherwise specified. If Fader will not be used then $iAlpha's default of 0xFF is good.
; If Fader will be used then start with $iAlpha equal to zero.  Option to make this image "Always on top" is also available.
Func DisplayImage($sFile, $iPosX = -1, $iPosY = -1, $iAlpha = 0xFF, $bTopmost = True)
    Local Const $hBmp_Background = _GDIPlus_BitmapCreateFromFile($sFile) ;load the image
    If @error Then Return SetError(1, 0, 0) ;image cannot be loaded
    Local Const $iW = _GDIPlus_ImageGetWidth($hBmp_Background), $iH = _GDIPlus_ImageGetHeight($hBmp_Background) ;get the dimension of the background image
    Local Const $hGUI = GUICreate("", $iW, $iH, $iPosX, $iPosY, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST * $bTopmost, $WS_EX_TOOLWINDOW)) ;create GUI with appropriate styles and extented style (borderless transparent GUI)
    GUICtrlCreateLabel("", 0, 0, $iW, $iH, Default, $GUI_WS_EX_PARENTDRAG) ;create a hidden label for GUI dragging
    GUISetState(@SW_SHOW, $hGUI) ;show GUI

    Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) ;define an empty bitmap where all the gfx stuff will copied to
    Local Const $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;get the context to the bitmap to be able to copy / draw to the bitmap
    _GDIPlus_GraphicsDrawImageRect($hGfx, $hBmp_Background, 0, 0, $iW, $iH) ;draw background image to the empty bitmap

    ;display GDI+ with transparency on desktop
    Local Const $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) ;convert GDI+ image to GDI to display it on the screen using GDI functions
    Local Const $hScrDC = _WinAPI_GetDC($hGUI) ;get the device context (dc) handle of the GUI
    Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) ;create a compatible dc handle
    Local Const $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap) ;selects the GDI bitmap object into the specified device context
    Local Const $tSize = DllStructCreate($tagSIZE) ;create a $tagSIZE struct (x = width, y = height)
    DllStructSetData($tSize, "X", $iW) ;set data for width
    DllStructSetData($tSize, "Y", $iH) ;set data for height
    Local $tSource = DllStructCreate($tagPOINT) ;create a $tagPOINT struct (x = x position, y = y position)
    Local $tBlend = DllStructCreate($tagBLENDFUNCTION) ;create $tagBLENDFUNCTION struct -> see help file for more info
    DllStructSetData($tBlend, "Alpha", $iAlpha) ;set the alpha channel of the GUI -> 255 = opaque, 0 = transparent
    DllStructSetData($tBlend, "Format", 1) ;set the format to 1 -> bitmap has alpha channels
    DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $hGUI, "handle", $hScrDC, "ptr", 0, "struct*", $tSize, "handle", $hMemDC, "struct*", $tSource, "dword", 0, "struct*", $tBlend, "dword", $ULW_ALPHA) ;display bitmap on screen

    ;release resources otherwise memory will filled up (memory leak)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BitmapDispose($hBitmap)
    Local $aResource[7] = [$hGUI, $hScrDC, $hHBitmap, $hMemDC, $tBlend, $tSize, $tSource] ;return the handle to release it later
    Return $aResource
EndFunc   ;==>DisplayImage

; This function releases the resources of a specific image and closes it
Func ReleaseResources(ByRef $aResource)
    If Not IsArray($aResource) Then Return SetError(1, 0, 0)
    If UBound($aResource) <> 7 Then Return SetError(2, 0, 0)
    _WinAPI_ReleaseDC($aResource[0], $aResource[1])
    _WinAPI_DeleteDC($aResource[3])
    _WinAPI_DeleteObject($aResource[2])
    GUIDelete($aResource[0])
EndFunc   ;==>ReleaseResources

; To fade in an image leave $bIn at default (True); to fade out specify False.
; There are also options to set the ending transparency level (0 transparent, 255 opaque), speed and delay.
; If you change the speed or delay be sure to specify $bIn and $iTrans, otherwise you'll wonder why the fade-in or out isn't what you hoped for.
; The default values are specified in the function below.
Func _Fader($res1, $bIn = True, $iTrans = 255, $speed = 3, $delay = 10  )
    If Not IsArray($res1) Then Return SetError(1, 0, 0)
    If UBound($res1) <> 7 Then Return SetError(2, 0, 0)
    Switch $bIn
        Case True
            For $a = 0 To $iTrans Step $speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
        Case Else
            For $a = $iTrans To 0 Step -$speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
    EndSwitch
EndFunc   ;==>_FadeIn



#region GDI and GDI+ functions
Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iPixelFormat = $GDIP_PXF32ARGB, $iStride = 0, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aResult[0] Then Return SetError(10, $aResult[0], 0)
    Return $aResult[6]
EndFunc   ;==>_GDIPlus_BitmapCreateFromScan0
#endregion GDI and GDI+ functions

images.zip

Edited by timmy2
Link to comment
Share on other sites

Seems to be that an image wasn't loaded properly.

 

Try this function and check error code please:

Func _Fader($res1, $bIn = True, $iTrans = 255, $speed = 3, $delay = 10  )
    If Not IsArray($res1) Then Return SetError(1, 0, 0)
    If UBound($res1) <> 7 Then Return SetError(2, 0, 0)
    Switch $bIn
        Case True
            For $a = 0 To $iTrans Step $speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
        Case Else
            For $a = $iTrans To 0 Step -$speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
    EndSwitch
EndFunc   ;==>_FadeIn
Br,

UEZ

Edited by UEZ

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

Further, due to different screen resolutions the circle is only placed properly when the screen resolution is the same as yours.

Try this instead:

; fade in handdrawn circle (therefore start with $iAlpha = 0)
$aPos = WinGetPos($aRes1[0])
$aRes4 = DisplayImage("circle.png",  $aPos[0] + 290, $aPos[1] + 75, 0)
sleep (500)
_Fader($aRes4)
sleep(1000)
_Fader($aRes4, False)
ReleaseResources($aRes4)
sleep(500)

; add third step

Br,

UEZ

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

Replace these lines and post the result:

$aRes1 = DisplayImage( "Wood-framed-chalkboard.png", -1, -1 )
If @error Then Exit MsgBox(0, "", @error)

Further test with 

$aRes1 = DisplayImage( @ScriptDir & "\Wood-framed-chalkboard.png", -1, -1 )

Be sure that the images are in the same folder as the script!

Br,

UEZ

Edited by UEZ

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

Your main function...

$aRes1 = DisplayImage("step-1.png")

...returns an array in $aRes1.  To use WinMove with this image the correct instruction is:

WinMove($aRes1[0], "", 500, 600)

So, the first element in the array at index zero is a handle useable by WinMove. That leaves 7 other elements in the array, correct?

(If UBound($aResource) <> 7 Then Return SetError(2, 0, 0))

I'm curious. What is stored in these other elements?

Link to comment
Share on other sites

Your main function...

$aRes1 = DisplayImage("step-1.png")

...returns an array in $aRes1.  To use WinMove with this image the correct instruction is:

WinMove($aRes1[0], "", 500, 600)

So, the first element in the array at index zero is a handle useable by WinMove. That leaves 7 other elements in the array, correct?

(If UBound($aResource) <> 7 Then Return SetError(2, 0, 0))

I'm curious. What is stored in these other elements?

 

Here more information about the returned array:

Local $aResource[7] = [$hGUI, _ ;GUI handle
                           $hScrDC, _ ;device context (dc) handle of the GUI (GDI)
                           $hHBitmap, _ ;GDI bitmap handle of the displayed image
                           $hMemDC, _ ;compatible dc handle from $hScrDC
                           $tBlend, _ ;tBlend struct (source blend oper., flags, alpha value, format) -> see help file for description
                           $tSize, _ ;tSize struct (width and height of the window / image)
                           $tSource] ;tSource struct for x / y position of the GUI
    Return $aResource ;returns the handles to release it later or to use it for fading effects

Here the complete code:

; Functions coded by UEZ 2013-11-02
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#NoTrayIcon

_GDIPlus_Startup() ;initiate GDI+

#region
; timmy2's simple demonstration of UEZ's code
;
; display blank chalkboard (there will be no fade-in so use default $iAlpha value of 255)
$aRes1 = DisplayImage( "Wood-framed-chalkboard.png", -1, -1 )
If @error Then
    ConsoleWrite( "Error " & @error & " has occured." & @LF )
    _GDIPlus_Shutdown()
    Exit
EndIf

Sleep (500)

; add first two steps
$aRes2 = DisplayImage("step-1.png", -1, -1 )
Sleep(2000)
$aRes3 = DisplayImage("step-2.png", -1, -1 )

; fade in handdrawn circle (therefore start with $iAlpha = 0)
$aPos = WinGetPos($aRes1[0])
$aRes4 = DisplayImage("circle.png",  $aPos[0] + 290, $aPos[1] + 75, 0)
sleep (500)
_Fader($aRes4)
sleep(1000)
_Fader($aRes4, False)
ReleaseResources($aRes4)
sleep(500)

; add third step
$aRes5 = DisplayImage("step-3.png", -1, -1 )
Sleep(2000)

; fade the three steps out in reverse order (faster than defaults)
_Fader($aRes5, False, 255, 5, 5)
ReleaseResources($aRes5)
_Fader($aRes3, False, 255, 5, 5)
ReleaseResources($aRes3)
_Fader($aRes2, False, 255, 5, 5)
ReleaseResources($aRes2)

Sleep(500)

; fade out chockboard
_Fader($aRes1, False, 255, 10, 5)
ReleaseResources($aRes1)
#endregion

_GDIPlus_Shutdown()

Exit

; Display the image at center unless otherwise specified. If Fader will not be used then $iAlpha's default of 0xFF is good.
; If Fader will be used then start with $iAlpha equal to zero.  Option to make this image "Always on top" is also available.
Func DisplayImage($sFile, $iPosX = -1, $iPosY = -1, $iAlpha = 0xFF, $bTopmost = True)
    Local Const $hBmp_Background = _GDIPlus_BitmapCreateFromFile($sFile) ;load the image
    If @error Then Return SetError(1, 0, 0) ;image cannot be loaded
    Local Const $iW = _GDIPlus_ImageGetWidth($hBmp_Background), $iH = _GDIPlus_ImageGetHeight($hBmp_Background) ;get the dimension of the background image
    Local Const $hGUI = GUICreate("", $iW, $iH, $iPosX, $iPosY, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST * $bTopmost, $WS_EX_TOOLWINDOW)) ;create GUI with appropriate styles and extented style (borderless transparent GUI)
    GUICtrlCreateLabel("", 0, 0, $iW, $iH, Default, $GUI_WS_EX_PARENTDRAG) ;create a hidden label for GUI dragging
    GUISetState(@SW_SHOW, $hGUI) ;show GUI

    Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) ;define an empty bitmap where all the gfx stuff will copied to
    Local Const $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;get the context to the bitmap to be able to copy / draw to the bitmap
    _GDIPlus_GraphicsDrawImageRect($hGfx, $hBmp_Background, 0, 0, $iW, $iH) ;draw background image to the empty bitmap

    ;display GDI+ with transparency on desktop
    Local Const $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) ;convert GDI+ image to GDI to display it on the screen using GDI functions
    Local Const $hScrDC = _WinAPI_GetDC($hGUI) ;get the device context (dc) handle of the GUI
    Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) ;create a compatible dc handle
    Local Const $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap) ;selects the GDI bitmap object into the specified device context
    Local Const $tSize = DllStructCreate($tagSIZE) ;create a $tagSIZE struct (x = width, y = height)
    DllStructSetData($tSize, "X", $iW) ;set data for width
    DllStructSetData($tSize, "Y", $iH) ;set data for height
    Local $tSource = DllStructCreate($tagPOINT) ;create a $tagPOINT struct (x = x position, y = y position)
    Local $tBlend = DllStructCreate($tagBLENDFUNCTION) ;create $tagBLENDFUNCTION struct -> see help file for more info
    DllStructSetData($tBlend, "Alpha", $iAlpha) ;set the alpha channel of the GUI -> 255 = opaque, 0 = transparent
    DllStructSetData($tBlend, "Format", 1) ;set the format to 1 -> bitmap has alpha channels
    DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $hGUI, "handle", $hScrDC, "ptr", 0, "struct*", $tSize, "handle", $hMemDC, "struct*", $tSource, "dword", 0, "struct*", $tBlend, "dword", $ULW_ALPHA) ;display bitmap on screen

    ;release resources otherwise memory will filled up (memory leak)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BitmapDispose($hBitmap)
    Local $aResource[7] = [$hGUI, _ ;GUI handle
                           $hScrDC, _ ;device context (dc) handle of the GUI (GDI)
                           $hHBitmap, _ ;GDI bitmap handle of the displayed image
                           $hMemDC, _ ;compatible dc handle from $hScrDC
                           $tBlend, _ ;tBlend struct (source blend oper., flags, alpha value, format) -> see help file for description
                           $tSize, _ ;tSize struct (width and height of the window / image)
                           $tSource] ;tSource struct for x / y position of the GUI
    Return $aResource ;returns the handles to release it later or to use it for fading effects
EndFunc   ;==>DisplayImage

; This function releases the resources of a specific image and closes it
Func ReleaseResources(ByRef $aResource)
    If Not IsArray($aResource) Then Return SetError(1, 0, 0)
    If UBound($aResource) <> 7 Then Return SetError(2, 0, 0)
    _WinAPI_ReleaseDC($aResource[0], $aResource[1])
    _WinAPI_DeleteDC($aResource[3])
    _WinAPI_DeleteObject($aResource[2])
    GUIDelete($aResource[0])
EndFunc   ;==>ReleaseResources

; To fade in an image leave $bIn at default (True); to fade out specify False.
; There are also options to set the ending transparency level (0 transparent, 255 opaque), speed and delay.
; If you change the speed or delay be sure to specify $bIn and $iTrans, otherwise you'll wonder why the fade-in or out isn't what you hoped for.
; The default values are specified in the function below.
Func _Fader($res1, $bIn = True, $iTrans = 255, $speed = 3, $delay = 10  )
    If Not IsArray($res1) Then Return SetError(1, 0, 0)
    If UBound($res1) <> 7 Then Return SetError(2, 0, 0)
    Switch $bIn
        Case True
            For $a = 0 To $iTrans Step $speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
        Case Else
            For $a = $iTrans To 0 Step -$speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
    EndSwitch
EndFunc   ;==>_FadeIn

#region GDI and GDI+ functions
Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iPixelFormat = $GDIP_PXF32ARGB, $iStride = 0, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aResult[0] Then Return SetError(10, $aResult[0], 0)
    Return $aResult[6]
EndFunc   ;==>_GDIPlus_BitmapCreateFromScan0
#endregion GDI and GDI+ functions

Br,

UEZ

Edited by UEZ

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

Can GUISetAccelerators be used with your code?  If not, what is the best way to add the ability to wait for some specific keys to be pressed without passing them through? 

8lcx.jpg

The only methods for waiting for keystrokes that I'm somewhat conversant with are _IsPressed and HotKeySet. The former allows all keystrokes to be passed through; the latter allows all keys other than the hotkeys to pass through. I don't want any keystrokes to pass through and want the "hotkeys" valid only when the graphic is displayed.

Edited by timmy2
Link to comment
Share on other sites

For another project I'm working on I came up with the following script. It has no relationship with UEZ's DisplayImage function but it'll serve as a solution until something better comes along. When the GUI is active it does not pass keystrokes through, but only when the GUI is active. In a separate thread I'm trying to chase down whether the BlockInputEX UDF can be used to truly isolate input to this form only.

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

$form = GUICreate("test", 0, 0,-1,-1,BitOR($WS_SYSMENU,$WS_POPUP))

$sHelp = GUICtrlCreateDummy()
$sRepeat = GUICtrlCreateDummy()
$sQuit = GUICtrlCreateDummy()
Dim $AccelKeys[3][2] = [["h", $sHelp],["r", $sRepeat],["q", $SQuit]]
GUISetAccelerators($AccelKeys)
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $sHelp
            ConsoleWrite("help" & @CRLF)
        Case $sRepeat
            ConsoleWrite("repeat" & @CRLF)
        Case $SQuit
            ConsoleWrite("quit" & @CRLF)
    EndSwitch
WEnd
Edited by timmy2
Link to comment
Share on other sites

You can use something like this here:

#include <GUIConstantsEx.au3>

$hGUI = GUICreate("Test")
GUISetState()
Global $aKeyboardState

Do
    If WinActive($hGUI) Then
        $aKeyboardState = _WinAPI_GetKeyboardState()
        If BitAND($aKeyboardState[0x48], 0xF0) > 0 Then
            ConsoleWrite("H key was pressed" & @LF)
        ElseIf BitAND($aKeyboardState[0x51], 0xF0) > 0 Then
            ConsoleWrite("Q key was pressed" & @LF)
        ElseIf BitAND($aKeyboardState[0x52], 0xF0) > 0 Then
            ConsoleWrite("R key was pressed" & @LF)
        EndIf
    EndIf
Until GUIGetMsg() = $GUI_EVENT_CLOSE


; #FUNCTION# ====================================================================================================================
; Name...........:  _WinAPI_GetKeyboardState
; Description ...:  Returns the status of the 256 virtual keys
; Syntax.........:  _WinAPI_GetKeyboardState($iFlag=0)
; Parameters ....:  $iFlag   - Return Type
;                   0 Returns an array[256]
;                   1 Returns a string
; Return values .:  Success  - Array[256] or String containing status of 256 virtual keys
;                   Failure  - False
; Author ........:  Eukalyptus
; Modified.......:
; Remarks .......:  If the high-order bit is 1, the key is down; otherwise, it is up.
;                   If the key is a toggle key, for example CAPS LOCK, then the low-order bit is 1
;                   when the key is toggled and is 0 if the key is untoggled
; Related .......:  _IsPressed
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func _WinAPI_GetKeyboardState($iFlag = 0)
    Local $aDllRet, $lpKeyState = DllStructCreate("byte[256]")
    $aDllRet = DllCall("User32.dll", "int", "GetKeyboardState", "ptr", DllStructGetPtr($lpKeyState))
    If @error Then Return SetError(@error, 0, 0)
    If $aDllRet[0] = 0 Then
        Return SetError(1, 0, 0)
    Else
        Switch $iFlag
            Case 0
                Local $aReturn[256]
                For $i = 1 To 256
                    $aReturn[$i - 1] = DllStructGetData($lpKeyState, 1, $i)
                Next
                Return $aReturn
            Case Else
                Return DllStructGetData($lpKeyState, 1)
        EndSwitch
    EndIf
EndFunc   ;==>_WinAPI_GetKeyboardState

Br,

UEZ

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

  • 2 months later...

Hi. Thanks for a nice code example. I'm having some issues getting it to work properly:

When I try running this example, nothing appears. I get no error messages in console, but still nothing is displayed.

The images are located in the same folder as the script. I also tried adding @ScriptDir, but without any luck.

I tried removing the styles from GUICreate, just to see if the windows appeared on my desktop, and that worked, but the window contents were just gray (no image/content) and no image faded in/out.

_GDIPlus_ImageGetWidth, etc. reports the correct values, so it seems to be an issue with displaying the images on the Gui.

I'm running Autoit 3.3.6.1 on Win 8.1.

I'm using UEZs code "Complete Code"-example, Posted 02 November 2013 - 01:49 PM:

; Functions coded by UEZ 2013-11-02
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#NoTrayIcon

_GDIPlus_Startup() ;initiate GDI+

#region
; timmy2's simple demonstration of UEZ's code
;
; display blank chalkboard (there will be no fade-in so use default $iAlpha value of 255)
$aRes1 = DisplayImage( "Wood-framed-chalkboard.png", -1, -1 )
If @error Then
    ConsoleWrite( "Error " & @error & " has occured." & @LF )
    _GDIPlus_Shutdown()
    Exit
EndIf

Sleep (500)

; add first two steps
$aRes2 = DisplayImage("step-1.png", -1, -1 )
Sleep(2000)
$aRes3 = DisplayImage("step-2.png", -1, -1 )

; fade in handdrawn circle (therefore start with $iAlpha = 0)
$aPos = WinGetPos($aRes1[0])
$aRes4 = DisplayImage("circle.png",  $aPos[0] + 290, $aPos[1] + 75, 0)
sleep (500)
_Fader($aRes4)
sleep(1000)
_Fader($aRes4, False)
ReleaseResources($aRes4)
sleep(500)

; add third step
$aRes5 = DisplayImage("step-3.png", -1, -1 )
Sleep(2000)

; fade the three steps out in reverse order (faster than defaults)
_Fader($aRes5, False, 255, 5, 5)
ReleaseResources($aRes5)
_Fader($aRes3, False, 255, 5, 5)
ReleaseResources($aRes3)
_Fader($aRes2, False, 255, 5, 5)
ReleaseResources($aRes2)

Sleep(500)

; fade out chockboard
_Fader($aRes1, False, 255, 10, 5)
ReleaseResources($aRes1)
#endregion

_GDIPlus_Shutdown()

Exit

; Display the image at center unless otherwise specified. If Fader will not be used then $iAlpha's default of 0xFF is good.
; If Fader will be used then start with $iAlpha equal to zero.  Option to make this image "Always on top" is also available.
Func DisplayImage($sFile, $iPosX = -1, $iPosY = -1, $iAlpha = 0xFF, $bTopmost = True)
    Local Const $hBmp_Background = _GDIPlus_BitmapCreateFromFile($sFile) ;load the image
    If @error Then Return SetError(1, 0, 0) ;image cannot be loaded
    Local Const $iW = _GDIPlus_ImageGetWidth($hBmp_Background), $iH = _GDIPlus_ImageGetHeight($hBmp_Background) ;get the dimension of the background image
    Local Const $hGUI = GUICreate("", $iW, $iH, $iPosX, $iPosY, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST * $bTopmost, $WS_EX_TOOLWINDOW)) ;create GUI with appropriate styles and extented style (borderless transparent GUI)
    GUICtrlCreateLabel("", 0, 0, $iW, $iH, Default, $GUI_WS_EX_PARENTDRAG) ;create a hidden label for GUI dragging
    GUISetState(@SW_SHOW, $hGUI) ;show GUI

    Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) ;define an empty bitmap where all the gfx stuff will copied to
    Local Const $hGfx = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;get the context to the bitmap to be able to copy / draw to the bitmap
    _GDIPlus_GraphicsDrawImageRect($hGfx, $hBmp_Background, 0, 0, $iW, $iH) ;draw background image to the empty bitmap

    ;display GDI+ with transparency on desktop
    Local Const $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) ;convert GDI+ image to GDI to display it on the screen using GDI functions
    Local Const $hScrDC = _WinAPI_GetDC($hGUI) ;get the device context (dc) handle of the GUI
    Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) ;create a compatible dc handle
    Local Const $hOld = _WinAPI_SelectObject($hMemDC, $hHBitmap) ;selects the GDI bitmap object into the specified device context
    Local Const $tSize = DllStructCreate($tagSIZE) ;create a $tagSIZE struct (x = width, y = height)
    DllStructSetData($tSize, "X", $iW) ;set data for width
    DllStructSetData($tSize, "Y", $iH) ;set data for height
    Local $tSource = DllStructCreate($tagPOINT) ;create a $tagPOINT struct (x = x position, y = y position)
    Local $tBlend = DllStructCreate($tagBLENDFUNCTION) ;create $tagBLENDFUNCTION struct -> see help file for more info
    DllStructSetData($tBlend, "Alpha", $iAlpha) ;set the alpha channel of the GUI -> 255 = opaque, 0 = transparent
    DllStructSetData($tBlend, "Format", 1) ;set the format to 1 -> bitmap has alpha channels
    DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $hGUI, "handle", $hScrDC, "ptr", 0, "struct*", $tSize, "handle", $hMemDC, "struct*", $tSource, "dword", 0, "struct*", $tBlend, "dword", $ULW_ALPHA) ;display bitmap on screen

    ;release resources otherwise memory will filled up (memory leak)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_BitmapDispose($hBitmap)
    Local $aResource[7] = [$hGUI, _ ;GUI handle
                           $hScrDC, _ ;device context (dc) handle of the GUI (GDI)
                           $hHBitmap, _ ;GDI bitmap handle of the displayed image
                           $hMemDC, _ ;compatible dc handle from $hScrDC
                           $tBlend, _ ;tBlend struct (source blend oper., flags, alpha value, format) -> see help file for description
                           $tSize, _ ;tSize struct (width and height of the window / image)
                           $tSource] ;tSource struct for x / y position of the GUI
    Return $aResource ;returns the handles to release it later or to use it for fading effects
EndFunc   ;==>DisplayImage

; This function releases the resources of a specific image and closes it
Func ReleaseResources(ByRef $aResource)
    If Not IsArray($aResource) Then Return SetError(1, 0, 0)
    If UBound($aResource) <> 7 Then Return SetError(2, 0, 0)
    _WinAPI_ReleaseDC($aResource[0], $aResource[1])
    _WinAPI_DeleteDC($aResource[3])
    _WinAPI_DeleteObject($aResource[2])
    GUIDelete($aResource[0])
EndFunc   ;==>ReleaseResources

; To fade in an image leave $bIn at default (True); to fade out specify False.
; There are also options to set the ending transparency level (0 transparent, 255 opaque), speed and delay.
; If you change the speed or delay be sure to specify $bIn and $iTrans, otherwise you'll wonder why the fade-in or out isn't what you hoped for.
; The default values are specified in the function below.
Func _Fader($res1, $bIn = True, $iTrans = 255, $speed = 3, $delay = 10  )
    If Not IsArray($res1) Then Return SetError(1, 0, 0)
    If UBound($res1) <> 7 Then Return SetError(2, 0, 0)
    Switch $bIn
        Case True
            For $a = 0 To $iTrans Step $speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
        Case Else
            For $a = $iTrans To 0 Step -$speed
                DllStructSetData($res1[4], "Alpha", $a)
                DllCall("user32.dll", "bool", "UpdateLayeredWindow", "hwnd", $res1[0], "handle", $res1[1], "ptr", 0, "struct*", $res1[5], "handle", $res1[3], "struct*", $res1[6], "dword", 0, "struct*", $res1[4], "dword", $ULW_ALPHA) ;display bitmap on screen
                Sleep($delay)
            Next
    EndSwitch
EndFunc   ;==>_FadeIn

#region GDI and GDI+ functions
Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iPixelFormat = $GDIP_PXF32ARGB, $iStride = 0, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "handle*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    If $aResult[0] Then Return SetError(10, $aResult[0], 0)
    Return $aResult[6]
EndFunc   ;==>_GDIPlus_BitmapCreateFromScan0
#endregion GDI and GDI+ functions
Link to comment
Share on other sites

Works properly on Win8.1. Update to the latest AutoIt version and removed the _GDIPlus_BitmapCreateFromScan0 function because it is already included.

Try again.

Br,

UEZ

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

  • 4 months later...

This chalkboard example has great potential for a variety of uses ... if one aspect could be changed:

How can all the displayed elements be set so that when the chalkboard is dragged, those elements move with it? ... yet, have each element remain positionable on the chalkboard.

Each element is enabled with:

    GUICtrlCreateLabel("", 0, 0, $iW, $iH, Default, $GUI_WS_EX_PARENTDRAG) ;create a hidden label for GUI dragging
 

But the coordinates are absolute, not relative to the chalkboard.  Would this involve the GUICoordMode setting?  Is it even practical to consider this?

Thanks in advance for any suggestions/ideas.

Link to comment
Share on other sites

  • 2 years later...
On 5/19/2014 at 5:27 PM, qwert said:

This chalkboard example has great potential for a variety of uses ... if one aspect could be changed:

How can all the displayed elements be set so that when the chalkboard is dragged, those elements move with it? ... yet, have each element remain positionable on the chalkboard.

Each element is enabled with:

    GUICtrlCreateLabel("", 0, 0, $iW, $iH, Default, $GUI_WS_EX_PARENTDRAG) ;create a hidden label for GUI dragging
 

But the coordinates are absolute, not relative to the chalkboard.  Would this involve the GUICoordMode setting?  Is it even practical to consider this?

Thanks in advance for any suggestions/ideas.

Great idea! Any luck finding a solution?

Link to comment
Share on other sites

Your break was too long I think. ;)

 

Replace $ghGDIPDLL with $__g_hGDIPDll and it should or use latest AutoIt version.

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

I suppose I should change my username to Rip Van Winkle.

Before resuming my use of AutoIt after the long sleep I downloaded the production version v3.3.14.2.  The beta version appears to predate it.  What version do you recommend?

FYI, I replaced $ghGDIPDLL with $__g_hGDIPDll and that fixed the "undeclared global variable" error, but I'm still getting the "already defined" error -- with v3.3.14.2.

 

Am glad to see you're still active after lo these many years.

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

×
×
  • Create New...