Jump to content

Why GUICtrlCreatePic saves this script ?


Recommended Posts

Hi everybody :)
The script below creates a transparent GUI, resizable, with a pseudo red border and a blue docked square in its middle (a label to make the GUI draggable)

But this GUI is transparent only because of this useless line :

$idPic = GUICtrlCreatePic("", 0, 0, 1, 1)

As soon as you comment out this line, the GUI isn't transparent anymore. Please note that the GUI is totally transparent no matter the value present in WinSetTrans... as soon as GUICtrlCreatePic is present. Anybody could explain this strange behavior ?
Thanks

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

Global $iWidth = 300, $iHeight = 200
$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST)
GUISetBkColor($GUI_BKCOLOR_TRANSPARENT)

WinSetTrans($hGUI, "", 255) ; or any value in this special context (?)
$idPic = GUICtrlCreatePic("", 0, 0, 1, 1) ; strange GUICtrlCreatePic allows the transparency (?)

$idLabel1 = GUICtrlCreateLabel("", 0, 0, $iWidth, 1) ; top horizontal red line
GUICtrlSetBkColor(-1, $COLOR_RED)
GUICtrlSetResizing(-1, $GUI_DOCKMENUBAR)

$idLabel2 = GUICtrlCreateLabel("", 0, $iHeight - 1, $iWidth, 1) ; bottom horizontal red line
GUICtrlSetBkColor(-1, $COLOR_RED)
GUICtrlSetResizing(-1, $GUI_DOCKSTATEBAR)

$idLabel3 = GUICtrlCreateLabel("", 0, 1, 1, $iHeight - 1) ; left vertical red line
GUICtrlSetBkColor(-1, $COLOR_RED)
GUICtrlSetResizing(-1, $GUI_DOCKWIDTH + $GUI_DOCKLEFT)

$idLabel4 = GUICtrlCreateLabel("", $iWidth - 1, 1, 1, $iHeight - 1) ; right vertical red line
GUICtrlSetBkColor(-1, $COLOR_RED)
GUICtrlSetResizing(-1, $GUI_DOCKWIDTH + $GUI_DOCKRIGHT)

$idLabel5 = GUICtrlCreateLabel("drag", ($iWidth / 2) - 20, ($iHeight / 2) - 20, 40, 40, _ ; centered blue square
    BitOr($SS_CENTERIMAGE, $SS_CENTER), $GUI_WS_EX_PARENTDRAG)
GUICtrlSetBkColor(-1, $COLOR_BLUE)
GUICtrlSetResizing(-1, $GUI_DOCKSIZE + $GUI_DOCKVCENTER + $GUI_DOCKHCENTER)

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            GUIDelete($hGUI)
            Exit
    EndSwitch
Wend

1759746815_strangepiccontrol.png.6c4d1cb198beb3049433794a3854924f.png

Escape will end the script (while the GUI is active)

Link to comment
Share on other sites

Interesting indeed.  Here my deductions.  I think it relates to those 2 assertions :

Quote

To have a transparent picture create the GUI with the WS_EX_LAYERED extended style. The left-top pixel will be used as the transparency color.

Quote

The background is always set to transparent. GUICtrlSetBkColor() has no effect on pic control.

WinSetTrans($hGUI, "", xxx)  seems to perform the same action as declaring the window WS_EX_LAYERED.  So you can consider that your GUI has in fact that extended style, so the first assertion is applied.

Since the background of pic is always transparent and you did not assign a file to the control, the whole GUI takes that property.

To better show what I am trying to explain, lets take a few examples :

$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST+$WS_EX_LAYERED)
GUISetBkColor($GUI_BKCOLOR_TRANSPARENT)
;WinSetTrans($hGUI, "", 255) ; or any value in this special context (?)
$idPic = GUICtrlCreatePic("", 0, 0, 1, 1) ; strange GUICtrlCreatePic allows the transparency (?)

Works as explained above.

$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST+$WS_EX_LAYERED)
GUISetBkColor($GUI_BKCOLOR_TRANSPARENT)
;WinSetTrans($hGUI, "", 255) ; or any value in this special context (?)
$idPic = GUICtrlCreatePic("Torus.jpg", 0, 0, 100, 100) ; strange GUICtrlCreatePic allows the transparency (?)

Works only under the 100x100 pixels of the picture.  Second assertion is proven right.

$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST+$WS_EX_LAYERED)
GUISetBkColor($GUI_BKCOLOR_TRANSPARENT)
;WinSetTrans($hGUI, "", 255) ; or any value in this special context (?)
$idPic = GUICtrlCreatePic("Torus.jpg", 0, 0, 1, 1) ; strange GUICtrlCreatePic allows the transparency (?)
GUICtrlSetState (-1, $GUI_DISABLE)

