How to create/set a gui without background?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

How to create/set a gui without background?

Post by N_athan » 18 Jan 2022, 03:33

Im trying to create a GUI with rounded borders, however im struggling in find a way to remove or set the background transparent.

What i already tried:

Code: Select all

Gui, Color, 797979
WinSet, TransColor, 797979
WinSet, TransColor caused a lot of "issues" because some controls and pictures has transparency, and while resizing the GUI it flash/flicker the entire time.


It also cause the picture in the background to lose quality in the borders.

Code: Select all

Gui, +HwndHGUI -Caption
Gui, Color, 0060ff
Gui, Add, Picture, x0 y10, pic.png
Gui, Show

Return 

F2::
WinSet, TransColor, 0060ff, ahk_id %HGUI%
Return


Example:
The background picture, before:
pic.png
pic.png (7.21 KiB) Viewed 2587 times
After TransColor:
Code_2022-01-18_05-52-05.png
Code_2022-01-18_05-52-05.png (10.79 KiB) Viewed 2587 times

I dont know how/if is possible to load controls in Layered window, when i tried the controls dont became visible, only the picture.

Would like to ask what other options i could try?
C++ / editing the ahk src, also helps!

User avatar
lmstearn
Posts: 688
Joined: 11 Aug 2016, 02:32
Contact:

Re: How to create/set a gui without background?

Post by lmstearn » 18 Jan 2022, 04:14

Hi,
Tried BackgroundTrans?
Failing that, best way is to process it in WM_PAINT with something like:

Code: Select all

; for custom see  https://docs.microsoft.com/en-us/windows/win32/gdi/drawing-a-custom-window-background
		DllCall("gdi32\ExcludeClipRect", "Ptr", hDC, "Int", X, "Int", Y, "Int", W, "Int", H)

		;SelectClipRgn not required
		; one pixel region
		hRgn := []
		hRgn := DllCall("gdi32\CreateRectRgn", "Int", 0, "Int", 0, "Int", 1, "Int", 1, "Ptr")
		; Updates hRgn to define the clipping region in hDC
		DllCall("gdi32\GetClipRgn", "Ptr", hDC, "Ptr", hRgn)
		hBrush := DllCall("user32\GetSysColorBrush", "Int", 15, "Ptr") ;COLOR_BTNFACE := 15
		DllCall("gdi32\FillRgn", "Ptr", hDC, "Ptr", hRgn, "Ptr", hBrush)
		This.deleteObject(hRgn)
Might be best to use a GDI(+) library for it- here's a nice little one. :)
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How to create/set a gui without background?

Post by just me » 18 Jan 2022, 07:12

A simple one, but not smooth:

Code: Select all

#NoEnv
SetBatchLines, -1

Gui, -Caption +hwndHGUI +LastFound
Gui, Color, 0060FF
Gui, Font, s24 cWHite
Gui, Margin, 0, 0
Gui, Add, Text, w400 h200 Center +0x0200, Hello world!
Gui, Show, Hide
WinGetPos, X, Y, W, H
R := Min(W, H) // 4
WinSet, Region, 0-0 W%W% H%H% R%R%-%R%
Gui, Show
OnMessage(0x0201, "WM_LBUTTONDOWN")
Return

WM_LBUTTONDOWN() {
   PostMessage, 0x00A1, 2, 0
}

GuiEscape:
ExitApp

N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

Re: How to create/set a gui without background?

Post by N_athan » 18 Jan 2022, 12:59

@just me @lmstearn
I tried to subclass the Gui following one of justme scripts (imagebutton), and erase her background but i'm a bit confused about the process.

What i tried:
Set a callback in the Gui HWnd to read her msgs.

Code: Select all

SCCB               := RegisterCallback("GDI.SubClassCallback")
DllCall("Comctl32.dll\SetWindowSubclass", "Ptr", This.hWnd, "Ptr", SCCB, "Ptr", This.hWnd, "Ptr", &This)


Then when it send the window message ERASEBKGND, i created a blank bitmap and saved it into a dc.

Code: Select all

   
; Create the background pbitmap.
DllCall("Gdiplus.dll\GdipCreateBitmapFromScan0", "Int", This.Width, "Int", This.Height, "Int", 0, "UInt", 0x26200A, "Ptr", 0, "PtrP", pBitmap)
HBITMAP := Gdip_CreateHBITMAPFromBitmap(pBitmap)            
DC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr",, "UPtr")
DllCall("Gdi32.dll\SelectObject", "Ptr", DC, "Ptr", HBITMAP)
This.DC := DC


And when it sends wm paint, i painted this new dc into the gui dc:

Code: Select all

VarSetCapacity(PAINTSTRUCT, A_PtrSize + (4 * 7) + 32 + (A_PtrSize - 4), 0)
guiDC := DllCall("USer32.dll\BeginPaint", "Ptr", This.hWnd, "Ptr", &PAINTSTRUCT, "UPtr")
DllCall("Gdi32.dll\SetBkMode", "Ptr", guiDC, "Int", 1) ; TRANSPARENT          
    
DC := This.DC

