So I'm starting a new topic.Should really start a new topic, but do you have any idea of how to have an image with transparencies put onto an invisible gui? So the png for example would appear to be its own gui.
For anyone with programming experience, this demonstration is based on one of these articles/demos:
Per Pixel Alpha Blend (C++)
Per Pixel Alpha Blend in C#
(I forget which one.)
A while ago I wrote a test script to demonstrate how to do this from AutoHotkey. It got rather messy, as I tried various things with it. (Various text effects with GDI; messy because GDI doesn't really support alpha-blending.) Here's a cleaned up version - a magnifying glass (just an icon, lol) that can be dragged around the screen:
[Edit: see Sean's post with added PNG support via GDI+]
; REQUIRES WINDOWS 2000 OR LATER #NoEnv Gui, -Caption +E0x80000 ; WS_EX_LAYERED ; Prevents later Gui,Show calls from auto-sizing the GUI. ; Center/default positioning doesn't work unless we explicitly ; size the GUI. :-/ (It will be resized to the size of the icon later.) Gui, Show, W1 H1 Hide Gui, +LastFound if !(h_icon := ExtractIcon("shell32.dll", 23, 48)) ExitApp GetIconSize(h_icon, width, height) ; Create a device context compatible with the screen. if (hdcDest := DllCall("CreateCompatibleDC", "UInt", 0)) { ; Create a 32-bit bitmap to draw the icon onto. if (h_bm := CreateDIBSection(width, height, 32, hdcDest, pBits)) { ; Select the new bitmap into the device context. if (bmOld := GDI_SelectObject(hdcDest, h_bm)) { ; Draw the icon onto the window. DllCall("DrawIconEx" , "UInt", hdcDest ; hdc (destination device context) , "Int" , x+1 ; xLeft , "Int" , 0 ; yTop , "UInt", h_icon , "UInt", width , "UInt", height , "UInt", 0 ; istepIfAniCur , "UInt", 0 ; hbrFlickerFreeDraw = NULL (draw directly into buffer) , "UInt", 3) ; diFlags = DI_NORMAL ; BLENDFUNCTION bf VarSetCapacity(bf, 4, 0) ;NumPut(0, bf, 0, "UChar") ; BlendOp := AC_SRC_OVER ;NumPut(0, bf, 1, "UChar") ; BlendFlags - must be zero NumPut(255, bf, 2, "UChar") ; SourceConstantAlpha := 255 NumPut(1, bf, 3, "UChar") ; AlphaFormat := AC_SRC_ALHPA VarSetCapacity(size, 8, 0) NumPut(width, size, 0) NumPut(height, size, 4) hwnd := WinExist() DllCall("UpdateLayeredWindow" , "uint", hwnd , "uint", 0 ; hdcDst , "uint", 0 ; pptDst (pointer to new position, or NULL if not changing) , "uint", &size ; psize (pointer to new size, or NULL if not changing) , "uint", hdcDest ; hdcSrc (defines the layered window) , "uint", &ptSrc ; pptSrc (pointer to location of the layer in the DC) , "uint", 0 ; crKey (not used if !(dwFlags&ULW_COLROKEY)) , "uint", &bf ; pblend , "uint", 2) ; dwFlags := ULW_ALPHA (use pblend, not crKey) ; Reselect previous object (as per MSDN recommendation.) GDI_SelectObject(hdcDest, bmOld) } ; we no longer need the bitmap! (Windows has created a copy for the layered window) DllCall("DeleteObject", "uint", h_bm) } ; Done using the device context. DllCall("DeleteDC", "UInt", hdcDest) } OnMessage(0x201, "WM_LBUTTONDOWN") Gui, Show return GuiClose: GuiEscape: ExitApp ; Allow click-drag to move the window. WM_LBUTTONDOWN() { if (A_Gui) { Gui, +LastFound PostMessage, 0xA1, 2 ; WM_NCLBUTTONDOWN } } GDI_SelectObject(hdc, hgdiobj) { return DllCall("SelectObject", "uint", hdc, "uint", hgdiobj) } GDI_DeleteObject(hObject) { return DllCall("DeleteObject", "uint", hObject) } GetIconSize(h_icon, ByRef width, ByRef height) { VarSetCapacity(ii, 20, 0) if (DllCall("GetIconInfo", "UInt", h_icon, "UInt", &ii)) { hbmColor := NumGet(ii, 16) hbmMask := NumGet(ii, 12) ret := GetBitmapSize(hbmColor, width, height) DllCall("DeleteObject", "UInt", hbmColor) DllCall("DeleteObject", "UInt", hbmMask) return ret } return false } GetBitmapSize(h_bitmap, ByRef width, ByRef height, ByRef bpp="") { VarSetCapacity(bm, 24, 0) ; BITMAP if (!DllCall("GetObject", "UInt", h_bitmap, "Int", 24, "UInt", &bm)) return false width := NumGet(bm, 4, "int") height := NumGet(bm, 8, "int") bpp := NumGet(bm,18, "ushort") return true } CreateDIBSection(w, h, bpp, hDC=0, ByRef ppvBits=0) { hdcUsed := hDC ? hDC : DllCall("GetDC", "UInt", 0) if (hdcUsed) { VarSetCapacity(bi, 40, 0) ; BITMAPINFO(HEADER) NumPut(40, bi, 0) ; biSize NumPut(1, bi, 12, "UShort") ; biPlanes NumPut(0, bi, 16) ; biCompression = BI_RGB (none) NumPut(w, bi, 4) ; biWidth NumPut(h, bi, 8) ; biHeight NumPut(bpp,bi, 14, "UShort") ; biBitCount hbmp := DllCall("CreateDIBSection" , "UInt" , hDC , "UInt" , &bi ; defines format, attributes, etc. , "UInt" , 0 ; iUsage = DIB_RGB_COLORS , "UInt*", ppvBits ; gets a pointer to the bitmap data , "UInt" , 0 , "UInt" , 0) if (hdcUsed != hDC) DllCall("ReleaseDC", "UInt", 0, "UInt", hdcUsed) return hbmp } return 0 } ExtractIcon(Filename, IconNumber, IconSize=0) { return DllCall("LoadImage" ,"uint",DllCall("GetModuleHandle","str","shell32.dll") ,"uint",IconNumber,"uint",1,"int",IconSize,"int",IconSize,"uint",0) }It should work on Vista and XP; I'm not sure if the icon exists on earlier versions of Windows. The icon can easily be changed, anyway, by changing this line:
if !(h_icon := ExtractIcon("shell32.dll", 23, 48))Icon 23 on Vista and XP is a magnifying glass. The "48" on the end is to specify the 48x48 icon.
The process is "basically":
[*:3ry97oy8]Create the GUI/window with the WS_EX_LAYERED extended style (+E0x80000).
[*:3ry97oy8]Create a GDI device context. (Knowing how to use this is more important than knowing what it is.)
[*:3ry97oy8]Create a 32-bit device independent bitmap.
[*:3ry97oy8]Select the bitmap into the device context.
[*:3ry97oy8]Using the device context, draw the icon onto the bitmap.
[*:3ry97oy8]Call UpdateLayeredWindow() to update the size and content of the window, using the device context.If you already have a bitmap (i.e. loaded from a PNG file), you can skip steps 3 and 5. To load PNG files, see Image conversions and capturing with GDI+.
It is important to note that layered windows cannot have controls. At least, they won't be visible. To have similar functionality, you'd either have to use two windows/GUIs (one layered + one with controls) or draw your own "controls."
Edit: Updated ExtractIcon() to use LoadImage (thanks to Sean.)
Edit: Fixed WM_LBUTTONDOWN() to use Gui,+LastFound instead of Gui,Default (oops.)
Edit: Fixed handle leak in CreateDIBSection (minor since it didn't apply to the example.)