Jump to content

transparent paint?, How to?


Gianni
 Share

Recommended Posts

Hi

Is it possible to draw using a semitransparent paint?
In short, I would like to paint on a Label control that contains text, and at the same time be able to see through the paint, so to see the text behind.
Something like using an highlighter.

Only to show the effect that I would achieve, here are two listings. The first, using transparency on the whole gui, allows to draw an ellipse into the gui's body showing at the same time what's beneath the ellipse's border. (the inner of the ellipse should be totally transparent.) Click on the GUI and drag to draw the ellipse.

#include <Misc.au3> ; for _IsPressed (01 Left mouse button)
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <WinAPIGdi.au3>

Opt("MouseCoordMode", 0)

Global $hUser32dll = DllOpen("user32.dll") ; for _IsPressed

Local $aPos

; -- Create the GUI -------------------------------
Global $hGUI = GUICreate("Preview of an ellipse (click and drag to draw)", 400, 400, 100, 100, -1, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))

Local $iTransparent = 0x0FF0FF ; tansparent color

; This sets which color to be transparent and opacity of the whole window
_WinAPI_SetLayeredWindowAttributes($hGUI, $iTransparent, 127) ; last param opacity intensity: 0 totally transp, 255 NOT transp

GUISetBkColor($iTransparent, $hGUI) ; background becomes transparent

GUISetState(@SW_SHOW)

; MAIN LOOP
While 1
    $aPos = MouseGetPos()
    $aMsg = GUIGetMsg($GUI_EVENT_ARRAY) ; $GUI_EVENT_ARRAY -> returns an array containing the event and extended information
    Select
        Case $aMsg[0] = $GUI_EVENT_CLOSE
            ConsoleWrite("Bye" & @LF)
            Exit ; End()
    EndSelect

    If _IsPressed("01", $hUser32dll) Then
        ; draw the ellipse following mouse position.
        ; returns only when left mouse button is released
        _Preview_Ellipse($hGUI, $aPos[0], $aPos[1], 24)
    EndIf

WEnd


Func _Preview_Ellipse($hGUIx, $iX, $iY, $iPenSize = 9, $iColor = 0xFF0000, $iFill = 0x0FF0FF)

    ; Creates $tagRECT structure with the coordinates of the specified rectangle
    Local $tRECT = _WinAPI_CreateRect($iX, $iY, $iX, $iY)

    Local $hDC = _WinAPI_GetWindowDC($hGUIx)
    Local $hPen = _WinAPI_CreatePen($PS_SOLID, $iPenSize, $iColor) ; border size and color
    Local $hBrush = _WinAPI_CreateBrushIndirect($BS_SOLID, $iFill) ; fill color
    Local $hObj1 = _WinAPI_SelectObject($hDC, $hBrush)
    Local $hObj2 = _WinAPI_SelectObject($hDC, $hPen)

    Local $aPreviousPos[2], $aPos[2]

    While _IsPressed("01", $hUser32dll) ; stay here till left mouse button is released

        ; get the mouse coordinates:
        ; $aPos[0] = X coord (horizontal), $aPos[1] = Y coord (vertical)
        $aPos = MouseGetPos()

        ; if mouse has mooved then redraw the ellipse accordingly
        If $aPreviousPos[0] <> $aPos[0] Or $aPreviousPos[1] <> $aPos[1] Then ; mouse has mooved

            ; take track of new mouse position
            $aPreviousPos[0] = $aPos[0]
            $aPreviousPos[1] = $aPos[1]

            ; DllStructSetData($tRECT, 1, $iX) ; initial point is fixed
            ; DllStructSetData($tRECT, 2, $iY)

            DllStructSetData($tRECT, 3, $aPos[0]) ; new mouse position
            DllStructSetData($tRECT, 4, $aPos[1])

            ; erase content of the gui (erase the previous ellipse)
            _WinAPI_RedrawWindow($hGUIx, 0, 0, BitOR($RDW_INVALIDATE, $RDW_ERASE, $RDW_UPDATENOW))

            ; Draws the new ellipse (based on new mouse position)
            _WinAPI_Ellipse($hDC, $tRECT)

        EndIf
        ;
    WEnd ; if left button is released then exit

    ; free resources
    _WinAPI_SelectObject($hDC, $hObj1)
    _WinAPI_SelectObject($hDC, $hObj2)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_ReleaseDC($hGUIx, $hDC)
    _WinAPI_RedrawWindow($hGUIx, 0, 0, BitOR($RDW_INVALIDATE, $RDW_ERASE, $RDW_UPDATENOW)) ; erase content of the gui

