Jump to content

transparent movable windows with drop shadow


Go to solution Solved by Nine,

Recommended Posts

Posted

Hello!

i want to create a transparent main windows with full visible control on it.

i decide to use png for covering main windows  to create drop shadow .

i search community for this and find a lot of outdated topic that dont work anymore.

any solution?

  • Solution
Posted (edited)

Here modern coding (removed useless code) :

#include <WinAPISysWin.au3>
#include <WinAPIConstants.au3>
#include <GDIPlus.au3>
#include <GuiComboBox.au3>
#include <File.au3>
#include <WindowsConstants.au3>
#include <GuiConstants.au3>
#include <ButtonConstants.au3>

Opt("MustDeclareVars", True)

Global Const $AC_SRC_ALPHA = 1

Example()

Func Example()
  ; Load PNG file as GDI bitmap
  _GDIPlus_Startup()
  Local $sPngSrc = @ScriptDir & "\LaunchySkin.png"
  Local $hImage = _GDIPlus_ImageLoadFromFile($sPngSrc)

  ; Extract image width and height from PNG
  Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
  Local $iHeight = _GDIPlus_ImageGetHeight($hImage)

  ; Create layered window
  Local $hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
  Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
  _WinAPI_UpdateLayeredWindowEx($hGUI, -1, -1, $hBitmap)

  ; Register notification messages
  GUIRegisterMsg($WM_NCHITTEST, WM_NCHITTEST)
  GUISetState()
  WinSetOnTop($hGUI, "", $WINDOWS_ONTOP)

  ; As per help file :
  ; When using $WS_EX_MDICHILD the position is relative to client area of the parent window.
  ; With $WS_EX_LAYERED it is possible to have a transparent picture on a background picture defined in the parent window.

  ; 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.
  ; If several pictures are created the last picture defines the transparent color.

  GUICreate("", $iWidth, $iHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD), $hGUI)

  GUICtrlCreatePic(@ScriptDir & "\grey.gif", 0, 0, $iWidth, $iHeight) ; makes the whole child GUI transparent
  GUICtrlSetState(-1, $GUI_DISABLE)

  GUICtrlCreateLabel("Type the name of a file on" & @CR & "your desktop and press Enter", 50, 30, 140, 60)
  GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
  GUICtrlSetColor(-1, 0xFFFFFF)

  ; combo box listing all items on desktop
  Local $idCombo = GUICtrlCreateCombo("", 210, 30, 250, -1, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL))
  GUICtrlSetFont($idCombo, 10)

  ; set default button for Enter key activation - renders outside GUI window
  Local $idButton = GUICtrlCreateButton("", 0, 0, 0, 0, $BS_DEFPUSHBUTTON)

  GUISetState()

  ; get list of files on desktop, show in combobox
  Local $aFileList = _FileListToArray(@DesktopDir), $sRun
  _ArraySort($aFileList, 0, 1)
  GUICtrlSetData($idCombo, _ArrayToString($aFileList, "|", 1))

  While True
    Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE
        ExitLoop
      Case $idButton
        $sRun = GUICtrlRead($idCombo)
        ExitLoop
    EndSwitch
  WEnd

  If $sRun And FileExists(@DesktopDir & "\" & $sRun) Then
    Beep(2000, 50)
    ShellExecute($sRun, "", @DesktopDir)
  EndIf

  _WinAPI_DeleteObject($hBitmap)
  _GDIPlus_ImageDispose($hImage)
  _GDIPlus_Shutdown()
EndFunc   ;==>Example

Func WM_NCHITTEST($hWnd, $iMsg, $iwParam, $ilParam)
  Return $HTCAPTION
EndFunc   ;==>WM_NCHITTEST

 

Edited by Nine
Posted (edited)

Yes, it is working.   But we should use :

Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
_WinAPI_UpdateLayeredWindowEx($hGUI, -1, -1, $hBitmap)

to ensure no memory leak.

 

Also, I just noticed a small bug. 

_WinAPI_DeleteObject($hImage)

is incorrect and should be replaced by :

_GDIPlus_ImageDispose($hImage)

and then add :

_WinAPI_DeleteObject($hBitmap)

 

EDIT : modified code above accordingly.

Edited by Nine
Posted (edited)
6 hours ago, Nine said:

to ensure no memory leak.

That's right, thanks for the info :)

In fact, I remembered a discussion from 2021 with @UEZ concerning the bypass of SetBitmap() and its replacement with _WinAPI_UpdateLayeredWindowEx() . You can find the original discussion here, also you'll need Torus.png if you intend to run UEZ's interesting script.

We really owe a lot to Yashied and "his famous WinAPIEx UDF" , as quoted by UEZ in his answer.

Edit: now that SetBitmap() has gone forever, we still may get a shorter code with same functionalities :

; Local $hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, $WS_POPUP, $WS_EX_LAYERED)