;DllCall("Gdi32.dll\BitBlt", "Ptr", guiDC, "Int", 0, "Int", 0, "Int", This.Width, "Int", This.Height, "Ptr", DC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
DllCall("Gdi32.dll\GdiAlphaBlend", "Ptr", guiDC, "Int", 0, "Int", T, "Int", This.Width, "Int", This.Height , "Ptr", DC, "Int", 0, "Int", 0, "Int", This.Width, "Int", This.Height , "UInt", 0x01FF0000) ;(BkTrans << 16))

This is the result i got:
image.png
image.png (8.55 KiB) Viewed 2508 times
The blue background got removed and the bitmap got drawed on it, but...
I dont understand, the bitmap used in the dc is blank/empty, why its white?

obs: pic.png, is at my firs post.


Code: Select all

pToken := Gdip_Startup()
OnMessage(0x0201, "WM_LBUTTONDOWN")



Gui, +HwndHGUI +Resize -Caption
Gui, Color, 0060ff
Gui, Add, Picture, x0 y10 +BackgroundTrans, pic.png
Gui, Show,, Test

WinGetPos,,, W, H, ahk_id %HGUI%

Object        := {}
Object.Hwnd   := HGUI
Object.Width  := W
Object.Height := H
x := New GDI(Object)
Return



F2::
WinSet, TransColor, 0060ff, ahk_id %HGUI%
Return

Esc::ExitApp