EndFunc   ;==>_Preview_Ellipse

 

This second listing is a botched attempt to achieve the same effect on a Label control located on a normal window (not transparent).

#include <Misc.au3> ; for _IsPressed (01 Left mouse button)
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <WinAPIGdi.au3>

Opt("MouseCoordMode", 0)

Global $hUser32dll = DllOpen("user32.dll") ; for _IsPressed

Local $aPos

; -- Create the GUI -------------------------------
Global $hGUI = GUICreate("Preview of an ellipse (click and drag to draw)", 400, 400, 100, 100) ; , -1, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))

; Label
Local $s = StringReplace(StringFormat('%22s', ""), " ", "the quick brown fox jumps over the lazy dog ")
Local $hLabel = GUICtrlGetHandle(GUICtrlCreateLabel($s, 10, 10, 250, 250))
GUICtrlSetBkColor(-1, 0xAAAA00)

; Local $iTransparent = 0x0FF0FF ; tansparent color

; This sets which color to be transparent and opacity of the whole window
; _WinAPI_SetLayeredWindowAttributes($hGUI, $iTransparent, 127) ; last param opacity intensity: 0 totally transp, 255 NOT transp

; GUISetBkColor($iTransparent, $hGUI) ; background becomes transparent

GUISetState(@SW_SHOW)

; MAIN LOOP
While 1
    $aPos = MouseGetPos()
    $aMsg = GUIGetMsg($GUI_EVENT_ARRAY) ; $GUI_EVENT_ARRAY -> returns an array containing the event and extended information
    Select
        Case $aMsg[0] = $GUI_EVENT_CLOSE
            ConsoleWrite("Bye" & @LF)
            Exit ; End()
    EndSelect

    If _IsPressed("01", $hUser32dll) Then
        ; draw the ellipse following mouse position.
        ; returns only when left mouse button is released
        _Preview_Ellipse($hLabel, $aPos[0], $aPos[1], 24)
    EndIf

WEnd


Func _Preview_Ellipse($hGUIx, $iX, $iY, $iPenSize = 9, $iColor = 0xFF0000, $iFill = 0x0FF0FF)

    ; Creates $tagRECT structure with the coordinates of the specified rectangle
    Local $tRECT = _WinAPI_CreateRect($iX, $iY, $iX, $iY)

    Local $hDC = _WinAPI_GetWindowDC($hGUIx)
    Local $hPen = _WinAPI_CreatePen($PS_SOLID, $iPenSize, $iColor) ; border size and color
    Local $hBrush = _WinAPI_CreateBrushIndirect($BS_SOLID, $iFill) ; fill color
    Local $hObj1 = _WinAPI_SelectObject($hDC, $hBrush)
    Local $hObj2 = _WinAPI_SelectObject($hDC, $hPen)

    Local $aPreviousPos[2], $aPos[2]

    While _IsPressed("01", $hUser32dll) ; stay here till left mouse button is released

        ; get the mouse coordinates:
        ; $aPos[0] = X coord (horizontal), $aPos[1] = Y coord (vertical)
        $aPos = MouseGetPos()

        ; if mouse has mooved then redraw the ellipse accordingly
        If $aPreviousPos[0] <> $aPos[0] Or $aPreviousPos[1] <> $aPos[1] Then ; mouse has mooved

            ; take track of new mouse position
            $aPreviousPos[0] = $aPos[0]
            $aPreviousPos[1] = $aPos[1]

            ; DllStructSetData($tRECT, 1, $iX) ; initial point is fixed
            ; DllStructSetData($tRECT, 2, $iY)

            DllStructSetData($tRECT, 3, $aPos[0]) ; new mouse position
            DllStructSetData($tRECT, 4, $aPos[1])

            ; erase content of the gui (erase the previous ellipse)
            _WinAPI_RedrawWindow($hGUIx, $tRECT, 0, BitOR($RDW_INVALIDATE, $RDW_ERASE, $RDW_UPDATENOW))

            ; Draws the new ellipse (based on new mouse position)
            _WinAPI_Ellipse($hDC, $tRECT)

        EndIf
        ;
    WEnd ; if left button is released then exit

    ; free resources
    _WinAPI_SelectObject($hDC, $hObj1)
    _WinAPI_SelectObject($hDC, $hObj2)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_DeleteObject($hBrush)
    _WinAPI_ReleaseDC($hGUIx, $hDC)
    _WinAPI_RedrawWindow($hGUIx, 0, 0, BitOR($RDW_INVALIDATE, $RDW_ERASE, $RDW_UPDATENOW)) ; erase content of the gui

