I've been looking for ways to create interactive GUI's with GDI+ and found the
TTG example that tic refers to a few posts above.
I wrote the following script as research/preparation for another script I'm working on, but I think it's a reasonable example of one way to create interactive GDI+ gui's (I mean, it kinda has to be - it's largely based off of tic's TTG stuff

).
Right now, it will just display screenshots of the first 4 windows in the AltTab cycle (i limited it to 4 for anybody on smaller resolution screens - right now it's not smart about detecting screen sizes and adjusting, etc.). Also, it has a close button that works.
I had fun playing around with this and I hope it can help somebody.
Code:
#SingleInstance, Force
#NoEnv
CoordMode, Mouse, Screen
SetBatchLines, -1
; Start gdi+
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
; Create the window we'll be redrawing on and save its handle
Gui, 1: -Caption +E0x80000 +LastFound +OwnDialogs
Gui, 1: Show, NA, This is my script
hgui1 := WinExist()
; Get open window list
alist := AltTabList(hgui1)
; Get bitmaps of windows in the list
Loop, parse, alist, `,
{
if (A_Index > 4)
break
pBitmap%A_Index% := Gdip_BitmapFromHWND(A_LoopField)
WinGetPos, , , w%A_Index%, h%A_Index%, ahk_id %A_LoopField%
if (w%A_Index% > h%A_Index%)
{
ww%A_Index% := 200
wh%A_Index% := 200 * (h%A_Index%/w%A_Index%)
wx%A_Index% := 50 + ((A_Index-1) * 230)
wy%A_Index% := 50 + floor((200 - wh%A_Index%)/2)
}
else
{
ww%A_Index% := 200 * (w%A_Index%/h%A_Index%)
wh%A_Index% := 200
wx%A_Index% := 50 + ((A_Index-1) * 230) + floor((200 - ww%A_Index%)/2)
wy%A_Index% := 50
}
; set up region information for hovering stuff
%A_Index%_x := 35 + ((A_Index-1) * 230)
%A_Index%_y := 35
%A_Index%_w := 230
%A_Index%_h := 230
regions .= "," A_Index
; get window title
WinGetTitle, %A_Index%_title, ahk_id %A_LoopField%
; remember how many windows there are
windowcount := A_Index
}
; Set the width and height of the main window
gw := (windowcount * 230) + 30 + 40
gh := 350
; 1. Create a gdi bitmap of the appropriate width and height
; 2. Get a compatiable device context
; 3. Select the bitmap into the device context
; 4. Get a pointer to the graphics of the bitmap
hbm := CreateDIBSection(gw, gh)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
; Set the smoothing mode to antialias = 4
Gdip_SetSmoothingMode(G, 4)
Gdip_SetInterpolationMode(G, 7)
; Draw the main gui rectangle
pBrush := Gdip_BrushCreateSolid(0xaa000000)
Gdip_FillRectangle(G, pBrush, 0, 0, gw, gh)
Gdip_DeleteBrush(pBrush)
; ; Draw the "close" x and the "minimize" line
cb_x := gw - 25
cb_y := 0
cb_w := 25
cb_h := 25
pPen := Gdip_CreatePen(0xffffffff, 2)
Gdip_DrawLine(G, pPen, cb_x+6, cb_y+6, cb_x+cb_w-6, cb_y+cb_h-6)
Gdip_DrawLine(G, pPen, cb_x+cb_w-6, cb_y+6, cb_x+6, cb_y+cb_h-6)
Gdip_DeletePen(pPen)
regions .= ",cb"
; Draw the screenshots onto the main gui rectangle
Loop, % windowcount
Gdip_DrawImage(G, pBitmap%A_Index%, wx%A_Index%, wy%A_Index%, ww%A_Index%, wh%A_Index%, 0, 0, w%A_Index%, h%A_Index%)
; Update the window
UpdateLayeredWindow(hgui1, hdc, (A_ScreenWidth-gw)//2, (A_ScreenHeight-gh)//2, gw, gh)
; Catch left-buttonclick messages
OnMessage(0x201, "WM_LBUTTONDOWN")
; Set the timer to check if the mouse is over the close button
SetTimer, CheckPos, 10
return
test:
return
AltTabList(exclusions)
{
static WS_EX_CONTROLPARENT = 0x10000, WS_EX_APPWINDOW = 0x40000, WS_EX_TOOLWINDOW = 0x80, WS_DISABLED = 0x8000000, WS_POPUP = 0x80000000
WinGet, wlist, List
Loop, %wlist%
{
hWnd := wlist%A_Index%
if hwnd in %exclusions%
continue
WinGetTitle, wtitle, ahk_id %hWnd%
WinGet, wstyle, Style, ahk_id %hWnd%
WinGet, wexstyle, ExStyle, ahk_id %hWnd%
WinGetClass, wclass, ahk_id %wid%
hParent := DllCall( "GetParent", uint, hWnd )
WinGet, parentstyle, Style, ahk_id %hParent%
If (wstyle & WS_DISABLED) ; ignore disabled windows
or (!wtitle) ; and titleless windows
or (wexstyle & WS_EX_TOOLWINDOW) ; and toolwindows
or ( (wexstyle & WS_EX_CONTROLPARENT) ; and PSPad child windows
and !(wstyle & WS_POPUP) ; (presumably other MDI children
and !(wclass = "#32770") ; as well)
and ! (wexstyle & WS_EX_APPWINDOW) ) ;
or ( (wstyle & WS_POPUP) ; and Notepad find window
and (hParent)
and (parentstyle & WS_DISABLED) = 0 )
continue
alttablist .= hWnd "," ; Add the hWnd to the list
}
StringTrimRight, alttablist, alttablist, 1
return alttablist
}
WM_LBUTTONDOWN(wParam, lParam, msg, hWnd)
{
global
if (oldrgn="cb")
exitapp
if (oldrgn+0)
{
msgbox % "you clicked:`n" %oldrgn%_title
}
}
CheckPos:
; Get mouse location
MouseGetPos, x, y, hwnd
if (hwnd != hgui1)
return
WinGetPos, wx, wy, , , ahk_id %hgui1%
x -= wx, y -= wy
; Is the mouse over a predefined region?
rgn := 0
loop, parse, regions, `,
if (x >= %A_LoopField%_x) and (x <= %A_LoopField%_x + %A_LoopField%_w) and (y >= %A_LoopField%_y) and (y <= %A_LoopField%_y + %A_LoopField%_h)
rgn := A_LoopField
; If the region hasn't changed, don't do anything
if (rgn = oldrgn)
return
if (rgn = "cb") or (oldrgn = "cb") ; the close button
{
Gdip_SetCompositingMode(G, 1)
Gdip_SetClipRect(G, cb_x, cb_y,cb_w, cb_h)
; Draw the new close rectangle
pBrush := Gdip_BrushCreateSolid( (rgn = "cb") ? 0xaa222222 : 0xaa000000)
Gdip_FillRectangle(G, pBrush, 0, 0, gw, gh)
Gdip_DeleteBrush(pBrush)
Gdip_SetCompositingMode(G, 0)
; Draw the "close" x
pPen := Gdip_CreatePen((rgn = "cb") ? 0xffff6600 : 0xffffffff, 2)
Gdip_DrawLine(G, pPen, cb_x+6, cb_y+6, cb_x+cb_w-6, cb_y+cb_h-6)
Gdip_DrawLine(G, pPen, cb_x+cb_w-6, cb_y+6, cb_x+6, cb_y+cb_h-6)
Gdip_DeletePen(pPen)
}
if (oldrgn+0) ; the region we changed from is a screenshot slot
{
Gdip_SetCompositingMode(G, 1)
pBrush := Gdip_BrushCreateSolid(0xaa000000)
; redraw the window title display area
Gdip_SetClipRect(G, 0, 250, gw, 100)
Gdip_FillRectangle(G, pBrush, 0, 0, gw, gh)
; redraw the background for this slot
Gdip_SetClipRect(G, %oldrgn%_x, %oldrgn%_y, %oldrgn%_w, %oldrgn%_h)
Gdip_FillRectangle(G, pBrush, 0, 0, gw, gh)
Gdip_DeleteBrush(pBrush)
Gdip_SetCompositingMode(G, 0)
; redraw the screenshot
Gdip_DrawImage(G, pBitmap%oldrgn%, wx%oldrgn%, wy%oldrgn%, ww%oldrgn%, wh%oldrgn%, 0, 0, w%oldrgn%, h%oldrgn%)
}
if (rgn+0) ; the region we changed to is a screenshot slot
{
Gdip_SetCompositingMode(G, 1)
; redraw slot background to the hover state
Gdip_SetClipRect(G, %rgn%_x, %rgn%_y, %rgn%_w, %rgn%_h)
pBrush := Gdip_BrushCreateSolid(0xaa222222)
Gdip_FillRectangle(G, pBrush, 0, 0, gw, gh)
Gdip_DeleteBrush(pBrush)
Gdip_SetCompositingMode(G, 0)
; redraw the screenshot
Gdip_DrawImage(G, pBitmap%rgn%, wx%rgn%, wy%rgn%, ww%rgn%, wh%rgn%, 0, 0, w%rgn%, h%rgn%)
; write the window title to the gui
Gdip_SetClipRect(G, 0, 250, gw, 100)
Options = x10p y290 w80p Centre caaff6600 r4 s25 Bold
Gdip_TextToGraphics(G, %rgn%_title, Options, "Calibri", gw, gh)
}
; Update the window, unset the clipping region, and remember the last region visited
UpdateLayeredWindow(hgui1, hdc)
Gdip_ResetClip(G)
oldrgn := rgn
return
Exit:
; Clean everything up
Loop, % windowcount
Gdip_DisposeImage(pBitmap%A_Index%)
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_Shutdown(pToken)
ExitApp