Does not work because of the left-top pixel (first assertion) cannot be used as the transparency color since the all the colors of the picture are all merged into a single pixel.

So may not be that surprising after all.  

Link to comment
Share on other sites

@Nine: thanks for your tests & explanations.

It would have been great to reach exactly the same result as the pic above, without using GUICtrlCreatePic() at all. But well... if it's not possible, we'll stick to an empty GUICtrlCreatePic() which solved everything. After all, it's only 1 line of script :)

Here is an example of how the script could be used, to select a part of a pic, while selection can't go beyond the image borders (thanks to WM_WINDOWPOSCHANGING). Then a right click on the pic allows to save the selected part (under a new name)

The simulated red border (4 labels) is commented out. If needed, please uncomment the according lines of code :

#include <ColorConstantS.au3>
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Global $hGUI1 = 0, $hGUI2 = 0, $hImage = 0, $hBitmap = 0, $hClone = 0
$sFileName = StringTrimRight(@ScriptFullPath, 4) & ".jpg" ; .au3/.a3x/.exe => .jpg
If Not FileExists($sFileName) Then _Exit("File not found", $sFileName, @error, @extended)

_GDIPlus_Startup()

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

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

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

;========================
; $hGUI1 = GUICreate("", $iX, $iY, -1, -1, $WS_POPUP, $WS_EX_TOPMOST)
; -1, -1 "to center the window" isn't enough in case the image (i.e the GUI in this case) fills the whole screen (or nearly)

$hGUI1 = GUICreate("", $iX, $iY, (@DesktopWidth - $iX) / 2, (@DesktopHeight - $iY) / 2, $WS_POPUP, $WS_EX_TOPMOST)
$idPic = GUICtrlCreatePic("", 0, 0, $iX, $iY)
$hPrevImage = GUICtrlSendMsg($idPic, 0x0172, 0, $hBitmap) ; STM_SETIMAGE = 0x0172, $IMAGE_BITMAP = 0
_WinAPI_DeleteObject($hPrevImage); Delete prev image if any (help file)

$aWinPos = WinGetPos($hGUI1)
$iLeft1 = $aWinPos[0]
$iTop1 = $aWinPos[1]
$iWidth1 = $aWinPos[2]
$iHeight1 = $aWinPos[3]
$iRight1 = $iLeft1 + $iWidth1
$iBottom1 = $iTop1 + $iHeight1

GUISetState(@SW_SHOW, $hGUI1)
GUISetState(@SW_DISABLE, $hGUI1)

;========================
Global $iWidth = $iX / 2, $iHeight = $iY / 2
$hGUI2 = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST)
GUISetBkColor($GUI_BKCOLOR_TRANSPARENT)

WinSetTrans($hGUI2, "", 255) ; or any value in this special context (?)
$idPic = GUICtrlCreatePic("", 0, 0, 1, 1) ; strange GUICtrlCreatePic allows the transparency (?)
GUICtrlSetState (-1, $GUI_DISABLE) ; thanks Nine

;~ $idLabel1 = GUICtrlCreateLabel("", 0, 0, $iWidth, 1) ; top horizontal red line
;~ GUICtrlSetBkColor(-1, $COLOR_RED)
;~ GUICtrlSetResizing(-1, $GUI_DOCKMENUBAR)

;~ $idLabel2 = GUICtrlCreateLabel("", 0, $iHeight - 1, $iWidth, 1) ; bottom horizontal red line
;~ GUICtrlSetBkColor(-1, $COLOR_RED)
;~ GUICtrlSetResizing(-1, $GUI_DOCKSTATEBAR)

;~ $idLabel3 = GUICtrlCreateLabel("", 0, 1, 1, $iHeight - 1) ; left vertical red line
;~ GUICtrlSetBkColor(-1, $COLOR_RED)
;~ GUICtrlSetResizing(-1, $GUI_DOCKWIDTH + $GUI_DOCKLEFT)

;~ $idLabel4 = GUICtrlCreateLabel("", $iWidth - 1, 1, 1, $iHeight - 1) ; right vertical red line
;~ GUICtrlSetBkColor(-1, $COLOR_RED)
;~ GUICtrlSetResizing(-1, $GUI_DOCKWIDTH + $GUI_DOCKRIGHT)

$idLabel5 = GUICtrlCreateLabel("drag", ($iWidth / 2) - 20, ($iHeight / 2) - 20, 40, 40, _ ; centered blue square
    BitOr($SS_CENTERIMAGE, $SS_CENTER), $GUI_WS_EX_PARENTDRAG)
GUICtrlSetBkColor(-1, $COLOR_BLUE)
GUICtrlSetResizing(-1, $GUI_DOCKSIZE + $GUI_DOCKVCENTER + $GUI_DOCKHCENTER)