EndFunc   ;==>_Preview_Ellipse

I'm sure to be on the wrong way (I admit my knowledge on graphics is close to zero)

How can I achieve that effect?
Thanks on advance for any help.

Edited by Chimp

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

I made a little progress, learned that the alpha component of the color structure is there precisely to allow the transparency of color....
This new listing works quite well, but there is a boring flickering while drawing the ellipse.

the flikering could be reduced if I could use the extended styles $WS_EX_COMPOSITED, $WS_EX_LAYERED in the GUICreate() function. Unfortunatelly if I use those styles, the drawing of the ellipse doesn't works anymore.

Anyone knows how to allow the use of the $WS_EX_COMPOSITED, $WS_EX_LAYERED styles or any other way to eliminate flicker?

Thank You

Click on text in the Label and drag to draw the ellipse (and to see the boring flickering).

#include <Misc.au3> ; for _IsPressed (01 Left mouse button)
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <WinAPIGdi.au3>
#include <GDIPlus.au3>
; Start GDIPlus
_GDIPlus_Startup()

Opt("MouseCoordMode", 2)

Global $hUser32dll = DllOpen("user32.dll") ; for _IsPressed

Local $aPos

; -- Create the GUI -------------------------------
Global $hGUI = GUICreate("Preview of an ellipse (click and drag to draw)", 400, 400, 100, 100);, Default,BitOR($WS_EX_COMPOSITED, $WS_EX_LAYERED))

; Label
Local $s = StringReplace(StringFormat('%22s', ""), " ", "the quick brown fox jumps over the lazy dog ")
Local $hLabel = GUICtrlGetHandle(GUICtrlCreateLabel($s, 10, 10, 250, 250))
GUICtrlSetBkColor(-1, 0xAAAA00)
GUISetState(@SW_SHOW)

; MAIN LOOP
While 1
    $aPos = MouseGetPos()
    $aMsg = GUIGetMsg($GUI_EVENT_ARRAY)
    Select
        Case $aMsg[0] = $GUI_EVENT_CLOSE
            ConsoleWrite("Bye" & @LF)
            Exit ; End
    EndSelect

    If _IsPressed("01", $hUser32dll) Then
        ; draw the ellipse following mouse position.
        ; returns only when left mouse button is released
        _Preview_Ellipse($hLabel, $aPos[0], $aPos[1], 20) ; X Y starting point, pensize
    EndIf

WEnd


