per-pixel alpha blended GUI demo
I've been using autohotkeys for about a year, and I am getting a lot better at THE BASICS, but I'm still learning, so forgive me is if I sound like a noob.
I tried the code and I was very impressed at how the PNG looks, if you get creative with Photoshop and make a png graphic that looks like glass with a shadow behind it, (Vista style) it looks awesome. However, from reading the post I understand you cant add controls on a layered window because they wont show. It was suggested that two GUI's could be used, one with the PNG and another with the controls, and I guess that could be a work around, but I don't even know how I would go about doing that.
If someone could elaborate a little on that, or point me to some additional documentation I could read and get more familiarized with all this, it would be wonderful.
I haven't tried it yet, but one brainstorm idea I had was to use the DOC function to dock a widow with controls on top of the window with the png, and then set the background color of the window with the controls to be transparent with Winset Transcolor , but not sure how or if that would work. Another thought I had was perhaps use the SETPARENT function to set the gui with controls as the child of the layered GUI with the PNG, but again, not sure if that would work either.
I haven't tried it yet, but one brainstorm idea I had was to use the DOC function to dock a widow with controls on top of the window with the png, and then set the background color of the window with the controls to be transparent with Winset Transcolor , but not sure how or if that would work. Another thought I had was perhaps use the SETPARENT function to set the gui with controls as the child of the layered GUI with the PNG, but again, not sure if that would work either.
I imagine the easiest way would be to have the second window move when the skinned window moves. But I'm having trouble understanding how to get the X and Y coords from the function so that it doesn't lag behind...
I'm using this:
Gui, Show, Center W%nWidth% H%nHeight%, WinTitleand
WM_MOVE(wParam, lParam, nMsg, hWnd) { If A_Gui && DllCall("UpdateLayeredWindow", "Uint", hWnd, "Uint", 0, "int64P", (lParam<<48>>48)&0xFFFFFFFF|(lParam&0xFFFF0000)<<32>>16, "Uint", 0, "Uint", 0, "Uint", 0, "Uint", 0, "Uint", 0, "Uint", 0) WinGetPos, GuiX, GuiY,,, WinTitle if (GuiY) Gui, 2: Show, x%GuiX% y%GuiY% else Gui, 2: Show, Center Return 0 }Which works, but the second gui seems to lag behind just a tad... And I'd be greatful if someone could show me a better way.
P.S. Gui 2 is +AlwaysOnTop
The docking method should work. SetParent won't since that essentially makes the window a "control" of the parent window. (i.e. it will become invisible.)Another thought I had was perhaps use the SETPARENT function to set the gui with controls as the child of the layered GUI with the PNG, but again, not sure if that would work either.
SetAlpha(hwnd, alpha) { DllCall("UpdateLayeredWindow","uint",hwnd,"uint",0,"uint",0 ,"uint",0,"uint",0,"uint",0,"uint",0,"uint*",alpha<<16|1<<24,"uint",2) }In Sean's version of the script, the default alpha is the red bit:
DllCall("UpdateLayeredWindow", "Uint", WinExist(), "Uint", 0, "Uint", 0, "int64P", nWidth|nHeight<<32, "Uint", mDC_Scr, "int64P", 0, "Uint", 0, "UintP", [color=red]255[/color]<<16|1<<24, "Uint", 2)Alpha is a number between 0 (fully transparent) and 255 (fully opaque, assuming the bitmap is opaque.)
Most parameters of UpdateLayeredWindow are optional. You can update the image data, size, position, blend function, or any combination. (Blend function = constant alpha, & whether to use the source bitmap's alpha.)
I know a lot of us using this language would appreciate it if we could make desktop gadgets and such, using autohotkey, and still get shadows behind the gui and all the other effects you can get with a PNG.
but it is all flickery and jumpy as i want the coverart to be the draggable part, so everything muct be docked to that, but then everything jostles for position.
hopefully a good fix can be found, as this will revolutionize ahk guis, if you can just make the whole gui and any control a png. I think youll agree that it looks much more professional than a standard gui.
Thanks...
Basically, for it to work well, you need to draw the "controls" directly onto a bitmap, which would then be applied to the window with UpdateLayeredWindow. The biggest problem is that GDI does not support alpha blending, so to draw text, shapes, etc. you need to either use GDI+ or manually calculate the alpha data (which is always fun! )
Luckily, AlphaBlend can be used to draw bitmaps onto bitmaps; obviously with alpha blending. Like with GDI functions, you need to create a device context (CreateCompatibleDC) and select the bitmap into it (SelectObject). However, I think AlphaBlend() expects the bitmap to have pre-multiplied alpha (i.e. the RGB values of each pixel are pre-multiplied by the alpha component.) I haven't managed to get that to look quite right...
If you plan on going ahead with this, I'd suggest doing a few GDI/GDI+ tutorials first, and perhaps looking at any existing AutoHotkey scripts that use GDI or GDI+.
Alternatively, you might be able to remove some "jostling" by replacing Dock with OnMessage - since the GUI is under your control, you should be able to simply handle WM_WINDOWPOSCHANGING (0x46) and move the child windows from there. I think WM_WINDOWPOSCHANGING is sent before the window moves, so it would probably be more responsive.
OnMessage(0x200, "WM_MOUSEMOVE") Gui, 1: +LastFound -Caption +ToolWindow +0x400000 Gui1 := WinExist() Gui, 1: Add, Text, x0 y0 w200 h200 Border Center GuiMove, Click Here `&& Drag Gui, 1: Show, x200 y200 w200 h200, GUi1 Gui, 2: +LastFound -Caption +ToolWindow +0x400000 Gui2 := WinExist() Gui, 2: Show, x500 y200 w200 h200, Gui2 Return uiMove: PostMessage, 0xA1, 2,,, A Return Esc::ExitApp WM_MOUSEMOVE() { global WinGetPos, Gui1X, Gui1Y,,, ahk_id %Gui1% Result := DllCall("SetWindowPos", "UInt", Gui2, "UInt", Gui1, "Int", Gui1X + 300, "Int", Gui1Y, "Int", "", "Int", "", "Int", 0x01) Return }
That just uses mousemove to detect a window being moved, which isnt ideal, as some people have "show window contents while dragging" enabled. I didnt understand how to register this callback:
<!-- m -->http://msdn2.microso...y/ms633573.aspx<!-- m -->
perhaps you can help
Edit: ha. yeh...i completely dont uderstand how to use that onmessage and registercallback. help would be appreciated.
OnMessage(0x46, "WM_WINDOWPOSCHANGING") Gui, 1:Show, X200 Y200 W400 H400, Parent Gui, 2:+AlwaysOnTop Gui, 2:Show, X210 Y230 W100 H100, Child return WM_WINDOWPOSCHANGING(wParam, lParam) { if (A_Gui = 1 && !(NumGet(lParam+24) & 0x2)) ; SWP_NOMOVE=0x2 { x := NumGet(lParam+8), y := NumGet(lParam+12) x += 10, y += 30 Gui, 2:Show, X%x% Y%y% NA } }
OnMessage(0x46, "WM_WINDOWPOSCHANGING") Gui, 1: -Caption +ToolWindow +0x400000 +LastFound Gui1 := WinExist() Gui, 1: Add, Text, x0 y0 w200 h200 Border Center gMove, Drag Gui, 1: Show, x200 y200 w200 h200, Gui1 Gui, 2: -Caption +ToolWindow +0x400000 +LastFound Gui2 := WinExist() Gui, 2: Show, x150 y150 w100 h100, Gui2 Return Move: PostMessage, 0xA1, 2,,, A Return WM_WINDOWPOSCHANGING(wParam, lParam) { global If (A_Gui = 1 && !(NumGet(lParam+24) & 0x2)) { x := NumGet(lParam+8), y := NumGet(lParam+12) Result := DllCall("SetWindowPos", "UInt", Gui2, "UInt", Gui1, "Int", x-50, "Int", y-50, "Int", "", "Int", "", "Int", 0x01) } SetTimer, OnTop, 10 Result := DllCall("SetWindowPos", "UInt", Gui1, "UInt", Gui2, "Int", "", "Int", "", "Int", "", "Int", "", "Int", 0x03) ;Tooltip, %Result% Return } OnTop: SetTimer, OnTop, Off Result := DllCall("SetWindowPos", "UInt", Gui1, "UInt", Gui2, "Int", "", "Int", "", "Int", "", "Int", "", "Int", 0x03) Return
it shouldnt be necessary to set a timer, and makes it look messy, but why does correcting the z-order not work? obviosuly alwaysontop as shown in your example cannot be used, but then how would i keep the z-order?
Why is it that
hicon := DllCall("LoadImage", "uInt", 0, "Str", "Icon.ico", "uInt", 2, "Int", 16, "Int", 16, "uInt", 0x10)
doesnt work?
What extra would be needed to get an ico to show in a similar way to the pngs?
Actually, not really based on per pixel stuff.....but would be very useful to know. How exactly does the png format work. So I have read information about it, but if I wanted to make my own png using just the hex values, then what are the steps needed? For example icons have a header, BGR and then opacity for each pixel and then a mask at the end.
So 1 pixel black icon would look like:
Header . ffffffff . Mask
But I see there is compression with png, so what are the steps to first make the png format and then compress it if I wish to construct it from hex? (I ask all this as I believe I could remake all the ahk controls, but for per pixel png guis, so some really nice guis could be constructed)
Thank you
IMAGE_ICON := 0x1 LR_LOADFROMFILE := 0x10 MsgBox % hicon := DllCall("LoadImage" , "uInt", 0 , "Str", "C:\Icon.ico" , "uInt", IMAGE_ICON , "Int", 16 , "Int", 16 , "uInt", LR_LOADFROMFILE)
ʞɔпɟ əɥʇ ʇɐɥʍ