Class GDI {

   ; Constructor
   __New(Options) {
      This.HWnd      := Options.hWnd
      This.Width     := Options.Width
      This.Height    := Options.Height  
      This.HasBackground := False
      SCCB               := RegisterCallback("GDI.SubClassCallback")
      DllCall("Comctl32.dll\SetWindowSubclass", "Ptr", This.hWnd, "Ptr", SCCB, "Ptr", This.hWnd, "Ptr", &This)
      This.SCCB          := SCCB
   }



   ; Subclass callback function
   SubClassCallback(uMsg, wParam, lParam, IdSubclass, RefData) {
      Critical 10000
      hWnd := This ; first parameter 'hWnd' is passed as 'This'
      Return Object(RefData).SubClassProc(hWnd, uMsg, wParam, lParam)
   }



   ; Subclassproc
   SubClassProc(hWnd, uMsg, wParam, lParam) {

      Static WM := {DESTROY: 0x0002, DRAWITEM: 0x002B, LBUTTONDBLCLK: 0x0203, ERASEBKGND: 0x0014, HSCROLL: 0x0114, KEYDOWN     : 0x0100, KILLFOCUS: 0x0008, LBUTTONDOWN: 0x0201, LBUTTONUP: 0x0202, MOUSEWHEEL: 0x020A, PAINT       : 0x000F, SETFOCUS: 0x0007, SETREDRAW: 0x000B, VSCROLL: 0x0115}
      Static SRCCOPY := 0x00CC0020




      ; WM_PAINT message
      If (uMsg = WM.PAINT) {
         
         ; Get the GUI DC
         VarSetCapacity(PAINTSTRUCT, A_PtrSize + (4 * 7) + 32 + (A_PtrSize - 4), 0)
         guiDC := DllCall("USer32.dll\BeginPaint", "Ptr", This.hWnd, "Ptr", &PAINTSTRUCT, "UPtr")
         DllCall("Gdi32.dll\SetBkMode", "Ptr", guiDC, "Int", 1) ; TRANSPARENT          
         
         

         DC := This.DC

         ;DllCall("Gdi32.dll\BitBlt", "Ptr", guiDC, "Int", 0, "Int", 0, "Int", This.Width, "Int", This.Height, "Ptr", DC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
         DllCall("Gdi32.dll\GdiAlphaBlend", "Ptr", guiDC, "Int", 0, "Int", T, "Int", This.Width, "Int", This.Height , "Ptr", DC, "Int", 0, "Int", 0, "Int", This.Width, "Int", This.Height , "UInt", 0x01FF0000) ;(BkTrans << 16))
            


         ; Free resources
         DllCall("User32.dll\EndPaint", "Ptr", &PAINTSTRUCT)
         DllCall("Gdi32.dll\DeleteDC", "Ptr", LBDC)
         PAINTSTRUCT := ""

         Return 0

      }



      ; WM_ERASEBKGND message
      If (uMsg = WM.ERASEBKGND) {
         
         If (!This.HasBackground) { 
                       
               
            ; Create the background pbitmap.
            DllCall("Gdiplus.dll\GdipCreateBitmapFromScan0", "Int", This.Width, "Int", This.Height, "Int", 0, "UInt", 0x26200A, "Ptr", 0, "PtrP", pBitmap)
            ;pBitmap := CreateBitmap(0xFFff0000, This.Width, This.Height)



            HBITMAP := Gdip_CreateHBITMAPFromBitmap(pBitmap)            
            FileAppend, HBITMAP: %HBITMAP%`n,*

            DC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr",, "UPtr")
            DllCall("Gdi32.dll\SelectObject", "Ptr", DC, "Ptr", HBITMAP)
                  
            This.DC := DC

            

            ; Dispose the objects.
            Gdip_DisposeImage(pBitmap)
            DeleteObject(HBITMAP)

            ;This.HasBackground := True



         }         

         Return True

      }



      Return DllCall("Comctl32.dll\DefSubclassProc", "Ptr", hWnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam)



   }



   ; Set Redrawing True/False.
   SetRedraw(Mode, Redrawing:="") {

      FileAppend, Redraw! Redrawing: %Redrawing%`n,*

      ; It's highly recommended to call this function instead of using GuiControl, -/+Redraw,
      ; because the drawing state will be stored internally for use by other methods.
      Static WM_SETREDRAW := 0x000B

      If (Redrawing != "") {
         ;FileAppend, This.Redrawing! `n,*
         This.Redrawing := Redrawing
      }

      Mode := !!Mode
      This.Drawing := Mode
      ;SendMessage, %WM_SETREDRAW%, %Mode%, 0, , % "ahk_id " . This.hWnd
      If (Mode)
         WinSet, Redraw, , % "ahk_id " . This.hWnd
   
      Return True

   }



}



WM_LBUTTONDOWN(wParam, lParam, Msg, Hwnd) {
   If (A_Gui)
      PostMessage, 0xA1, 2
}
Last edited by N_athan on 18 Jan 2022, 17:00, edited 2 times in total.


N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

Re: How to create/set a gui without background?

Post by N_athan » 18 Jan 2022, 15:38

Hey thanks, but i would like to get this working on windows 10 too.

I think the background rect is filled at this line:
https://github.com/Lexikos/AutoHotkey_L/blob/5d5a569f123f68cbd522d90bf6780f2b3be404af/source/script_gui.cpp#L8603

But im not sure how to "erase it"

fabricio234
Posts: 122
Joined: 06 Mar 2020, 21:48

Re: How to create/set a gui without background?

Post by fabricio234 » 18 Jan 2022, 17:09

Not sure if this will work but, you have set transparency in the guiDC
Try setting transparency in the dc created inside of WM.ERASEBKGND too

Code: Select all

DC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr",, "UPtr")
DllCall("Gdi32.dll\SelectObject", "Ptr", DC, "Ptr", HBITMAP)
DllCall("Gdi32.dll\SetBkMode", "Ptr", DC, "Int", 1) ; <= Here
This.DC := DC
Regarding the c++ thing you asked, @swagfag has already helped me once with some, tagging him maybe he could help somehow.

N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

Re: How to create/set a gui without background?

Post by N_athan » 19 Jan 2022, 10:53

fabricio234 wrote:
18 Jan 2022, 17:09
Not sure if this will work but, you have set transparency in the guiDC
Try setting transparency in the dc created inside of WM.ERASEBKGND too

Code: Select all

DC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr",, "UPtr")
DllCall("Gdi32.dll\SelectObject", "Ptr", DC, "Ptr", HBITMAP)
DllCall("Gdi32.dll\SetBkMode", "Ptr", DC, "Int", 1) ; <= Here
This.DC := DC
Regarding the c++ thing you asked, @swagfag has already helped me once with some, tagging him maybe he could help somehow.
I tried to set transparency into the dc like you suggest but it also did not work.

User avatar
lmstearn
Posts: 688
Joined: 11 Aug 2016, 02:32
Contact:

Re: How to create/set a gui without background?

Post by lmstearn » 20 Jan 2022, 03:13

Another thing to try would be a timer and ValidateRect or ValidateRgn in WM_ERASEBKGND and or WM_PAINT, in that case conditional statements regarding the background/foreground painting will have to be inserted into the event processing.
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

Re: How to create/set a gui without background?

Post by N_athan » 20 Jan 2022, 13:39

@lmstearn could you provide an example?
i couldnt find in the forum some examples using ValidateRect

fabricio234
Posts: 122
Joined: 06 Mar 2020, 21:48

Re: How to create/set a gui without background?

Post by fabricio234 » 20 Jan 2022, 18:02

https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-paintstruct
fErase

Indicates whether the background must be erased. This value is nonzero if the application should erase the background. The application is responsible for erasing the background if a window class is created without a background brush. For more information, see the description of the hbrBackground member of the WNDCLASS structure.
Did you tried setting this value to True inside of the PaintStruct?

User avatar
lmstearn
Posts: 688
Joined: 11 Aug 2016, 02:32
Contact:

Re: How to create/set a gui without background?

Post by lmstearn » 21 Jan 2022, 00:34

N_athan wrote:
20 Jan 2022, 13:39
@lmstearn could you provide an example?
i couldnt find in the forum some examples using ValidateRect
No, it's not in common use,- it can be used if the window is drawn, but WM_PAINT is not required. It looks like it could work after FillRect, but if the area is filled with a null brush there's not much point. If BeginPaint calls WM_ERASEBKGND, then ValidateRect, called in WM_ERASEBKGND, will only work for the following WM_PAINT, not the one being currently processed.

Btw, what were your results with BackgroundTrans mentioned above? When dealing with transparent bitmaps, also consider TransparentBlt.
The gui already has a background, so why not capture a portion of the screen background into the bitmap for that? The code in PicScroller can help with that for sure. :)

Code: Select all

hdcScreen := DllCall("CreateDC", "Str", "DISPLAY", "Ptr", 0, "Ptr", 0, "Ptr", 0)

ImageProps.hdcScreenCompat := DllCall("CreateCompatibleDC", "UPtr", hdcScreen)
;Retrieve the metrics for the bitmap associated with the regular device context. 
bmPlanes := DllCall( "GetDeviceCaps", "UPtr", hdcScreen, "Int", PLANES)
bmBitsPixel := DllCall( "GetDeviceCaps", "UPtr", hdcScreen, "Int", BITSPIXEL)


ImageProps.dcWidth := DllCall( "GetDeviceCaps", "UPtr", hdcScreen, "Int", HORZRES)
ImageProps.dcHeight := DllCall( "GetDeviceCaps", "UPtr", hdcScreen, "Int", VERTRES)
... etc.
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How to create/set a gui without background?

Post by just me » 21 Jan 2022, 05:55

EDIT: It doesn't work, it only seems to work as long as the background doesn't change. Sorry!

I didn't expect that this would work, but it does on my Win 10 system:

Code: Select all

#NoEnv
OnMessage(0x0014, "WM_ERASEBKGND")
OnMessage(0x0201, "WM_LBUTTONDOWN")
Gui, +hwndHGUI -Caption
Gui, Margin, 0, 0
Gui, Add, Pic,  w400 h200 BackgroundTrans Altsubmit vPic, Pic.png
Gui, Add, Edit, x50 y50 w300, My 1st Edit
Gui, Add, Edit, xp y+10 w300, My 2nd Edit
Gui, Add, Edit, xp y+10 w300, My 3rd Edit
Gui, Show, , Test
Return

GuiEscape:
ExitApp

WM_ERASEBKGND(W, L, M, H) {
   Global HGUI
   If (H = HGUI) ; may not be necessary
      Return True
}

WM_LBUTTONDOWN() {
   If (A_Gui) && (A_GuiControl = "")
      PostMessage, 0xA1, 2
}

N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

Re: How to create/set a gui without background?

Post by N_athan » 21 Jan 2022, 12:57

@fabricio234 i tried it, same result.

@just me i got the same result with my previous code "Class GDI", it only erase the background once and load the current background into the Gui. :|

User avatar
lmstearn
Posts: 688
Joined: 11 Aug 2016, 02:32
Contact:

Re: How to create/set a gui without background?

Post by lmstearn » 22 Jan 2022, 00:32

How about just me's code with a GroupBox instead?

Code: Select all

#NoEnv
OnMessage(0x0014, "WM_ERASEBKGND")
OnMessage(0x0201, "WM_LBUTTONDOWN")
Gui, +hwndHGUI -Caption
Gui, Margin, 0, 0
Gui, Add, GroupBox,  w400 h200 BackgroundTrans Altsubmit
Gui, Add, Edit, x50 y50 w300, My 1st Edit
Gui, Add, Edit, xp y+10 w300, My 2nd Edit
Gui, Add, Edit, xp y+10 w300, My 3rd Edit
Gui, Show, , Test

WinSet, Transparent, 200, ahk_id %HGUI%
;WinSet, TransColor, ffffff, ahk_id %HGUI%
Return

GuiEscape:
ExitApp

WM_ERASEBKGND(W, L, M, H) {
   Global HGUI
   If (H = HGUI) ; may not be necessary
      Return True
}

WM_LBUTTONDOWN() {
   If (A_Gui) && (A_GuiControl = "")
      PostMessage, 0xA1, 2
}
Return
Looks a bit better when making the whole thing a bit transparent, you might want to mod the frame, (transcolor on the text -at least for the default font here- glitches the text a bit). Try other types of font- or draw your own text, using a library like this.
Related thread, noting that layered windows cannot be parent to controls. Ref: link to transparent bitmap at Wikimedia.
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

Re: How to create/set a gui without background?

Post by N_athan » 23 Jan 2022, 20:12

You are using WinSet, Transparent, it applies layered attributes to the GUI, which causes some issues with transparent controls.

Also using the script you post with double buffer +E0x02000000 +E0x00080000, the control lose the transparency.

While I still trying to find a way to achieve this using AutoHotkey, I have created a topic on StackOverflow, if someone else cares:
https://stackoverflow.com/questions/70773592/how-to-erase-the-background-of-a-window

User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: How to create/set a gui without background?

Post by Hellbent » 23 Jan 2022, 20:34

N_athan wrote:
18 Jan 2022, 03:33
I dont know how/if is possible to load controls in Layered window, when i tried the controls dont became visible, only the picture.
As far as I am aware, you can't use a normal gui control with a layered window ( you can't see the control, but if you are on windows 8 or higher you can still interact with the hidden controls ).

You can also create your own controls, but it can be a lot of effort.

This is an example of a layered window gui with controls.

Image
viewtopic.php?f=19&t=89335

The only real issue is when it comes to using edit controls with a layered window. I barely have a functioning prototype edit control and have seen no other examples, so if you need edit controls, you might want to steer away from layered windows.
Of course you could just make your background a layered window and have it own a normal gui that sits inside it. ( <<<---- likely your best bet )

N_athan
Posts: 40
Joined: 21 Aug 2021, 16:40

Re: How to create/set a gui without background?

Post by N_athan » 23 Jan 2022, 21:58

In your script, you are creating a new GUI for each control and setting them parent to the Layered?
Drawing images into the background of the controls and the text is drawn directly to the pictures using GdipDrawTxt?

Code: Select all

		
Gui,2:Add,Text,x0 y0 w240 h30 hwndhwnd 
bd := This._MoveWindow.Bind( This )
GuiControl, 2: +G , % hwnd , % bd


Something like this?

Code: Select all

pToken := Gdip_Startup()
OnMessage(0x0201, "WM_LBUTTONDOWN")

W:= 400
H:= 200

Gui, L: +HwndGuiL +E0x80000 +OwnDialogs +Resize -Caption

hbm := CreateDIBSection(W, H)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G   := Gdip_GraphicsFromHDC(hdc)

Gdip_SetSmoothingMode(G, 4)

pBrush := Gdip_BrushCreateSolid(0x9B000000)
Gdip_FillRectangle(G, pBrush, 0, 0, W, H)
Gdip_DeleteBrush(pBrush)

UpdateLayeredWindow(GuiL, hdc, 0, 0, W, H)
Gui, L: Show, w%W% h%H%


Gui, 1: +ParentL
Gui, 1: +HwndGui1 +E0x02000000 +E0x00080000 -Caption
Gui, 1: Add, Button, x0 y0 w120 h30 Center, Button
Gui, 1: Show, x0 y0 w120 h30


Return
And there's the same problem, the GUI background color when using a control drawn with rounded corners:
2022-01-24_00-31-44.gif
2022-01-24_00-31-44.gif (377.06 KiB) Viewed 2032 times



Setting SetLayeredWindowAttributes on Gui1 the background is 'erased' but... the borders of the pictures lose quality and it also inherits the background color on them.

Code: Select all

Gui, 1: +ParentL
Gui, 1: Color, ffffff
Gui, 1: +HwndGui1 +E0x02000000 +E0x00080000 -Caption
Gui, 1: Add, Button, x0 y0 w220 h100 Center

DllCall("SetLayeredWindowAttributes", UInt, Gui1, UInt, 0xffffff, UChar, 0, UInt, 0x1)

2022-01-24_00-44-20.gif
2022-01-24_00-44-20.gif (646.43 KiB) Viewed 2026 times


Working with layered windows and controls is way more complicated, just being able to erase the background would help a lot. :|

User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: How to create/set a gui without background?

Post by Hellbent » 23 Jan 2022, 23:49

N_athan wrote:
23 Jan 2022, 21:58
In your script, you are creating a new GUI for each control and setting them parent to the Layered?
Drawing images into the background of the controls and the text is drawn directly to the pictures using GdipDrawTxt?

Code: Select all

		
Gui,2:Add,Text,x0 y0 w240 h30 hwndhwnd 
bd := This._MoveWindow.Bind( This )
GuiControl, 2: +G , % hwnd , % bd
That codes purpose is to repurpose the text control and use it a click trigger.
If you are running Windows 8 or higher, you can add controls and interact with them ( **if the background is painted** [ Tips / Tricks ] ) but you won't be able to see them.
If you look in the rest of that code you will see that I also used the functionality of a Hotkey gui control and used it to draw text on a layered window.
Something like this?
Working with layered windows and controls is way more complicated, just being able to erase the background would help a lot. :|
Something like this.
Animation.gif
Animation.gif (465.19 KiB) Viewed 2015 times

Code: Select all

;***************************************************************************************************
#Include, <My Altered GDIP LIB>  ;GDIP.ahk
;***************************************************************************************************

#SingleInstance, Force
SetBatchLines, -1
CoordMode, Mouse, Screen
DetectHiddenWindows, On

;******************************************************

pToken := Gdip_Startup()

ScaleFactor := A_ScreenDPI / 96

;******************************************************

Gui1 := New PopUpWindow( { AutoShow: 1 , X: "Center" , Y: "Center" , W: 800 * ScaleFactor , H: 400 * ScaleFactor , Options: " -DPIScale +AlwaysOnTop " } )
Gui1.DrawBitmap( HB_BITMAP_MAKER( ScaleFactor ) , { X: 0 , Y: 0 , W: Gui1.W , H: Gui1.H } , 1 , 1 )
Gui, % Gui1.Hwnd ":Add", Text, % "x" 142 * ScaleFactor " y" 32 * ScaleFactor " w" 440 * ScaleFactor " h" 36 * ScaleFactor " gMoveWindow" 
Gui, % Gui1.Hwnd ":Add", Text, % "x" 589 * ScaleFactor " y" 35 * ScaleFactor " w" 30 * ScaleFactor " h" 30 * ScaleFactor " gMinimizeWindow" 
Gui, % Gui1.Hwnd ":Add", Text, % "x" 624 * ScaleFactor " y" 35 * ScaleFactor " w" 30 * ScaleFactor " h" 30 * ScaleFactor " gGuiClose" 

;******************************************************

Gui, 2:New, % "-Caption +Owner" Gui1.Hwnd " hwndGui2Hwnd"
Gui, 2:Color, 45494F
Gui, 2:Margin, 10, 10
Gui, 2:Add, Edit, xm ym w300 r1 , % "Blah Blah Blah Blah Blah Blah Blah Blah"
Gui, 2:Add, Button, xm w120 h30 , Button
Gui, 2:Show, Hide

;******************************************************

WinGetPos, x, y,,, % "ahk_ID " Gui1.Hwnd
WinGetPos,,, w, h, % "ahk_ID " Gui2Hwnd

x := x + ( Gui1.W - w ) / 2
y := y + ( Gui1.H - h  ) / 2

Gui, 2:Show, % "x" x " y" y " NA"

;******************************************************

return
GuiClose:
*ESC::ExitApp

;~ RALT::PopUpWindow.Helper() 	;A tool that contains a clip for every function in the class.

MoveWindow:
	Gui, 2:Hide
	PostMessage, 0xA1, 2
	While( GetKeyState( "LButton" ) )
		Sleep, 30
	WinGetPos, x, y,,, % "ahk_ID " Gui1.Hwnd
	WinGetPos,,, w, h, % "ahk_ID " Gui2Hwnd
	Gui1.UpdateSettings( { X: x , Y: y } )
	x := x + ( Gui1.W - w  ) / 2
	y := y + ( Gui1.H - h ) / 2
	Gui, 2:Show, % "x" x " y" y " NA"
	return

MinimizeWindow:	
	Gui, % Gui1.Hwnd ":Minimize"
	return

HB_BITMAP_MAKER( ScaleFactor := 1 ){
	;Bitmap Created Using: HB Bitmap Maker
	pBitmap := Gdip_CreateBitmap( 800 * ScaleFactor , 400 * ScaleFactor ) , G := Gdip_GraphicsFromImage( pBitmap ) , Gdip_SetSmoothingMode( G , 2 )
	;Background
	Brush := Gdip_BrushCreateSolid( "0x6622262a" ) , Gdip_FillRoundedRectangle( G , Brush , 10 * ScaleFactor , 10 * ScaleFactor , 780 * ScaleFactor , 380 * ScaleFactor , 150 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 3 * ScaleFactor , 6 * ScaleFactor , 789 * ScaleFactor , 383 * ScaleFactor , "0x6645494f" , "0x66161a23" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 12 * ScaleFactor , 12 * ScaleFactor , 776 * ScaleFactor , 376 * ScaleFactor , 150 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF45494f" ) , Gdip_FillRoundedRectangle( G , Brush , 22 * ScaleFactor , 22 * ScaleFactor , 756 * ScaleFactor , 356 * ScaleFactor , 150 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF000000" ) , Gdip_FillRoundedRectangle( G , Brush , 140 * ScaleFactor , 30 * ScaleFactor , 520 * ScaleFactor , 40 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Title bar
	Brush := Gdip_BrushCreateSolid( "0xFF32363a" ) , Gdip_FillRoundedRectangle( G , Brush , 142 * ScaleFactor , 32 * ScaleFactor , 516 * ScaleFactor , 36 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF000000" ) , Gdip_TextToGraphics( G , "WinTitle" , "s" 22 * ScaleFactor " Center vCenter Bold c" Brush " x" 145 * ScaleFactor " y" 36 * ScaleFactor  , "Comic Sans MS" , 516 * ScaleFactor , 36 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_TextToGraphics( G , "WinTitle" , "s" 22 * ScaleFactor " Center vCenter Bold c" Brush " x" 143 * ScaleFactor " y" 33 * ScaleFactor  , "Comic Sans MS" , 516 * ScaleFactor , 36 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Min Button
	Brush := Gdip_CreateLineBrushFromRect( 591 * ScaleFactor , 37 * ScaleFactor , 29 * ScaleFactor , 24 * ScaleFactor , "0xFF62666a" , "0xFF000000" , 1 , 1 ) , Gdip_FillEllipse( G , Brush , 589 * ScaleFactor , 35 * ScaleFactor , 30 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF0078D7" ) , Gdip_TextToGraphics( G , "_" , "s" 36 * ScaleFactor " Center vCenter Bold c" Brush " x" 590 * ScaleFactor " y" 21 * ScaleFactor  , "Segoe ui" , 30 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Close Button
	Brush := Gdip_CreateLineBrushFromRect( 591 * ScaleFactor , 37 * ScaleFactor , 29 * ScaleFactor , 24 * ScaleFactor , "0xFF62666a" , "0xFF000000" , 1 , 1 ) , Gdip_FillEllipse( G , Brush , 624 * ScaleFactor , 35 * ScaleFactor , 30 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x66ff0000" ) , Gdip_TextToGraphics( G , "X" , "s" 20 * ScaleFactor " Center vCenter c" Brush " x" 625 * ScaleFactor " y" 37 * ScaleFactor  , "Comic Sans MS" , 30 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Gdip_DeleteGraphics( G )
	return pBitmap
}





;####################################################################################################################################################################################
;####################################################################################################################################################################################
;###############################################################	  Layered Window Class	    #####################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
class PopUpWindow	{
;PopUpWindow v2
;Date Written: Oct 28th, 2021
;Written By: Hellbent aka CivReborn
;SpcThanks: teadrinker , malcev 
	static Index := 0 , Windows := [] , Handles := [] , EditHwnd , HelperHwnd
	__New( obj := "" ){
		This._SetDefaults()
		This.UpdateSettings( obj )
		This._CreateWindow()
		This._CreateWindowGraphics()
		if( This.AutoShow )
			This.ShowWindow( This.Title )
	}
	_SetDefaults(){
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
		This.Smoothing := 2
		This.Options := " -DPIScale +AlwaysOnTop "
		This.AutoShow := 0
		This.GdipStartUp := 0
		This.Title := ""
		
		This.Controls := []
		This.Handles := []
		This.Index := 0 
	}
	AddTrigger( obj ){
		local k , v , cc , bd
		
		This.Controls[ ++This.Index ] := { 	X:		10
										,	Y:		10
										,	W:		10
										,	H:		10	}
		for k, v in obj
			This.Controls[ This.Index ][ k ] := obj[ k ] 
		cc := This.Controls[ This.Index ]
		Gui, % This.Hwnd ":Add", Text, % "x" cc.X " y" cc.Y " w" cc.W " h" cc.H " hwndhwnd"
		This.Handles[ hwnd ] := This.Index
		This.Controls[ This.Index ].Hwnd := hwnd
		return hwnd
		
	}
	DrawTriggers( color := "0xFFFF0000" , AutoUpdate := 0 ){
		local brush , cc 
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_SetSmoothingMode( This.G , 3 )
		loop, % This.Controls.Length()	{
			cc := This.Controls[ A_Index ]
			Gdip_FillRectangle( This.G , Brush , cc.x , cc.y , cc.w , cc.h )
		
		}
		Gdip_DeleteBrush( Brush )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	UpdateSettings( obj := "" , UpdateGraphics := 0 ){
		local k , v
		if( IsObject( obj ) )
			for k, v in obj
				This[ k ] := obj[ k ]
		( This.X = "Center" ) ? ( This.X := ( A_ScreenWidth - This.W ) / 2 ) 	
		( This.Y = "Center" ) ? ( This.Y := ( A_ScreenHeight - This.H ) / 2 ) 	
		if( UpdateGraphics ){
			This._DestroyWindowsGraphics()
			This._CreateWindowGraphics()
		}
	}
	_CreateWindow(){
		local hwnd
		Gui , New, % " +LastFound +E0x80000 hwndhwnd -Caption  " This.Options
		PopUpWindow.Index++
		This.Index := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
		This.Hwnd := hwnd
		PopUpWindow.Handles[ hwnd ] := PopUpWindow.Index
		if( This.GdipStartUp && !PopUpWindow.pToken )
			PopUpWindow.pToken := GDIP_STARTUP()
	}
	_DestroyWindowsGraphics(){
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
	}
	_CreateWindowGraphics(){
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
	}
	ShowWindow( Title := "" ){
		Gui , % This.Hwnd ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.Hwnd ":Hide",
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	ClearWindow( AutoUpdate := 0 ){
		Gdip_GraphicsClear( This.G )
		if( Autoupdate )
			This.UpdateWindow()
	}
	DrawBitmap( pBitmap , obj , dispose := 1 , AutoUpdate := 0 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
		if( Autoupdate )
			This.UpdateWindow()
	}
	PaintBackground( color := "0xFF000000" , AutoUpdate := 0 ){
		if( isObject( color ) ){
			Brush := Gdip_BrushCreateSolid( ( color.HasKey( "Color" ) ) ? ( color.Color ) : ( "0xFF000000" ) ) 
			if( color.Haskey( "Round" ) )
				Gdip_FillRoundedRectangle( This.G , Brush , color.X , color.Y , color.W , color.H , color.Round )
			else
				Gdip_FillRectangle( This.G , Brush , color.X , color.Y , color.W , color.H ) 
		}else{
			Brush := Gdip_BrushCreateSolid( color ) 
			Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		}
		Gdip_DeleteBrush( Brush )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DeleteWindow( GDIPShutdown := 0 ){
		Gui, % This.Hwnd ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
		if( GDIPShutdown ){
			Gdip_Shutdown( PopUpWindow.pToken )
			PopUpWindow.pToken := ""
		}
	}
	_OnClose( wParam ){
		if( wParam = 0xF060 ){	;SC_CLOSE ;[ clicking on the gui close button ]
			Try{
				Gui, % PopUpWindow.HelperHwnd ":Destroy"
				SoundBeep, 555
			}
		}
	}
	CreateCachedBitmap( pBitmap , Dispose := 0 ){
		local pCachedBitmap
		if( This.CachedBitmap )
			This.DisposeCachedbitmap()
		DllCall( "gdiplus\GdipCreateCachedBitmap" , "Ptr" , pBitmap , "Ptr" , this.G , "PtrP" , pCachedBitmap )
		This.CachedBitmap := pCachedBitmap
		if( Dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DrawCachedBitmap( AutoUpdate := 0 ){
		DllCall( "gdiplus\GdipDrawCachedBitmap" , "Ptr" , this.G , "Ptr" , This.CachedBitmap , "Int" , 0 , "Int" , 0 )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DisposeCachedbitmap(){
		DllCall( "gdiplus\GdipDeleteCachedBitmap" , "Ptr" , This.CachedBitmap )
	}
	Helper(){
		local hwnd , MethodList := ["__New","UpdateSettings","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow" , "AddTrigger" , "DrawTriggers", "CreateCachedBitmap" , "DrawCachedBitmap" , "DisposeCachedbitmap" ]
		Gui, New, +AlwaysOnTop +ToolWindow +HwndHwnd
		PopUpWindow.HelperHwnd := hwnd
		Gui, Add, Edit, xm ym w250 r1 Center hwndhwnd, Gui1
		PopUpWindow.EditHwnd := hwnd
		loop, % MethodList.Length()	
			Gui, Add, Button, xm y+1 w250 r1 gPopUpWindow._HelperClip, % MethodList[ A_Index ]
		Gui, Show,,
		OnMessage( 0x112 , This._OnClose.Bind( hwnd ) )
	}
	_HelperClip(){
		local ClipList 
		
		GuiControlGet, out, % PopUpWindow.HelperHwnd ":", % PopUpWindow.EditHwnd	
		
		ClipList := 		{ 	__New: 					" := New PopUpWindow( { X: 0 , Y: 0 , W: A_ScreenWidth , H: A_ScreenHeight , Options: "" -DPIScale +AlwaysOnTop "" } )"
							,	UpdateSettings:			".UpdateSettings( { X: """" , Y: """" , W: """" , H: """" } , UpdateGraphics := 0 )"
							,	ShowWindow:				".ShowWindow( Title := """" )"
							,	HideWindow:				".HideWindow()"
							,	UpdateWindow:			".UpdateWindow()"
							,	ClearWindow:			".ClearWindow( AutoUpdate := 0 )"
							,	DrawBitmap:				".DrawBitmap( pBitmap := """" , { X: 0 , Y: 0 , W: " Out ".W , H: " Out ".H } , dispose := 1 )"
							,	PaintBackground:		".PaintBackground( color := ""0xFF000000"" )  "  ";{ Color: ""0xFF000000"" , X: 2 , Y: 2 , W: " Out ".W - 4 , H: " Out ".H - 4 , Round: 10 }"
							,	DeleteWindow:			".DeleteWindow( GDIPShutdown := 0 )"
							,	AddTrigger:				".AddTrigger( { X: """" , Y: """" , W: """" , H: """" , Value: """" , Label: """" , BoundClass: """" , BoundMethod: """" } )"	
							,	DrawTriggers:			".DrawTriggers( color := ""0xFFFF0000"" , AutoUpdate := 0 )"	
							,	CreateCachedBitmap:		".CreateCachedBitmap( pBitmap , Dispose := 0 )"	
							,	DrawCachedBitmap: 		".DrawCachedBitmap( AutoUpdate := 0 )"	
							,	DisposeCachedbitmap:	".DisposeCachedbitmap()"	}
							
		clipboard := Out ClipList[ A_GuiControl ]
		
	}
}

***EDIT***
Corrected scaling of window size.

Code: Select all

;Before
x := x + ( Gui1.W - w * ScaleFactor ) / 2
;After
x := x + ( Gui1.W - w  ) / 2
Last edited by Hellbent on 24 Jan 2022, 07:37, edited 1 time in total.

User avatar
lmstearn
Posts: 688
Joined: 11 Aug 2016, 02:32
Contact:

Re: How to create/set a gui without background?

Post by lmstearn » 24 Jan 2022, 01:16

@Hellbent: That's nice. :)
@N_athan:
Ah, having been round the traps with this, you have gotten to meet a lot of interesting folk, no? :)
If you want to show the controls while moving the mouse in the above script, it's possible to set a timer in order to move the gui around with the form, the controls can be disabled while this happens to avoid extra stutter. This may not be the best. Alternatively, take a snapshot of the controls, and redraw them onto the bitmap in the next WM_ENTERSIZEMOVE might produce a better result.
Made the whole thing transparent by commenting this line out:

Code: Select all

;Brush := Gdip_BrushCreateSolid( "0xFF45494f" ) , Gdip_FillRoundedRectangle( G , Brush , 22 * ScaleFactor , 22 * ScaleFactor , 756 * ScaleFactor , 356 * ScaleFactor , 150 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
You can mod that to suit for a different bevel on the edges.
:arrow: itros "ylbbub eht tuO kaerB" a ni kcuts m'I pleH

Post Reply

Return to “Ask for Help (v1)”