Func _Preview_Ellipse($hGUIx, $iX, $iY, $iPenSize = 9, $iColor = 0xFF0000, $iFill = 0x0FF0FF)

    ; Creates $tagRECT structure with the coordinates of the specified rectangle
    Local $tRECT = _WinAPI_CreateRect($iX, $iY, $iX, $iY)
    Local $aRect[4]

    Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUIx)

    ; Create solid brush
    ; The alpha component of color 0xAAnnnnnn determines the transparency of the color
    Local $hBrush = _GDIPlus_BrushCreateSolid(0xAA00FF00)
    Local $hPen = _GDIPlus_PenCreate2($hBrush, $iPenSize)

    Local $aPreviousPos[2], $aPos[2]

    While _IsPressed("01", $hUser32dll) ; stay here till left mouse button is released

        ; get the mouse coordinates:
        ; $aPos[0] = X coord (horizontal), $aPos[1] = Y coord (vertical)
        $aPos = MouseGetPos()

        ; if mouse has mooved then redraw the ellipse accordingly
        If $aPreviousPos[0] <> $aPos[0] Or $aPreviousPos[1] <> $aPos[1] Then ; mouse has mooved

            ; take track of new mouse position
            $aPreviousPos[0] = $aPos[0]
            $aPreviousPos[1] = $aPos[1]

            ; some attempts to erase the ellipse
            ; _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_ERASE, $RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME, $RDW_ALLCHILDREN))
             _WinAPI_RedrawWindow($hGUIx, 0, 0, BitOR($RDW_INVALIDATE, $RDW_ERASE, $RDW_UPDATENOW))
            ; _WinAPI_InvalidateRect($hGUI, $tRect, True) ; Redraws just the defined rectangle by the $tRect structure
            ; _GDIPlus_GraphicsClear($hGraphics, 0x00FFFFFF)

            ; Adjust coordinates of the rectangle
            If $aPos[0] < $iX Then
                $aRect[0] = $aPos[0]
                $aRect[2] = $iX
            Else
                $aRect[0] = $iX
                $aRect[2] = $aPos[0]
            EndIf

            If $aPos[1] < $iY Then
                $aRect[1] = $aPos[1]
                $aRect[3] = $iY
            Else
                $aRect[1] = $iY
                $aRect[3] = $aPos[1]
            EndIf

            ; populate the rect structure used for deleting ellipse by the function _WinAPI_InvalidateRect above
            DllStructSetData($tRECT, 1, $aRect[0] - $iPenSize) ; initial point is fixed
            DllStructSetData($tRECT, 2, $aRect[1] - $iPenSize)
            DllStructSetData($tRECT, 3, $aRect[2] + $iPenSize) ; new mouse position
            DllStructSetData($tRECT, 4, $aRect[3] + $iPenSize)

            ; Draws the new ellipse (based on new mouse position)
            _GDIPlus_GraphicsDrawEllipse($hGraphics, $aRect[0], $aRect[1], $aRect[2] - $aRect[0], $aRect[3] - $aRect[1], $hPen)

        EndIf
        ;
    WEnd ; if left button is released then exit

    ; free resources
    _WinAPI_DeleteObject($hPen)
    _WinAPI_DeleteObject($hBrush)
    _GDIPlus_GraphicsDispose ( $hGraphics )
    _WinAPI_RedrawWindow($hGUI, 0, 0, BitOR($RDW_INVALIDATE, $RDW_ERASE, $RDW_UPDATENOW)) ; erase content of the gui

EndFunc   ;==>_Preview_Ellipse

 

Edited by Chimp

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

I'm not sure but without creating a child GUI it is not possible to get a flickerless graphic handle.

#include <Misc.au3> ; for _IsPressed (01 Left mouse button)
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include <WinAPIGdi.au3>
#include <GDIPlus.au3>
; Start GDIPlus
_GDIPlus_Startup()

Opt("MouseCoordMode", 2)

Global $hUser32dll = DllOpen("user32.dll") ; for _IsPressed

Global $aPos, $iW = 250, $iH = 250

; -- Create the GUI -------------------------------
Global $hGUI = GUICreate("Preview of an ellipse (click and drag to draw)", 400, 400, 100, 100);, Default,BitOR($WS_EX_COMPOSITED, $WS_EX_LAYERED))

; Label
Global $s = StringReplace(StringFormat('%22s', ""), " ", "the quick brown fox jumps over the lazy dog ")
Global $hLabel = GUICtrlGetHandle(GUICtrlCreateLabel($s, 10, 10, 250, 250))
GUICtrlSetBkColor(-1, 0xAAAA00)
GUISetState(@SW_SHOW)

Global $hGUI_Child = GUICreate("", $iW, $iH, 0, 0, $WS_POPUP, $WS_EX_LAYERED)
_WinAPI_SetParent($hGUI_Child, $hLabel)
GUISetState(@SW_SHOWNA, $hGUI_Child)

