Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

per-pixel alpha blended GUI demo


  • Please log in to reply
48 replies to this topic
MiamiGuy
  • Members
  • 61 posts
  • Last active: Nov 25 2011 07:44 AM
  • Joined: 03 Nov 2006
I have to say "BRAVO", I'm sure a lot of us had been waiting anxiously for the moment we could use something like this in AHK.
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.

maximina
  • Members
  • 17 posts
  • Last active: Nov 04 2008 08:20 PM
  • Joined: 17 Oct 2007
Excellent work chaps! This solution is getting book-marked.

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%, WinTitle
and
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

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

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.

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.)

maximina
  • Members
  • 17 posts
  • Last active: Nov 04 2008 08:20 PM
  • Joined: 17 Oct 2007
Now, if only someone could figure out how to change the transparency of the alpha-blended image on the fly...

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
I've known how right from the get go. 8)
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.)

MiamiGuy
  • Members
  • 61 posts
  • Last active: Nov 25 2011 07:44 AM
  • Joined: 03 Nov 2006
I really think PNG support for AutoHotkey needs to be worked on and developed a bit further, specially now that Vista's graphics are pretty much mostly PNG's.
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.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Again...thank you lexikos and sean. I am writing something truly great to demonstrate nicly examples of how this can be used, but I really need a way to put controls onto it. I tried using majikinators dock, but it is too unstable and not suited to handling controls in this way. you can add one or two controls, but problems arise, especially as they all must be docked to 1 hwnd and you cannot choose which you want them to dock to. I would appreciate any suggestions on how to get a few controls on. thanks

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
It sounds like you are trying to dock each control to the per-pixel GUI. What you should do is add the controls to a GUI, use WinSet TransColor to make its background invisible, and dock it to the per-pixel GUI.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
problem is i want all the transparencies, and im trying to put pngs onto pngs. I just wanted to demonstrate how good your code actually was at creating guis, but unfortunately the docking method is too cumbersome. I have this....

Posted Image


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...

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
Ah, so by "controls" you weren't talking about the conventional windows kind. :) I've been meaning to write a "layered GUI framework" for AutoHotkey, but haven't had the time (i.e. too many other projects to finish first.)

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! :p)

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.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
thanks very much lexikos. could you please help on the registercallback though :oops:

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.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
You don't need RegisterCallback. As I said, use WM_WINDOWPOSCHANGING. Here's an example:
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
    }
}


tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
mmm whats going wrong here....

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?

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Ok. using methods I have used for tray bars, I could make nice looking controls, but it would be nice to be able to use icons rather than pngs, as theres all that compression and other stuff.

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

ahklerner
  • Members
  • 1386 posts
  • Last active: Oct 08 2014 10:29 AM
  • Joined: 26 Jun 2006
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)


Posted Image
ʞɔпɟ əɥʇ ʇɐɥʍ