I have corrected and cleaned up some things in my code, and now the border which shows 'focused' thumbnail looks very cool. I don't think it slows down anything, other than a millisec or so. I'd be happy if someone looked at it. I've been working with the version Da0nlyfreez posted. I think it could be inserted fairly easily into any version.
There are 'phantom' windows, I haven't investigated why, maybe they are excluded, maybe just dropped. But upon activation, the active window is now usually the focused thumbnail. When it is not, I *think* it is due to trying to focus on a thumbnail which does not exist.
Either type of selection (click or press enter) works fine, all the time, as far as I can see. I could add shift-tab... whatever. I may add back the window numbers, but not sure they are necessary.
Thanks for hearing me.
Code:
#SingleInstance force
#NoEnv
SetBatchLines -1
SetWinDelay 0
OnExit handle_exit
; config
fade_delay = 0 ; msec to wait for next animation frame
fade_steps = 4 ; steps in animation, 2 = fast, 10 = slow (smooth)
fadeout_steps = 4
min_w = 110 ; min width of windows to be shown
min_h = 110 ; min height of windows to be shown (hides taskbar etc)
trans_color = #998877
focus_color = 0xcc6666 ; color of focused thumbnail - must contrast with background
translevel = 255 ; transparency of end of animation
translevel_start = 0 ; transparency of start of animation (see offscreen painting)
translevel_stop_solid= 0 ; 0/1 turn off transparency at end of fade_in to hide background
scale_thumb_space = 1
live_repaint = 500 ;1000 ; msec repaint the windows in expose mode, 0 = off
;init values
gui_active = 0 ; gui is hidden at startup
pics_added = 0 ; onclicks are not yet registered
Return
+F12::
handle_exit:
Gosub destroy_gui
ExitApp
GuiEscape:
Goto destroy_gui
Return
!r::Reload
F12::
MButton::
If gui_active = 1 ; toggle off if already active
GoTo destroy_gui
WinGet prev_active_id, id, A
gui_active = 1 ; show gui
GoSub calculate_sizes ; sets "cols" , "rows"
If (num_win = "" or num_win = 1) ; do nothing if no active windows
Return ; or only 1
GoSub create_wall ; create bgwindow with current wallpaper
GoSub create_gui ; prepare gui to draw onto it
GoSub draw_thumbnails
GoSub fade_in
SetTimer draw_thumbnails, %live_repaint%
GoSub, create_overlay
Return
create_overlay:
gui, 4:Destroy
gui, 4:+AlwaysOnTop -Caption +ToolWindow
gui, 4:Color, %focus_color%
gui, 4:+LastFound
WinSet, Region, 0-0 w0 h0
gui, 4:Show, x0 y0 w%a_ScreenWidth% h%a_ScreenHeight%
olayID := WinActive()
if !SelItem
SelItem := 1
change_focus:
i := SelItem
xx1 := thumb_x_%i%
yy1 := thumb_y_%i%
xx2 := thumb_x_%i%+thumb_w_%i%
yy2 := yy1
xx3 := xx2
yy3 := thumb_y_%i%+thumb_h_%i%
xx4 := xx1
yy4 := yy3
xx6 := xx1-3
yy6 := yy1-3
xx7 := xx2+3
yy7 := yy2-3
xx8 := xx3+3
yy8 := yy3+3
xx9 := xx1-3
yy9 := yy3+3
WinSet, Region, %xx1%-%yy1% %xx2%-%yy2% %xx3%-%yy3% %xx4%-%yy4% %xx1%-%yy1% %xx6%-%yy6% %xx7%-%yy7% %xx8%-%yy8% %xx9%-%yy9% %xx6%-%yy6%, ahk_id %olayID%
return
#IfWinExist, Expose
Tab::
WinSet, Region, 0-0 w0 h0, ahk_id %olayID%
SelItem++
tooltip, SelItem %SelItem%`nnum_win %num_thumbs%
If ( SelItem > num_thumbs )
SelItem := 1
GoSub, change_focus
return
Enter::
clicked_on_pic_id := task_ids_%SelItem%
clicked_on_pic := true
goto, destroy_gui
#IfWinExist
create_wall:
RegRead, wall_path, HKCU, Control Panel\Desktop, Wallpaper
Gui, 2:Destroy
Gui, 2:+AlwaysOnTop -Caption
Gui, 2:Add, Picture, gClickedOnWall x0 y0 w%A_ScreenWidth% h%A_ScreenHeight%
, %wall_path%
Gui, 2:Show, Hide NA x0 y0 w%A_ScreenWidth% h%A_ScreenHeight%
Return
calculate_sizes:
num_win := get_wins()
cols := ceil( sqrt( num_win ))
rows := ceil( sqrt( num_win ))
If (cols * (rows-1) >= num_win )
rows--
thumb_w := A_ScreenWidth // cols
thumb_h := A_ScreenHeight // rows
ratio_of_screen := A_ScreenWidth / A_ScreenHeight * rows / cols
Return
draw_thumbnails:
pos_x := 0
pos_y := 0
win_now := 0
task_ids =
Loop %ids% ; ids has been set up in calculate_sizes
task_ids := task_ids "," ids%a_index%
Sort task_ids, D, ; keep positions of thumbnails
Loop Parse, task_ids, `,
{
task_id = %A_LoopField%
WinGetTitle title, ahk_id %task_id%
WinGetPos,,, w, h, ahk_id %task_id%
If (!is_excluded_win() ) { ; small windows not shown (eg taskbar)
win_now++
task_ids_%win_now% := task_id ; for activation
If ! SelItem
if ( task_id = prev_active_id )
SelItem := win_now
if !pics_added
Gui Add, Pic, gActivateWin x%pos_x% y%pos_y% w%thumb_w% h%thumb_h% vPic%win_now% ; register "onclick"
sleep 10 ; prevent missing windows
pwin := DllCall("PrintWindow", UInt,task_id, UInt,hdc_buffer, UInt,0)
ratio_of_win := w / h
if ( scale_thumb_space ) {
if ( ratio_of_win < ratio_of_screen ) { ; tall window
thumb_h2 := thumb_h
thumb_w2 := thumb_w * ratio_of_win / ratio_of_screen
} Else { ; wide window
thumb_w2 := thumb_w
thumb_h2 := thumb_h / ratio_of_win * ratio_of_screen
}
}
x1 := pos_x + (thumb_w - thumb_w2 ) / 2
y1 := pos_y + (thumb_h - thumb_h2 ) / 2
x1+=2
y1+=2
thumb_w2-=4
thumb_h2-=4
thumb_x_%win_now% := x1
thumb_y_%win_now% := y1
thumb_w_%win_now% := thumb_w2
thumb_h_%win_now% := thumb_h2
DllCall("gdi32.dll\StretchBlt"
, UInt, hdc_frame
, Int, x1
, Int, y1
, Int, thumb_w2
, Int, thumb_h2
, UInt, hdc_buffer
, Int, 0
, Int, 0
, Int, w
, Int, h
, UInt, 0xCC0020) ; SRCCOPY
pos_x += thumb_w
if ( pos_x >= A_ScreenWidth ) {
pos_x :=0
pos_y += thumb_h
}
} ; If !excluded
} ; Loop task_ids
pics_added := 1
num_thumbs := win_now ; cannot find this anywhere else just now
Return
is_excluded_win() {
Global
Return w < min_w or h < min_h or title ="Expose" or title =""
}
fade_in:
Loop %fade_steps% {
intrans := A_Index * translevel / fade_steps
WinSet, TransColor, %trans_color% %intrans%, ahk_id %hw_frame%
Sleep %fade_delay%
}
If translevel_stop_solid
WinSet Transparent, off
intrans =
Return
fade_out:
Loop %fadeout_steps% {
outtrans := translevel - A_Index * translevel / fadeout_steps
WinSet, TransColor, %trans_color% %outtrans%, ahk_id %hw_frame%
Sleep %fade_delay%
}
outtrans =
Return
get_wins() {
Local x
WinGet ids, list,,,Program Manager ; all active windows-tasks (processes)
Loop %ids% {
task_id := ids%a_index% ; id of this window
WinGetTitle title, ahk_id %task_id%
WinGetPos,,, w, h, ahk_id %task_id%
If !is_excluded_win() ; small windows not shown (eg taskbar)
x++
}
Return x
}
; *** Create Expose Gui
create_gui:
Gui Destroy ; clear old stuff if expose hotkey is running in background
Gui +AlwaysOnTop +LastFound
Gui Color, %trans_color%, 0xcc4444
WinSet, TransColor, %trans_color%
Gui -Caption
WinSet, Transparent, %translevel_start%
Gui Show, w%A_ScreenWidth% h%A_ScreenHeight% x0 y0, Expose
WinGet hw_frame, id, Expose
hdc_frame := DllCall( "GetDC"
, UInt, hw_frame )
DllCall( "gdi32.dll\SetStretchBltMode"
, "uint", hdc_frame
, "int", 4 ) ; Halftone better quality with stretch
hdc_buffer := DllCall("gdi32.dll\CreateCompatibleDC"
, UInt, hdc_frame) ; buffer
hbm_buffer := DllCall("gdi32.dll\CreateCompatibleBitmap"
, UInt,hdc_frame
, Int,A_ScreenWidth
, Int,A_ScreenHeight)
DllCall( "gdi32.dll\SelectObject"
, UInt,hdc_buffer
, UInt,hbm_buffer)
pics_added := 0
Return
; *** Actions on selection made
; on click on picture
ActivateWin:
StringReplace pos, A_GuiControl, Pic ; find the clicked pic-id
clicked_on_pic_id := task_ids_%pos%
clicked_on_pic = true
; -- continue
; on click on wallpaper
ClickedOnWall:
WinActivate, ahk_id %hw_frame%
; -- continue
; fade out
destroy_gui:
SetTimer draw_thumbnails, OFF
Gui, 4:Destroy
GoSub fade_out
Gui, 2:Destroy
Gui, 1:Destroy
gui_active := 0
pics_added := 0
DllCall("gdi32.dll\DeleteObject", UInt,hbm_buffer)
DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdc_buffer)
If clicked_on_pic_id != "" and if clicked_on_pic = true
WinActivate ahk_id %clicked_on_pic_id%
Else
WinActivate ahk_id %prev_active_id%
SelItem = 0 ; prepare to show focus
clicked_on_pic_id =
clicked_on_pic = false
Return
; /*** Actions on selection made