Global $hBrush = _GDIPlus_BrushCreateSolid(0xA0FFFFFF)
Global Const $hDC = _WinAPI_GetDC($hGUI_Child)
Global Const $hGfxDC = _WinAPI_CreateCompatibleDC($hDC)
Local Const $hBitmapGDI = _WinAPI_CreateCompatibleBitmap($hDC, $iW, $iH) ;_WinAPI_CreateDIB($iW, $iH)
Global $hObjOld = _WinAPI_SelectObject($hGfxDC, $hBitmapGDI)

Global $tSize = DllStructCreate($tagSIZE)
$tSize.x = $iW
$tSize.y = $iH
Global $tSource = DllStructCreate($tagPOINT)
Global $tBlend = DllStructCreate($tagBLENDFUNCTION)
$tBlend.Alpha = 0xFF
$tBlend.Format = 1
Global $tDest = DllStructCreate($tagPOINT), $pPoint = DllStructGetPtr($tDest)
$tDest.x = $iW
$tDest.y = $iH

Global $hGfx = _GDIPlus_GraphicsCreateFromHDC($hGfxDC)
_GDIPlus_GraphicsSetSmoothingMode($hGfx, 4)


; MAIN LOOP
While 1
    $aPos = MouseGetPos()
    $aMsg = GUIGetMsg($GUI_EVENT_ARRAY)
    Select
        Case $aMsg[0] = $GUI_EVENT_CLOSE
            _WinAPI_SelectObject($hGfxDC, $hObjOld)
            _WinAPI_ReleaseDC($hLabel, $hDC)
            _WinAPI_DeleteDC($hGfxDC)
            _WinAPI_DeleteObject($hBitmapGDI)
            _GDIPlus_GraphicsDispose($hGfx)
            _GDIPlus_BrushDispose($hBrush)
            _GDIPlus_Shutdown()
            ConsoleWrite("Bye" & @LF)
            Exit ; End
    EndSelect

    If _IsPressed("01", $hUser32dll) Then
        ; draw the ellipse following mouse position.
        ; returns only when left mouse button is released
;~         _Preview_Ellipse($hLabel, $aPos[0], $aPos[1], 20) ; X Y starting point, pensize
        _Preview_Ellipse2()
    EndIf

WEnd

Func _Preview_Ellipse2()
    While _IsPressed("01", $hUser32dll)
        _WinAPI_BitBlt($hGfxDC, 0, 0, $iW, $iH, $hGfxDC, 0, 0, $CAPTUREBLT)
        _GDIPlus_GraphicsFillEllipse($hGfx, 0, 0, MouseGetPos(0), MouseGetPos(1), $hBrush)
        _WinAPI_UpdateLayeredWindow($hGUI_Child, $hDC, Null, $tSize, $hGfxDC, $tSource, 0, $tBlend, $ULW_ALPHA)
        Sleep(20)
    WEnd
EndFunc

 

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

Hi Herr @UEZ :),  many thanks for your input.
Unfortunately if I try to run the script as is, it doesn't shows any ellipse. When I click and drag on the GUI nothing happens...
I had already tried before to use a child window and/or also to use the  $WS_EX_LAYERED style directly on the main GUI, but in both cases the drawing of the ellipse it doesn't anymore. (I'm using AutoIt 3.3.14.2 on win7 x64)
I see instead that you are sucessfully running your script on your system. What's your system?
I'm a bit confused because I don't know if I have some weird problem on my system or if the $WS_EX_LAYERED style has some restrictions of use...
I will try to look further into the matter...
Thanks again for your very welcome aid :)

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

Signore Chimp,

I tried that script on Win10 x64 version 1607. I will try it in my vm Win7 just after my meeting.

 

Tested on Win7 (vm) with enabled Aero -> not working. :o Seems to be a problem with _WinAPI_SetParent() function.

 

Try these lines instead:

...
Global $hGUI_Child = GUICreate("", $iW, $iH, 10, 10, $WS_POPUP, BitOr($WS_EX_MDICHILD, $WS_EX_LAYERED), $hGUI)
;~ _WinAPI_SetParent($hGUI_Child, $hGUI)
GUISetState(@SW_SHOWNA, $hGUI_Child)
...

 

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

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