Local $hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, $WS_POPUP, BitOr($WS_EX_LAYERED, $WS_EX_CONTROLPARENT, $WS_EX_TOPMOST))

; Register notification messages
; GUIRegisterMsg($WM_NCHITTEST, WM_NCHITTEST)

; WinSetOnTop($hGUI, "", $WINDOWS_ONTOP)

; Func WM_NCHITTEST($hWnd, $iMsg, $iwParam, $ilParam)
;  Return $HTCAPTION
; EndFunc   ;==>WM_NCHITTEST

 

Edited by pixelsearch
suggesting a shorter code
Posted (edited)

@Nine thank for your support.

Now i want to put multiple png icon on top of this windows, so i have to use GUICreate for each of them?
is this ok?

also i want to know why putting  grey.gif ?

Edited by rot3r
Posted
13 minutes ago, rot3r said:

Now i want to put multiple png icon on top of this windows, so i have to use GUICreate for each of them?

Not exactly sure what you try to do.  Show the snippet of the code that is not working so we can work from it.

14 minutes ago, rot3r said:

also i want to know why putting  grey.gif ?

Like I put in the script (from help file), to get a child GUI transparent, you need to use an image where the first pixel serves as a transparent color.  Removing it would hide the main GUI.

Posted

i think i can explain better with picture

Untitled-1.jpg.9464b87479c54c76ea9ebe57400456fd.jpg

as you can see the main windows is transparent PNG image and there are some box and icon that they are png too.

how can i put this png over main windows?

create new gui for every png files?

sorry if its so amateur...

Posted

Since all the images are PNG, I would create a $WS_POPUP ,  BitOr($WS_EX_LAYERED, $WS_EX_MDICHILD) GUI window for each, and use _WinAPI_UpdateLayeredWindowEx to set the image inside the window (just like main GUI).

Posted
18 minutes ago, Nine said:

Since all the images are PNG, I would create a $WS_POPUP ,  BitOr($WS_EX_LAYERED, $WS_EX_MDICHILD) GUI window for each, and use _WinAPI_UpdateLayeredWindowEx to set the image inside the window (just like main GUI).

can cause performance draw back to create multiple gui windows for each?

or do you recommend any thing better to achieve this?

Posted
3 hours ago, rot3r said:

also i want to know why putting  grey.gif ?

Nine knows better than us, but this seems to work for me, without a pic in the 2nd GUI, maybe I missed something :

#include <ButtonConstants.au3>
#include <File.au3>
#include <GDIPlus.au3>
#include <GuiComboBox.au3>
#include <GuiConstantsEx.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", True)

Example()

Func Example()
    ; Load PNG file as GDI bitmap
    _GDIPlus_Startup()
    Local $sPngSrc = @ScriptDir & "\LaunchySkin.png"
    Local $hImage = _GDIPlus_ImageLoadFromFile($sPngSrc)

    ; Extract image width and height from PNG
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)

    ; Create layered window
    Local $hGUI = GUICreate("", $iWidth, $iHeight, -1, -1, $WS_POPUP, BitOr($WS_EX_LAYERED, $WS_EX_CONTROLPARENT, $WS_EX_TOPMOST))
    Local $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    _WinAPI_UpdateLayeredWindowEx($hGUI, -1, -1, $hBitmap)

    GUISetState()

    Local $hGUI2 = GUICreate("", $iWidth, $iHeight, 0, 0, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD), $hGUI)
    GUISetBkColor( 0xABCDEF, $hGUI2) ; transparent
    _WinAPI_SetLayeredWindowAttributes($hGUI2, 0xABCDEF)

    GUICtrlCreateLabel("Type the name of a file on" & @CR & "your desktop and press Enter", 50, 30, 140, 60)
    GUICtrlSetColor(-1, 0xFFFFFF)

    ; combo box listing all items on desktop
    Local $idCombo = GUICtrlCreateCombo("", 210, 30, 250, -1, BitOR($CBS_DROPDOWNLIST, $CBS_AUTOHSCROLL))
    GUICtrlSetFont($idCombo, 10)

    ; set default button for Enter key activation - renders outside GUI window
    Local $idButton = GUICtrlCreateButton("", 0, 0, 0, 0, $BS_DEFPUSHBUTTON)

    GUISetState()

    ; get list of files on desktop, show in combobox
    Local $aFileList = _FileListToArray(@DesktopDir), $sRun
    _ArraySort($aFileList, 0, 1)
    GUICtrlSetData($idCombo, _ArrayToString($aFileList, "|", 1))

    While True
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $idButton
            $sRun = GUICtrlRead($idCombo)
            ExitLoop
    EndSwitch
    WEnd

    If $sRun And FileExists(@DesktopDir & "\" & $sRun) Then
        Beep(2000, 50)
        ShellExecute($sRun, "", @DesktopDir)
    EndIf

    _WinAPI_DeleteObject($hBitmap)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc   ;==>Example

 

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
  • Recently Browsing   0 members

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