mpower Posted March 12, 2015 Posted March 12, 2015 (edited) Hi guys, I've been trying to create a working slide-out panel GUI but I am getting confused with $WS_EX_LAYERED. Reading here: "https://www.autoitscript.com/autoit3/docs/functions/GUICreate.htm#Extended Style Table" It says " With $WS_EX_LAYERED it is possible to have a transparent picture on a background picture defined in the parent window." - Perfect that's what I need. So I use this style and manage to get my GUI to have a transparent PNG background (see attached png file for the example bg). Now, the problem I have here is that after setting the background I go on to create some controls, but they are not showing up! What gives? My code is here, what am I doing wrong? I'd really like to wrap my head around using PNG's as GUI elements (background and controls). expandcollapse popup#include-once #NoTrayIcon #AutoIt3Wrapper_Outfile=Example.exe #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_UseX64=n #include <GDIPlus.au3> #include <WindowsConstants.au3> #include <GUIConstants.au3> #include <WinAPIEx.au3> Global $bAero Global Const $hDwmApiDll = DllOpen("dwmapi.dll"), $sChkAero = DllStructCreate("int;") DllCall($hDwmApiDll, "int", "DwmIsCompositionEnabled", "ptr", DllStructGetPtr($sChkAero)) $bAero = DllStructGetData($sChkAero, 1) If Not $bAero Then ;check for Aero as transparent png GUI requires Aero MsgBox(16, 'Sorry', 'Sorry, Aero must be enabled for this application to work!') Exit EndIf $hGUI = GUICreate("", 715, 683, -1, 0, $WS_POPUP, $WS_EX_LAYERED + $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle())) ;remove application taskbar icon $hIcon = _WinAPI_GetClassLongEx($hGUI, $GCL_HICON) _WinAPI_DestroyIcon($hIcon) _WinAPI_SetClassLongEx($hGUI, $GCL_HICON, 0) _WinAPI_SetClassLongEx($hGUI, $GCL_HICONSM, 0) ;set the png file as the gui background _GDIPlus_Startup() $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\panel.png') SetBitmap($hGUI, $hImage) _GDIPlus_Shutdown() ;create some controls - WHICH DONT SHOW UP :( GUISetFont(18, 100, Default, 'Segoe UI', $hGUI, 5) GUICtrlCreateLabel('Quicksearch:', 10, 25) GUICtrlCreateInput('', 150, 20, 100, 35) GUICtrlCreateLabel('Customise', 525, 25) GUISetState(@SW_SHOW, $hGUI) While 1 $msg = GUIGetMsg(1) Switch $msg[1] Case $hGUI Switch $msg[0] Case $GUI_EVENT_CLOSE, $GUI_EVENT_SECONDARYDOWN ;let's exit on right click (or esc or alt+f4) Exit EndSwitch EndSwitch WEnd Func SetBitmap($hGUI, $hImage, $iOpacity = 255) Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend $hScrDC = _WinAPI_GetDC(0) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) $tSize = DllStructCreate($tagSIZE) $pSize = DllStructGetPtr($tSize) DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage)) DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage)) $tSource = DllStructCreate($tagPOINT) $pSource = DllStructGetPtr($tSource) $tBlend = DllStructCreate($tagBLENDFUNCTION) $pBlend = DllStructGetPtr($tBlend) DllStructSetData($tBlend, "Alpha", $iOpacity) DllStructSetData($tBlend, "Format", 1) _WinAPI_UpdateLayeredWindow($hGUI, $hGUI, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) _WinAPI_ReleaseDC(0, $hScrDC) _WinAPI_SelectObject($hMemDC, $hOld) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) EndFunc Somewhat related, the other thing I have found on the same Docs page it says "$WS_EX_LAYERED Creates a layered window. Note that this cannot be used for child windows." But the funny thing is it follows with an example that explicitly uses $WS_EX_LAYERED on a child GUI: #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Example() Func Example() Local $sFilePath = "..\GUI\logo4.gif" ; Create a GUI with various controls. Local $hGUI = GUICreate("Example", 400, 100) GUICtrlCreatePic("..\GUI\msoobe.jpg", 0, 0, 400, 100) ; Display the GUI. GUISetState(@SW_SHOW, $hGUI) Local $hChild = GUICreate("", 169, 68, 20, 20, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD), $hGUI) ; Create a picture control with a transparent image. GUICtrlCreatePic($sFilePath, 0, 0, 169, 68) ; Display the child GUI. GUISetState(@SW_SHOW) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Delete the previous GUIs and all controls. GUIDelete($hGUI) GUIDelete($hChild) EndFunc ;==>Example EDIT: oops accidentally posted the wrong code for my section (it was the docs example) - now its my code. Edited March 12, 2015 by mpower
BrewManNH Posted March 13, 2015 Posted March 13, 2015 If a picture is set as a background picture the other controls will overlap, so it is important to disable the pic control: GUICtrlSetState(-1, $GUI_DISABLE). It's in the help file for GUICtrlCreatePic If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator
mpower Posted March 13, 2015 Author Posted March 13, 2015 (edited) It's in the help file for GUICtrlCreatePic But I don't have a Pic control? The PNG image is drawn directly onto the GUI without a control as far as I can tell: Func SetBitmap($hGUI, $hImage, $iOpacity = 255) Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend $hScrDC = _WinAPI_GetDC(0) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) $tSize = DllStructCreate($tagSIZE) $pSize = DllStructGetPtr($tSize) DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage)) DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage)) $tSource = DllStructCreate($tagPOINT) $pSource = DllStructGetPtr($tSource) $tBlend = DllStructCreate($tagBLENDFUNCTION) $pBlend = DllStructGetPtr($tBlend) DllStructSetData($tBlend, "Alpha", $iOpacity) DllStructSetData($tBlend, "Format", 1) _WinAPI_UpdateLayeredWindow($hGUI, $hGUI, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) _WinAPI_ReleaseDC(0, $hScrDC) _WinAPI_SelectObject($hMemDC, $hOld) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) EndFunc Edited March 13, 2015 by mpower
BrewManNH Posted March 13, 2015 Posted March 13, 2015 Sorry, I was looking at your second example and not the first. What exactly is it that you're trying to achieve with your panel.png? If all you want is a see through GUI, you can always try using WinSetTrans to do that, if you're doing the whole GUI. BTW, that example in the help file is demonstrating how to make a GUI with transparency by using a technique that makes the GUI transparent, it works because the pixel color in the 0,0 location on the image is used as the transparency indicator. Anywhere that color is in the image will cause the GUI to be transparent in that location. The logo4.gif has dark blue in that location, so the entire background of the GUI is transparent wherever that blue color is, in this case anywhere there isn't text. If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator
mpower Posted March 13, 2015 Author Posted March 13, 2015 BrewManNH, I am trying to make a GUI which has a drop shadow by using the PNG I have made (if there is another way to do this please let me know). I am also planning on adding other PNG images to go on top of the GUI to serve as GUI elements. ------------- The example I brought up from the Docs page (https://www.autoitscript.com/autoit3/docs/functions/GUICreate.htm) was to point out the contradictory statements made in the Docs of: "$WS_EX_LAYERED Creates a layered window. Note that this cannot be used for child windows." As you can see the example from Docs page clearly is applying $WS_EX_LAYERED style to a child window: Local $hChild = GUICreate("", 169, 68, 20, 20, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD), $hGUI)
Solution binhnx Posted March 13, 2015 Solution Posted March 13, 2015 (edited) I'm not quite interesting in this topic, but I think I can provide some information. - First, about your last example: Local $hChild = GUICreate("", 169, 68, 20, 20, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_MDICHILD), $hGUI) AutoIt do some hack with those Windows style, so some statement you've read can be incorrect in some situation. From Win32 point of view, a WS_EX_LAYERED flag doesn't have any effect to a child window. So with a MDI child, its still true. But AutoIt cannot provide a true MDI implementation (yes, it is complex, so AutoIt's dev decide to provide a simulated MDI child, using top-level window but move/minimize it when the main MDI host window is moved/minimized. So any 'MDI child' in AutoIt (created by GUICreate) is not a child window, but a top level window. They can have WS_EX_LAYERED flag, as all other top-level windows. - Second, from Windows 8, WS_EX_LAYERED also support child window, so if you target a Windows 8 platform or later, you can freely use that flag with any window. - Make dropshadow is hard part. You can use WS_EX_LAYERED and set a image as your GUI shape, but all your controls in the GUI becomes useless. Easiest solution is have a normal interactive GUI window, and create a/several decorater window which is WS_EX_LAYERED and do the shadow job. When your main GUI move or minimize then move/minimize your decorater window(s) along with. Its still a lot of work. Almost programs with custom shadow use this method (MS Office 2013 as an example) Edited March 13, 2015 by binhnx 99 little bugs in the code 99 little bugs! Take one down, patch it around 117 little bugs in the code!
mpower Posted March 13, 2015 Author Posted March 13, 2015 (edited) Thanks binhnx, for that explanation regarding simulated MDI child windows, now it makes sense. I think the wording on the Docs page could be changed to remove the confusion. I have managed to get somewhere though . Whilst you can't add controls to the Parent GUI, you can add controls to the child GUI. They show fine and work as expected! Here is a working example, much better than my previous crude work. expandcollapse popup#include-once #NoTrayIcon #AutoIt3Wrapper_Outfile=Example.exe #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_UseUpx=n #AutoIt3Wrapper_UseX64=n #include <GDIPlus.au3> #include <WindowsConstants.au3> #include <GUIConstants.au3> #include <WinAPIEx.au3> Global $bAero, $hidden = False Global Const $hDwmApiDll = DllOpen("dwmapi.dll"), $sChkAero = DllStructCreate("int;") DllCall($hDwmApiDll, "int", "DwmIsCompositionEnabled", "ptr", DllStructGetPtr($sChkAero)) $bAero = DllStructGetData($sChkAero, 1) If Not $bAero Then ;check for Aero as transparent png GUI requires Aero MsgBox(16, 'Sorry', 'Sorry, Aero must be enabled for this application to work!') Exit EndIf $hGUI = GUICreate("", 715, 683, -1, 0, $WS_POPUP, $WS_EX_LAYERED + $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle())) $hIcon = _WinAPI_GetClassLongEx($hGUI, $GCL_HICON) _WinAPI_DestroyIcon($hIcon) _WinAPI_SetClassLongEx($hGUI, $GCL_HICON, 0) _WinAPI_SetClassLongEx($hGUI, $GCL_HICONSM, 0) _GDIPlus_Startup() $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\panel.png') SetBitmap($hGUI, $hImage) _GDIPlus_Shutdown() $hGUI_child = GUICreate("", 715-39, 683 - 26, 22, 3, $WS_POPUP, $WS_EX_MDICHILD + $WS_EX_TOPMOST, $hGUI) GUISetBkColor(0xFFFFFF) GUISetFont(18, 100, Default, 'Segoe UI', $hGUI_child, 5) GUICtrlCreateLabel('Example lbl:', 10, 25) GUICtrlCreateInput('', 150, 20, 100, 35) GUICtrlCreateLabel('Example lbl', 525, 25) $testbutton = GUICtrlCreateButton('A test button', 100, 250) $hGUI_child2 = GUICreate("", 112, 50, 299, 645, $WS_POPUP, $WS_EX_LAYERED + $WS_EX_MDICHILD + $WS_EX_TOPMOST, $hGUI) GUISetCursor(0, 1, $hGUI_child2) _GDIPlus_Startup() $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\roundbn.png') SetBitmap($hGUI_child2, $hImage) _GDIPlus_Shutdown() GUISetState(@SW_SHOW, $hGUI) GUISetState(@SW_SHOW, $hGUI_child) GUISetState(@SW_SHOW, $hGUI_child2) While 1 $msg = GUIGetMsg(1) Switch $msg[1] Case $hGUI_child Switch $msg[0] Case $GUI_EVENT_CLOSE, $GUI_EVENT_SECONDARYDOWN ;let's exit on right click (or esc or alt+f4) Exit Case $testbutton MsgBox(0,'Button','You clicked a button!', 0, $hGUI_child) EndSwitch Case $hGUI_child2 Switch $msg[0] Case $GUI_EVENT_PRIMARYDOWN If Not $hidden Then For $i = -1 to -663 Step - 1 WinMove($hGUI, "", Default, $i) Next $hidden = True Else For $i = -664 to -4 Step 1 WinMove($hGUI, "", Default, $i) Next $hidden = False EndIf EndSwitch EndSwitch WEnd Func SetBitmap($hGUI, $hImage, $iOpacity = 255) Local $hScrDC, $hMemDC, $hBitmap, $hOld, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend $hScrDC = _WinAPI_GetDC(0) $hMemDC = _WinAPI_CreateCompatibleDC($hScrDC) $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage) $hOld = _WinAPI_SelectObject($hMemDC, $hBitmap) $tSize = DllStructCreate($tagSIZE) $pSize = DllStructGetPtr($tSize) DllStructSetData($tSize, "X", _GDIPlus_ImageGetWidth($hImage)) DllStructSetData($tSize, "Y", _GDIPlus_ImageGetHeight($hImage)) $tSource = DllStructCreate($tagPOINT) $pSource = DllStructGetPtr($tSource) $tBlend = DllStructCreate($tagBLENDFUNCTION) $pBlend = DllStructGetPtr($tBlend) DllStructSetData($tBlend, "Alpha", $iOpacity) DllStructSetData($tBlend, "Format", 1) _WinAPI_UpdateLayeredWindow($hGUI, $hGUI, 0, $pSize, $hMemDC, $pSource, 0, $pBlend, $ULW_ALPHA) _WinAPI_ReleaseDC(0, $hScrDC) _WinAPI_SelectObject($hMemDC, $hOld) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteDC($hMemDC) EndFunc Edited March 13, 2015 by mpower
qwert Posted March 13, 2015 Posted March 13, 2015 AutoIt cannot provide a true MDI implementation (yes, it is complex, so AutoIt's dev decide to provide a simulated MDI child, using top-level window but move/minimize it when the main MDI host window is moved/minimized. I'd also like to thank binhnx for his summary of the key aspects of layered windows. I've had instances of GUI elements becoming disassociated with the main gui ... especially when the entire screen is rotated from horizontal to vertical on one of the Win 8 tablets. I need to look at the whole issue again in light of this clearer explanation. Thanks, binhnx!
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now