GUISetState(@SW_SHOW, $hGUI2)
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")

;========================
$aMsg = 0 ; 2 Gui's

While 1
    $aMsg = GUIGetMsg($GUI_EVENT_ARRAY)

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

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

                Case $GUI_EVENT_SECONDARYDOWN ; right click => Save resized image ?
                    Local $iSave_Selection = MsgBox(BitOr($MB_TOPMOST, $MB_OKCANCEL, $MB_DEFBUTTON2), "Right click", _
                        "           Save selection ?")
                    If $iSave_Selection = $IDOK Then
                        $aWinPos2 = WinGetPos($hGUI2)
                        $hClone = _GDIPlus_BitmapCloneArea($hImage, $aWinPos2[0] - $iLeft1, $aWinPos2[1] - $iTop1, _
                            $aWinPos2[2], $aWinPos2[3])
                        If @error Then _Exit("_GDIPlus_BitmapCloneArea", $sFileName, @error, @extended)

                        $sFileName_Clone = StringTrimRight(@ScriptFullPath, 4) & "_area.jpg"
                        _GDIPlus_ImageSaveToFile($hClone, $sFileName_Clone)
                        If @error Then _Exit("_GDIPlus_ImageSaveToFile", $sFileName_Clone, @error, @extended)

                        MsgBox($MB_TOPMOST, "", "Selection saved", 2) ; timeout 2s
                        _Quit()
                    EndIf
            EndSwitch
    EndSwitch
WEnd

;========================
Func WM_WINDOWPOSCHANGING($hWnd, $Msg, $wParam, $lParam)

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

        If $iLeft2 < $iLeft1 Then DllStructSetData($stWinPos, 3, $iLeft1)
        If $iTop2 < $iTop1 Then DllStructSetData($stWinPos, 4, $iTop1)
        If $iWidth2 > $iWidth1 Then DllStructSetData($stWinPos, 5, $iWidth1)
        If $iHeight2 > $iHeight1 Then DllStructSetData($stWinPos, 6, $iHeight1)

        If $iRight2 > $iRight1 Then
            If $iWidth2 <= $iWidth1 Then
                DllStructSetData($stWinPos, 3, $iRight1 - $iWidth2)
            Else
                DllStructSetData($stWinPos, 3, $iLeft1)
                DllStructSetData($stWinPos, 5, $iWidth1)
            EndIf
        EndIf

        If $iBottom2 > $iBottom1 Then
            If $iHeight2 <= $iHeight1 Then
                DllStructSetData($stWinPos, 4, $iBottom1 - $iHeight2)
            Else
                DllStructSetData($stWinPos, 4, $iTop1)
                DllStructSetData($stWinPos, 6, $iHeight1)
            EndIf
        EndIf
    EndIf

    ; Return $GUI_RUNDEFMSG (?)

EndFunc   ;==>WM_WINDOWPOSCHANGING

;====================================================
Func _Exit($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)
    _Quit()

EndFunc ; _Exit()

; ====================================================
Func _Quit()

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

EndFunc ; _Quit()

764844717_3beatles.jpg.532c09b815b979e0611f660786bc42fe.jpg

I'm joining below the Beatles pic that was used, in case one wants to try the script. Just rename the pic accordingly to the script name (for example beatles.au3 <=> beatles.jpg)

https://www.autoitscript.com/forum/applications/core/interface/file/attachment.php?id=65421

 

Link to comment
Share on other sites

10 minutes ago, pixelsearch said:

It would have been great to reach exactly the same result as the pic above, without using GUICtrlCreatePic() at all

Possible this way :

$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST+$WS_EX_LAYERED)
GUISetBkColor(0xFFFF00)
_WinAPI_SetLayeredWindowAttributes ($hGUI, 0xFFFF00)

 

Link to comment
Share on other sites

Nine, 

I was interested in this source code,

When I change the source code you suggested and enter it, 

I get this error message. error: _WinAPI_SetLayeredWindowAttributes(): undefined function. 

What can I declare to get rid of this message?

Link to comment
Share on other sites

37 minutes ago, Nine said:

You need to add an #include file.  Look help file for it.

#include <WinAPISysWin.au3> ( or #include <WinAPI.au3> for older versions of AutoIt)

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Link to comment
Share on other sites

;$hGUI2 = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST)
;GUISetBkColor($GUI_BKCOLOR_TRANSPARENT)

$hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, BitOr($WS_POPUP, $WS_SIZEBOX), $WS_EX_TOPMOST+$WS_EX_LAYERED)
GUISetBkColor(0xFFFF00)
_WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFF00)

The commented part in the whole source code above was changed as above. 

If changed, the capture part will not be transparent and the save routine will not work. 

If you switch to the original commented source code, it will not be transparent but the save routine will work. 

I'm not sure what's the 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...