AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

real expose clone
Goto page 1, 2, 3 ... 18, 19, 20  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  

Would you like to see this script rewritten and easy to understand ?
No, I dont care, i just use the executable
5%
 5%  [ 1 ]
Yes, as this script is popular some may learn from it
94%
 94%  [ 16 ]
Total Votes : 17

Author Message
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sat Sep 30, 2006 11:16 pm    Post subject: real expose clone Reply with quote



Update: This script is also part of Activ'Aid (quite a while already) and they have even added some Configuration-Gui. The posted version there has bugs. but its interesting to be in an Article on Heise.de /CT.

Version on Heise.de

Removed link to Wiki, as nobody uses it.

as suggested by majkinetor, i combined some of my scripts and built a real expose clone, which shows all your windows in miniature and if you click on it it activates this window. compared to the other exposescript here, the windows are not moved or resized, but the window is "zoomed".
like other expose clones this also supports fancy animation, or better fade_in and fade_out. (animation would be possible but its to complicated for me now). you can configure this script in the "read_config" function. (transparency and speed of fade, simply set fade_steps to 1 to turn it off).

i tried to keep the script short, but its the nature of this application that it gets a bit longer. i didnt reuse the other expose script, as i wanted to figure it out myself but borrowed one or two ideas to make it shorter.

you could even have livepreviews if you call "draw_thumbnails:" in a timer function, but for me its enough to draw it only once. (less cpu)

use mbutton or win-tab to activate it. (pressing the same key while expose is running will end it and do no modification to any window)
activate the window by clicking on the replica.

important: if you miss windows then change min_w and min_h or change the function is_excluded_win()

You should use the code posted here if you want latest version. The downloads may not be latest, but sometimes it's good to have them.
download:
Show Directory all Versions
expose-20090916.ahk (script)
expose-20090914.ahk (script)
expose-20090912.ahk (script)
expose-20090914.exe (compiled exe) activate with middle-mouse-click or F12-Key
expose-20090912.exe (compiled exe) activate with middle-mouse-click or F12-Key

Version 0.1: initial version
...
Version 1.20: copied from Post on Page 17.
Version 1.20090912 : Bugfixfor positioning of zoomed thumbnail, max zoom to 100% of real window (maximized), zoom can be triggered now simply by scrolling the wheel over the active window. to turn off simply zoom to 100% (of thumb) again. (no rightclick needed this way) its more seamless.

* Nobody follows Roadmap, so lets just skip the plans Wink

Code:
;v1.20090916 -- expose.ahk - Thumbnails of windows over the working area, active thumbnails when no zoom,                                            ;zoomed window means redraw only zoomed window
; new minimized windows + hotkeys

OnExit handle_exit
#SingleInstance Force
#NoEnv
SetBatchLines -1
SetWinDelay 0               ; larger values also fail under heavy load, changing windows
Process Priority,,Above Normal
CoordMode Mouse, Relative

Main:
  Gosub, Read_Keymapping
  Gosub, Read_Config
  Gosub, Detect_Screensize
  Gosub, Create_Gui
  Gosub, Create_Buffers
  ; wait for key/mouse
Return

Read_Keymapping:
   Hotkey, #TAB,      Window_Choose
   Hotkey, ^q,     Window_Choose
   ;Hotkey, ^+q,   Current_App_Choose
   Hotkey, ^!q,   Window_Choose_No_Minimize
   ;Hotkey, ^!+q,   Current_App_No_Minimize

   Hotkey, IfWinActive, »Expose«
      Hotkey, #TAB    ,      Window_Activate
      Hotkey, MButton ,     Window_Activate
      Hotkey, LButton ,      Window_Activate
      HotKey, RButton ,     Window_Preview
      Hotkey, Esc     ,        hide_gui
      Hotkey, WheelUp ,    Handle_Zoom
      Hotkey, WheelDown, Handle_Zoom
      Hotkey, +MButton ,   handle_exit ; panik-key
      Hotkey, #F12 ,          Debug_Info
Return

Read_Config:
   min_w                        = 110  ; min width of windows to be shown
   min_h                        = 110  ; min height of windows to be shown (hides taskbar etc)
   scale_thumb_space    = 1    ; scale thumbnails to best fit to box?
   live_redraw                 = 1   ; 1/0 = Yes/No
   time_gap                   = 100   ; ms, time left for others after each thumbnail draw
   thumb_border             = 1   ; 1 for gap between thumbnail  s
   animate_in_delay       = 5
   animate_in_steps       = 5
   animate_out_delay     = 5
   animate_out_steps     = 5
   show_taskbar             = 1
   main_monitor   = 1 ; or 2 or 3 if you like
   ;fade_in_steps           = 5
   ;fade_in_delay           = 5
   ;fade_out_steps         = 5
   ;fade_out_delay         = 50
   quality_low                = 3 ; allowed: 1 (terrible) , 3 (accepatable) 4 (good = slow)
   quality_high               = 4 ; allowed: 1 (terrible) , 3 (accepatable) 4 (good = slow)
   BackGroundColor       = 004E98
   count := 0
   counter := 0
   zoom_preview = 0.8
   zoom_maximized = 1 ; // 1=on ; 0=off ; allow to zoom more than real size
   do_zoom := 0  ; // off at first
   old_ids_count =  -1 ;
   show_minimized := 1 ;
   minimized_counter := 0 ;
Return

Debug_Info:
ListLines

Window_Hidden() {
   global
   Return w < min_w or h < min_h or title ="»Expose«" or title =""
}

Handle_Zoom:
   If (do_zoom = 0 and ( A_ThisHotKey = "WheelUp" or A_ThisHotKey = "^+Up" ))
   {
      zoom_preview = 0 ; start at 100% to make it look seemless
      gosub Window_Preview ; activate Preview by Scrolling , eg. zooming
   }

   If (do_zoom = 1 and zoom_preview =0 and ( A_ThisHotKey = "WheelDown" or A_ThisHotKey = "^+Down" ))
      gosub Window_Preview ; deactivate zoom


   If (zoom_preview < 4 and ( A_ThisHotKey = "WheelUp" or A_ThisHotKey = "^+Up" ))
      zoom_preview += 0.05         ; sqrt(sqrt(2))
   If (zoom_preview >  0 and ( A_ThisHotKey = "WheelDown" or A_ThisHotKey = "^+Down" ))
      zoom_preview -= 0.05
   TrayTip,,% "Zoom = " Round(100*(1+zoom_preview)) "%"
Return

In(x,a,b) {                      ; closest number to x in [a,b]
   IfLess x,%a%, Return a
   IfLess b,%x%, Return b
   Return x
}


Detect_ScreenSize:

    ; Copy bounds of all monitors to an array.
    SysGet, mc, MonitorCount
    Loop, %mc%
        SysGet, mon%A_Index%, MonitorWorkArea, %A_Index%
   
  Th=0
  Tw=0
  Ty=0
  Tx=0

 
  if show_taskbar and mc = 1
  {   
   WinGetPos,Tx,Ty,Tw,Th,ahk_class Shell_TrayWnd,,,
  }
   ; Default
   WorkArea_Top    :=      ( Tw > Th  and  Tx = 0  and  Ty = 0) * Th
   WorkArea_Left   :=      ( Tw < Th  and  Tx = 0  and  Ty = 0) * Tw
   WorkArea_Height := A_ScreenHeight - ( Tw > Th  ) * Th
   WorkArea_Width  := A_ScreenWidth  - ( Tw < Th  ) * Tw
 
  if show_taskbar and mc > 1
  {   
    md := main_monitor ; // change this where you want to show your thumbnails Number of Monitor
    ; fix for dual monitor
    WorkArea_Top    := mon%md%Top
    WorkArea_Left   := mon%md%Left
    WorkArea_Width  := mon%md%Right - mon%md%Left
    WorkArea_Height := mon%md%Bottom - mon%md%Top
  }

 
 ; TrayTip,,% "Taskbar = " Tx " " Ty " " Tw " " Th " " A_ScreenWidth " " A_ScreenHeight " mc: " mc
  ; if Ty > A_ScreenHeight then Taskbar is "below" mon1
  ; if Ty < 0 Tastbar is above mon1
Return

Create_Gui:
  Gui +AlwaysOnTop -Caption  +Toolwindow +Owner +LastFound
  ;Gui Color, %BackGroundColor%
 
  ; create blank screens for non-main monitor
  ; SysGet, mc, MonitorCount
  ;   Loop, %mc%
  ;  {   
  ;    SysGet, mon%A_Index%, MonitorWorkArea, %A_Index%
  ;    md := A_Index
  ;    WorkArea_Top    := mon%md%Top
  ;    WorkArea_Left   := mon%md%Left
  ;    WorkArea_Width  := mon%md%Right - mon%md%Left
  ;    WorkArea_Height := mon%md%Bottom - mon%md%Top
  ;
  ;    Gui +AlwaysOnTop -Caption  +Toolwindow +Owner +LastFound
  ;    Gui Color, %BackGroundColor%
  ;    Gui Show,  Hide w%WorkArea_Width% h%WorkArea_Height% x%WorkArea_Left% y%WorkArea_Top%, »Expose%A_Index%«
  ;  }

   ; Last
   Gui Show, Hide  w%WorkArea_Width% h%WorkArea_Height% x%WorkArea_Left% y%WorkArea_Top%, »Expose«

  ;Gui, Add, Pic, x0 y0 w%WorkArea_Width% h%WorkArea_Height%, c:\test.bmp
  DetectHiddenWindows ON
  WinGet Expose_ID , ID, »Expose«
  WinGet Desktop_ID, ID, Program Manager
  DetectHiddenWindows OFF
Return

Create_Buffers:
  hdc_frontbuffer  := GetDC( Expose_ID )

  hdc_printwindow := CreateCompatibleDC(    hdc_frontbuffer)
  hbm_printwindow := CreateCompatibleBitmap(hdc_frontbuffer,WorkArea_Width,WorkArea_Height)
  hbm_old         := SelectObject(          hdc_printwindow,hbm_printwindow)

  hdc_thumbnails  := CreateCompatibleDC(    hdc_frontbuffer)
  hbm_thumbnails  := CreateCompatibleBitmap(hdc_frontbuffer,WorkArea_Width,WorkArea_Height)
  hbm_old         := SelectObject(          hdc_thumbnails,hbm_thumbnails)

  hdc_backbuffer  := CreateCompatibleDC(    hdc_frontbuffer)
  hbm_backbuffer  := CreateCompatibleBitmap(hdc_frontbuffer,WorkArea_Width,WorkArea_Height)
  hbm_old         := SelectObject(          hdc_backbuffer,hbm_backbuffer)

  hdc_desktop     := CreateCompatibleDC(    hdc_frontbuffer)
  hbm_desktop     := CreateCompatibleBitmap(hdc_frontbuffer,WorkArea_Width,WorkArea_Height)
  hbm_old         := SelectObject(          hdc_desktop,hbm_desktop)

  Gui Show
  PaintDesktop( hdc_frontbuffer ) ; 0=window, 1=Child(no toolbars)
  BitBlt(hdc_desktop     , 0, 0, WorkArea_Width, WorkArea_Height
      ,  hdc_frontbuffer , 0, 0 ,0xCC0020) ; SRCCOPY
  BitBlt(hdc_thumbnails  , 0, 0, WorkArea_Width, WorkArea_Height
      ,  hdc_frontbuffer , 0, 0 ,0xCC0020) ; SRCCOPY
  Gui Hide

Return

Window_Choose:
   WinGet ActiveID, ID, A
   show_minimized := 1
   gosub fill_mini_List

   SetTimer Window_Choose_Thread, 0       ; new thread to make thumbnail draws interruptible
Return

Window_Choose_No_Minimize:
   WinGet ActiveID, ID, A
   show_minimized := 0

   SetTimer Window_Choose_Thread, 0       ; new thread to make thumbnail draws interruptible
Return

;Current_App_Choose:
;   WinGet, activeProcessName, ProcessName, A
;   show_minimized := 1
;   gosub fill_mini_list_current         ; I'm sure there's an easier way, but too lazy and unskilled :P
;   
;   SetTimer Window_Choose_Thread, 0       ; new thread to make thumbnail draws interruptible
;return

Window_Choose_Thread:
   Stop_Drawing  =
   yield         := time_gap        ; yield time to other tasks after each thumbnail drawn
   SetTimer Window_Choose_Thread, OFF     ; run once
   GoSub Window_Info           ; list window IDs, sizes, etc.
   Gosub Animate_In

  GoSub Draw_Thumbnails
Return

Window_Activate:
   Stop_Drawing = 1
   MouseGetPos X, Y
   pos := 1 + X*cols//WorkArea_Width + Y*rows//WorkArea_Height * cols
   task_id := task_ids_%pos%

   If (pos <= num_win and X >= 0 and X <= WorkArea_Width and Y >= 0 and Y <= WorkArea_Height)
   {
      Gosub Animate_Out
      WinActivate(task_id)                 ; activate selected window
      Gosub fade_out
   }

   if ( show_minimized)
      gosub restore_position

   Gui_Hide()
Return

WinActivate(ID) {
   WinGet ,ActiveID2, ID, A
   if ActiveID2 <> ID
       WinActivate ahk_id %ID%
}

Window_Info:
   WinGet ids, list,,,Program Manager      ; all active windows-tasks (processes)
   task_info =
   num_win = 0
 
   Loop %ids%
   {
   task_id := ids%A_Index%              ; id of this window
   WinGetClass class, ahk_id %task_id%
   WinGetTitle title, ahk_id %task_id%
   WinGetPos,,, w, h, ahk_id %task_id%
   If Window_Hidden()                 ; small windows not shown (e.g. taskbar)
      Continue
   num_win++
   task_info := task_info class "|" ids%A_Index% "|" w "|" h ","
   TrayTip, task_info
   }
   
   StringTrimRight task_info, task_info, 1 ; remove last comma
   Sort task_info, D,                      ; keep positions of thumbnails
   cols := ceil(sqrt(num_win))
   rows := ceil(sqrt(num_win))
 
   If (cols*(rows-1) >= num_win)           ; minimize table size
       rows--
   
   thumb_w := WorkArea_Width  // cols
   thumb_h := WorkArea_Height // rows
   ratio_of_screen := WorkArea_Width / WorkArea_Height * rows / cols
 
   Loop Parse, task_info, `,               ; task_info has been set up in get_wins()
   {
      StringSplit z, A_LoopField, |        ; separate ID, w, h
      task_ids_%A_Index% := z2             ; needed for activation
      if ( z2 = ActiveID )
      pos = %A_Index%
     w%A_Index% := z3                     ; w
      h%A_Index% := z4                     ; h
      ratio_of_win := z3 / z4              ; w/h
      If ( scale_thumb_space  )  {
         If (ratio_of_win < ratio_of_screen) { ; tall window
            thumb_h%A_Index% := thumb_h - thumb_border
            thumb_w%A_Index% := Floor(thumb_w * ratio_of_win / ratio_of_screen) - thumb_border
         } Else {                              ; wide window
            thumb_w%A_Index% := thumb_w - thumb_border
            thumb_h%A_Index% := Floor(thumb_h * ratio_of_screen / ratio_of_win) - thumb_border
         }
      } Else {
         thumb_w%A_Index% := z3//cols - 2*thumb_border
         thumb_h%A_Index% := z4//cols - 2*thumb_border  ; cols >= rows, keep aspect ratio of window
      }
   
     if ( thumb_w%A_Index% > w%A_Index% or thumb_h%A_Index% > h%A_Index% )
     {
        thumb_w%A_Index% := w%A_Index%
         thumb_h%A_Index% := h%A_Index%
      }
   }
Return

Draw_Thumbnails:

   
    If ( Stop_Drawing )
   {
      tooltip,
           Return
   }

   
   SetStretchBltMode(hdc_thumbnails,quality_high) ; 3: Lower quality at 1st draw
 
   WinGet ids_count, list,,,Program Manager      ; all active windows-tasks (processes)
   if ( old_ids_count <> ids_count )
      gosub Window_Info   ; detect if windows were added in expose mode
   
   ; layout changed full refresh (start with empty desktop)
   if ( cols <> old_cols or rows <> old_rows)
       BitBlt( hdc_frontbuffer, 0, 0, WorkArea_Width, WorkArea_Height
           , hdc_desktop, 0, 0 , 0xCC0020) ; SRCCOPY
       BitBlt( hdc_thumbnails, 0, 0, WorkArea_Width, WorkArea_Height
           , hdc_desktop, 0, 0 , 0xCC0020) ; SRCCOPY
   
   ; clear "now empty" places , only needed when less, more are filled automatically
   gaps := old_num_win - num_win
    if ( gaps )
   {
     loop %gaps%
     {
        a_index2 := num_win + gaps
       pos_x := thumb_w * Mod(A_Index2-1,cols)
       pos_y := thumb_h * ((A_Index2-1)//cols)
 
       BitBlt( hdc_thumbnails, pos_x, pos_y, thumb_w, thumb_h
              , hdc_desktop,    pos_x, pos_y ,0xCC0020) ;
   
        BitBlt( hdc_frontbuffer, pos_x, pos_y, thumb_w, thumb_h
              , hdc_thumbnails,  pos_x, pos_y ,0xCC0020) ;
      }   
   }

    old_ids_count := ids_count
    old_rows := rows
    old_cols := cols
   old_num_win := num_win

    Loop %num_win%  {                       ; task_ids, dims have been set up in win_list
     ;  Sleep %yield%                        ; CPU cycles to other tasks @ frequent redraw
      If Stop_Drawing
         Break
   
      pos_x := thumb_w * Mod(A_Index-1,cols)
      pos_y := thumb_h * ((A_Index-1)//cols)
     
      PrintWindow( task_ids_%A_Index%, hdc_printwindow, 0) ; 0=window, 1=Child(no toolbars)
   
      BitBlt( hdc_thumbnails, pos_x , pos_y, thumb_w, thumb_h
            , hdc_desktop   , pos_x , pos_y ,0xCC0020) ; Clear slot . (could load Image here ?)
   
      ; prevent flicker with backbuffer , store it in hdc_thumbnails for later reuse!
      StretchBlt( hdc_thumbnails , pos_x + ( thumb_w - thumb_w%A_Index% ) // 2
                            , pos_y + ( thumb_h - thumb_h%A_Index% ) // 2     
                            , thumb_w%A_Index%
                          , thumb_h%A_Index%
             ,hdc_printwindow, 0, 0, w%A_Index%, h%A_Index% ,0xCC0020) ; SRCCOPY
 
        BitBlt( hdc_frontbuffer, pos_x , pos_y , thumb_w, thumb_h
             ,hdc_thumbnails,  pos_x , pos_y ,0xCC0020) ; Clear slot . (could load Image here ?)
   }

 
   MouseGetPos X, Y
      pos := 1 + X*cols//WorkArea_Width + Y*rows//WorkArea_Height * cols
 
   if pos > 0 ; dual monitor !
     winid := task_ids_%pos%
   
   WinGetTitle title, ahk_id %winid%

   tooltip, %title% ; + %old_pos2% + %pos%

   ; force Gui to foreground, maybe some windows have been opened or closed
 ; Gui_Show()
     
    If live_redraw
    {
       Gosub draw_active
       Return
      }
Return

Window_Preview:

   do_zoom := 1 - do_zoom ; toggle state
   BitBlt(hdc_frontbuffer, 0, 0, WorkArea_Width, WorkArea_Height
             ,  hdc_thumbnails, 0, 0 ,0xCC0020) ; SRCCOPY
   
return

draw_active:

  ; are gui windows also showing up and make a wrong ids_count ?
   WinGet ids_count, list,,,Program Manager      ; all active windows-tasks (processes)
   if ( old_ids_count <> ids_count ) {
      gosub,  Window_Info   ; detect if windows were added in expose mode
      gosub,  Draw_Thumbnails ;
      return
  }
  ; we need to check here if there are new windows, or windows missing and refresh the whole
  ; thing accordingly. maybe brutforce, destroy gui and paint as we have clicked "Window_Choose"
  ; only skip animation

  zoom :=  zoom_preview

  sleep %yield%                        ; CPU cycles to other tasks @ frequent redraw
       If ( Stop_Drawing )
   {
      tooltip,
           Return
   }
      MouseGetPos X, Y
      pos := 1 + X*cols//WorkArea_Width + Y*rows//WorkArea_Height * cols
 
      if pos > 0
       winid := task_ids_%pos%

      pos_x := thumb_w * Mod(pos -1,cols)
      pos_y := thumb_h * ((pos -1)//cols)

      A_Index2 = 0

      if pos > 0
         A_Index2 := pos

       task_id := task_ids_%A_Index2%
   
   diff_x := WorkArea_Left
   diff_y := WorkArea_Top
   diff_w := WorkArea_Width
   diff_h := WorkArea_Height


   WinGetPos, diff_x, diff_y, diff_w, diff_h , ahk_id %task_id%
   diff_x := X - diff_w // 2 ; -  ( WorkArea_Width - WorkArea_Left ) // 2

   diff_y := Y - diff_h // 2 ; - ( WorkArea_Height - WorkArea_Top ) // 2
   



   diff_x := diff_x - ( pos_x + (thumb_w - thumb_w%A_Index2% ) // 2 ) - WorkArea_Left
   diff_y := diff_y - ( pos_y + (thumb_h - thumb_h%A_Index2% ) // 2 ) - WorkArea_Top
   diff_w := diff_w - ( thumb_w%A_Index2% )
   diff_h := diff_h - ( thumb_h%A_Index2% )

   
      ; you can comment this line to get bit speed, acceptable
      BitBlt( hdc_backbuffer, 0, 0, WorkArea_Width, WorkArea_Height
              , hdc_thumbnails, 0, 0, 0xCC0020) ; SRCCOPY
      PrintWindow( task_ids_%A_Index2%, hdc_printwindow, 0) ; 0=window, 1=Child(no toolbars)
      SetStretchBltMode(hdc_backbuffer,quality_high) ; 3: Lower quality at 1st draw
      SetStretchBltMode(hdc_frontbuffer,quality_high) ; 3: Lower quality at 1st draw
   
     ; counter for debugging
     counter := counter +1

     if ( do_zoom = 1 ) {   
  ;   tooltip , Drawing Zoomed window %counter%

      x0 := pos_x + (thumb_w - thumb_w%A_Index2% ) // 2 - ( diff_w * zoom  ) // 2
      y0 := pos_y + (thumb_h - thumb_h%A_Index2% ) // 2 - ( diff_h * zoom  ) // 2
      w  := thumb_w%A_Index2% + diff_w * zoom
      h  := thumb_h%A_Index2% + diff_h * zoom

      if ( zoom_maximized ) {
   WinGetPos,,, w_temp, h_temp, ahk_id %task_id%
           
    if ( w > w_temp or h > h_temp )
         {
          w := w_temp
          h := h_temp
          zoom_preview1 := w / ( thumb_w%A_Index2% + diff_w ) - 0.05
          zoom_preview  := h / ( thumb_h%A_Index2% + diff_h ) - 0.05
          if (zoom_preview1 > zoom_preview)
            zoom_preview = zoom_preview1 ; use minimum
         }
     
          ; refresh, prevent flicker
          zoom := zoom_preview
     x0 := pos_x + (thumb_w - thumb_w%A_Index2% ) // 2 - ( diff_w * zoom  ) // 2
           y0 := pos_y + (thumb_h - thumb_h%A_Index2% ) // 2 - ( diff_h * zoom  ) // 2
           w  := thumb_w%A_Index2% + diff_w * zoom
          h  := thumb_h%A_Index2% + diff_h * zoom

        }

      ; if bottom/right of zoomed thumb is out move it back into view
      if x0 + w > WorkArea_Width
        x0 := WorkArea_Width - w

      if y0 + h > WorkArea_Height
        y0 := WorkArea_Height - h

      ; if top/left is out, move it back into view, can lead to clipping of bottom or right !
      if x0 < 0
   x0 := 0 ; // overflow

      if y0 < 0
        y0 := 0 ; // overflow


      StretchBlt( hdc_backbuffer
            , x0
                           , y0
                           , w
                           , h
                           , hdc_printwindow, 0, 0, w%A_Index2%, h%A_Index2% ,0xCC0020) ; SRCCOPY
      BitBlt(hdc_frontbuffer, 0, 0, WorkArea_Width, WorkArea_Height
               ,  hdc_backbuffer, 0, 0 ,0xCC0020) ; SRCCOPY
   
   }
else  {

     Loop %num_win%  {                       ; task_ids, dims have been set up in win_list
     ;  Sleep %yield%                        ; CPU cycles to other tasks @ frequent redraw
      If Stop_Drawing
         Break
   
      pos_x := thumb_w * Mod(A_Index-1,cols)
      pos_y := thumb_h * ((A_Index-1)//cols)
     
      PrintWindow( task_ids_%A_Index%, hdc_printwindow, 0) ; 0=window, 1=Child(no toolbars)
   
      BitBlt( hdc_thumbnails, pos_x , pos_y, thumb_w, thumb_h
            , hdc_desktop   , pos_x , pos_y ,0xCC0020) ; Clear slot . (could load Image here ?)
   
      ; prevent flicker with backbuffer , store it in hdc_thumbnails for later reuse!
      StretchBlt( hdc_thumbnails , pos_x + ( thumb_w - thumb_w%A_Index% ) // 2
                            , pos_y + ( thumb_h - thumb_h%A_Index% ) // 2     
                            , thumb_w%A_Index%
                          , thumb_h%A_Index%
             ,hdc_printwindow, 0, 0, w%A_Index%, h%A_Index% ,0xCC0020) ; SRCCOPY
 
        BitBlt( hdc_frontbuffer, pos_x , pos_y , thumb_w, thumb_h
             ,hdc_thumbnails,  pos_x , pos_y ,0xCC0020) ; Clear slot . (could load Image here ?)
     }
}

   
   MouseGetPos X, Y

   pos := 1 + X*cols//WorkArea_Width + Y*rows//WorkArea_Height * cols

   if ( pos > 0 )
     winid := task_ids_%pos%

   if ( pos < 0 )
     tooltip, %pos%

   WinGetTitle title, ahk_id %winid%

   if ( pos > 0 )
      tooltip, %title% ;  + %old_pos2% + %pos%

   

   If live_redraw
   {
      Gosub draw_active
      Return
   }

return

Animate_In:
    if !animate_in_steps
        return

    SetStretchBltMode(hdc_backbuffer, quality_low) ; 3: Lower quality at 1st draw
   
     A_index2 := pos
    pos_x := thumb_w * Mod(A_Index2-1,cols)
    pos_y := thumb_h * ((A_Index2-1)//cols)
 
    PrintWindow(task_ids_%A_Index2%,hdc_printwindow,0)
 
    task_id := task_ids_%A_Index2%
   WinGetPos, diff_x, diff_y, diff_w, diff_h , ahk_id %task_id%

    diff_x := diff_x - ( pos_x + (thumb_w - thumb_w%A_Index2% ) // 2 ) - WorkArea_Left
    diff_y := diff_y - ( pos_y + (thumb_h - thumb_h%A_Index2% ) // 2 ) - WorkArea_Top
    diff_w := diff_w - ( thumb_w%A_Index2% )
    diff_h := diff_h - ( thumb_h%A_Index2% )
   
   Loop %animate_in_steps%
   {
       sleep %animate_in_delay%
       zoom := 1 - ( A_Index / animate_in_steps )
     
        BitBlt( hdc_backbuffer, 0, 0, WorkArea_Width, WorkArea_Height
                 , hdc_thumbnails, 0, 0 , 0xCC0020) ; SRCCOPY
   
      if ( zoom = 0 )
         SetStretchBltMode(hdc_backbuffer, quality_high) ; 3: Lower quality at 1st draw
         StretchBlt( hdc_backbuffer , pos_x + (thumb_w - thumb_w%A_Index2% ) // 2 + diff_x * zoom     
                           , pos_y + (thumb_h - thumb_h%A_Index2% ) // 2 + diff_y * zoom     
                           , thumb_w%A_Index2% + diff_w * zoom   
                           , thumb_h%A_Index2% + diff_h * zoom
                           , hdc_printwindow, 0, 0, w%A_Index2%, h%A_Index2% ,0xCC0020) ; SRCCOPY
     
       if ( zoom = 0 )
         SetStretchBltMode(hdc_backbuffer, quality_low) ; 3: Lower quality at 1st draw
         Gui_Show()
         BitBlt(hdc_frontbuffer, 0, 0 ,WorkArea_Width ,WorkArea_Height
                 ,hdc_backbuffer , 0, 0 ,0xCC0020) ; SRCCOPY
   }

   old_cols := cols ; prevent full refresh on next draw
   old_rows := rows

Return

; should be reverse of animate in ? combine them ...
Animate_Out:
   
   if !animate_out_steps
         return

   A_index2 := pos
    pos_x := thumb_w * Mod(A_Index2-1,cols)
    pos_y := thumb_h * ((A_Index2-1)//cols)
 
    If (!(pos <= num_win and X >= 0 and X <= WorkArea_Width and Y >= 0 and Y <= WorkArea_Height))
       return

   ;SetStretchBltMode(hdc_frontbuffer,quality_low) ;
    PrintWindow( task_ids_%A_Index2%, hdc_printwindow ,0) ; get selected window
   
   ; clear
     BitBlt( hdc_backbuffer, pos_x, pos_y, thumb_w, thumb_h
              , hdc_desktop   , pos_x, pos_y, 0xCC0020) ; clear with desktopimage

   task_id := task_ids_%A_Index2%
   WinGetPos, diff_x, diff_y, diff_w, diff_h , ahk_id %task_id%

   diff_x := diff_x - ( pos_x + (thumb_w - thumb_w%A_Index2% ) // 2 ) - WorkArea_Left
   diff_y := diff_y - ( pos_y + (thumb_h - thumb_h%A_Index2% ) // 2 ) - WorkArea_Top
   diff_w := diff_w - ( thumb_w%A_Index2% )
   diff_h := diff_h - ( thumb_h%A_Index2% )

   SetStretchBltMode(hdc_backbuffer,quality_low) ; 3: Lower quality at 1st draw
    Loop %animate_out_steps%
   {
       sleep %animate_out_delay%
          zoom := ( A_Index / animate_out_steps )
       
      ; you can comment this line to get bit speed, acceptable
      BitBlt( hdc_backbuffer, 0, 0, WorkArea_Width, WorkArea_Height
              , hdc_thumbnails, 0, 0, 0xCC0020) ; SRCCOPY
     
      StretchBlt( hdc_backbuffer, pos_x + (thumb_w - thumb_w%A_Index2% ) // 2 + diff_x * zoom
                           , pos_y + (thumb_h - thumb_h%A_Index2% ) // 2 + diff_y * zoom
                           , thumb_w%A_Index2% + diff_w * zoom
                           , thumb_h%A_Index2% + diff_h * zoom
                           ,hdc_printwindow, 0, 0, w%A_Index2%, h%A_Index2% ,0xCC0020) ; SRCCOPY
   
       BitBlt(hdc_frontbuffer, 0, 0, WorkArea_Width, WorkArea_Height
                ,  hdc_backbuffer, 0, 0 ,0xCC0020) ; SRCCOPY
     }
   
Return

fade_in:
   ; not used ?
Return

fade_out:
   ; fade last animate_out with real desktop
Return


; subroutines by kli6891 to show minimized windows


; generate an array of minimized windows
fill_mini_List:

   minimized_counter := minimized_counter + 1 ; simulate "cleaning" groupadd

   miniList =
   miniCount = 0
   WinGet, listOfWindows, list,,, Program Manager
   Loop %listOfWindows%
   {
      currentWindowID := listOfWindows%A_Index%
      WinGetTitle, title, ahk_id %currentWindowID%
      if (title != "start" && title != "")
      {
         Winget, isMinimize, MinMax, ahk_id %currentWindowID%
         if (isMinimize == -1)
         {
            GroupAdd , mini%minimized_counter% , ahk_id %currentWindowID%
         }
      }
   }
   
   minAnimation(0)
   WinRestore, ahk_group mini%minimized_counter%
return

;generate group of the current process name NOT WORKING YET
;fill_mini_list_current:
;   minimized_counter := minimized_counter + 1 ; simulate "cleaning" groupadd
;
;   miniList =
;   miniCount = 0
;   WinGet, listOfWindows, list,,, Program Manager
;   Loop %listOfWindows%
;   {
;      currentWindowID := listOfWindows%A_Index%
;      WinGetTitle, title, ahk_id %currentWindowID%
;      WinGet, currentProcessName, ProcessName, hiahk_id %currentWindowID%
;      if (title != "start" && title != "")
;      {
;         Winget, isMinimize, MinMax, ahk_id %currentWindowID%
;         if (isMinimize == -1 && currentProcessName == activeProcessName)   ; only if the process name matches also
;         {
;            GroupAdd , mini%minimized_counter% , ahk_id %currentWindowID%
;         }
;      }
;   }
;   
;   minAnimation(0)
;   WinRestore, ahk_group mini%minimized_counter%
;return


; minimize all windows that were previously captured by fill_mini_list
; except if the window is currently active
restore_position:
   WinGet ActiveID, ID, A

   WinMinimize, ahk_group mini%minimized_counter%
   WinActivate ahk_id %ActiveID%
   minAnimation(1)
return


minAnimation(set="")
{
   VarSetCapacity(AnimationInfo, 8,0)
   cbSize := VarSetCapacity(AnimationInfo)
   NumPut(cbSize, AnimationInfo, 0, "UInt")

   if set =
   {
      DllCall("SystemParametersInfo", UInt, 0x48, UInt, cbSize, "UInt", &AnimationInfo, UInt, 1 )
      return NumGet(AnimationInfo,4)
   }
   
   if (set = 0 || set = 1)
   {
      NumPut(cbSize, AnimationInfo, 0, "UInt")
      NumPut(set, AnimationInfo, 4, "Int")
     
      DllCall("SystemParametersInfo", UInt, 0x49, UInt, cbSize, "UInt", &AnimationInfo, UInt, 1 )
      return 1
   }
   return 0
}


Gui_Show() {
   global
   if Shown
      return

  ; SysGet, mc, MonitorCount
  ; Loop, %mc%
  ;     Gui, %A_Index%:Show
    Gui, Show
   Shown = 1
}

Gui_Hide() {
   global
   tooltip,
   if !Shown
     return
   
  ; SysGet, mc, MonitorCount
  ; Loop, %mc% + 1
  ;     Gui, %A_Index%:Hide
   
   Gui, Hide
   Shown =
}

hide_gui:
   Stop_Drawing = 1
   Gui_Hide()
   WinActivate(ActiveID)                   ; activate last active window
Return

handle_exit:
   Gui Destroy
   ReleaseDC(hw_frame,hdc_frontbuffer)     ; free lock?
   DeleteObject( hbm_printwindow)
   DeleteDC(     hdc_printwindow)
   DeleteObject( hbm_window)
   DeleteDC(     hdc_window)
   DeleteObject( hbm_backbuffer)
   DeleteDC(     hdc_backbuffer)
 ;  WinActivate ahk_id %ActiveID%    ; activate last active window
ExitApp


; --------------------------------------------------------------------------------------------------
; Library: no need to modify below

; Libary (could be put in extra file )
; #include <GDI.ahk>
; for documentation of commands see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/wingdistart_9ezp.asp

; -- highlevel not direct dllcall mapping , simplifiers
CreateDCBuffer(ByRef hdc_from, ByRef hdc_to, ByRef hbm_to, w ,h ) {
   ; does not work, something wrong with ByRef and global
   hdc_to  := CreateCompatibleDC(hdc_from) ; buffer
   hbm_to  := CreateCompatibleBitmap(hdc_from,w,h)
   old     := SelectObject(hdc_to,hbm_to)
}

; -- mfc wrapper
GetDC( hw ) {
   return DLLCall("GetDC", UInt, hw )
}

CreateDC( driver,device,output,mode  ) {
   return DLLCall("GetDC", UInt, driver, UInt, device, UInt, output, UInt, mode )
}

SetStretchBltMode( hdc , value ) {
     return DllCall("gdi32.dll\SetStretchBltMode", UInt,hdc, "int",value)
}

CreateCompatibleDC( hdc ) {
   return DllCall("gdi32.dll\CreateCompatibleDC", UInt,hdc)
}

CreateCompatibleBitmap( hdc , w, h ) {
     return DllCall("gdi32.dll\CreateCompatibleBitmap", UInt,hdc, Int,w, Int,h)
}

SelectObject( hdc , hbm ) {
   return DllCall("gdi32.dll\SelectObject", UInt,hdc, UInt,hbm)
}

DeleteObject( hbm ) {
   return DllCall("gdi32.dll\DeleteObject", UInt,hbm)   
}

DeleteDC( hdc ) {
   return DllCall("gdi32.dll\DeleteDC", UInt,hdc )
}

ReleaseDC( hwnd, hdc ) {
   return DllCall("gdi32.dll\ReleaseDC", UInt,hwnd,UInt,hdc )
}

PrintWindow( window_id , hdc , mode ) {
   return DllCall("PrintWindow", UInt, window_id , UInt,hdc, UInt, mode)
}

StretchBlt( hdc_dest , x1, y1, w1, h1, hdc_source , x2, y2, w2, h2 , mode) {
   return DllCall("gdi32.dll\StretchBlt"
          , UInt,hdc_dest  , Int,x1, Int,y1, Int,w1, Int,h1
             , UInt,hdc_source, Int,x2, Int,y2, Int,w2, Int,h2
          , UInt,mode)
}

BitBlt( hdc_dest, x1, y1, w1, h1 , hdc_source, x2, y2 , mode ) {
   return DllCall("gdi32.dll\BitBlt"
          , UInt,hdc_dest   , Int, x1, Int, y1, Int, w1, Int, h1
             , UInt,hdc_source    , Int, x2, Int, y2
          , UInt, mode)
}

PaintDesktop(  hdc ) {
   return DllCall("PaintDesktop", UInt, hdc )
}

; constants
; see: http://www.adaptiveintelligence.net/Developers/Reference/Win32API/GDIConstants.aspx
; #SRCCOPY = 0xCC0020





Here is an updated Version with a rewrite of the script, there is some complexity involved so its not completely easy. I put many comments ito the code, so it should be easier to understand. Feel free to improve and post you modificaions here.

You will need gdip.ahk in the same folder or globaly in ahk.
gdip.ahk download

Code:

; v.20090922 -- expose.ahk - Thumbnails of Windows. Clean Rewrite

OnExit Handle_Exit
#include Gdip.ahk ; in library folder or next to this script
#SingleInstance Force
#NoEnv
SetBatchLines -1
SetWinDelay 0               ; larger values also fail under heavy load, changing windows
Process Priority,,Above Normal
CoordMode Mouse, Relative

Main:
   Gosub, Config
   Gosub, Init_Gui
   ;Gosub, Repaint
   ; idle in background, wait for key (Window_Activate)
Return

Config:
   ; -- Keys to Start/Show Expose
   Hotkey, MButton, Window_Choose
   Hotkey, ESC, Handle_Exit
   ;
   ;

   ; -- Keys while in Gui-Mode
   Hotkey, IfWinActive, EXPOSE_GUI_1
      Hotkey, MButton , Window_Activate
      ;
      ;
      ;
      Hotkey, #F12 , Debug_Info
      Hotkey, ESC , Handle_Exit

   ; -- Predefined Variables and other Configs
   show_win_min_w = 110 ; min width of windows to be shown
   show_win_min_h = 110 ; min height of windows to be shown, hides Taskbar
   cpu_yield = 100 ; ms to wait
   gui_background = 333333
   do_zoom := 0 ;
   ; animate_delay  = 5 ;
   ; show_taskbar   = 1 ; Leave a gap so Taskbar is still visible
   ; main_monitor   = 1 ; (or 2,3,4,...)
   win_count_old := 0
   can_repaint := 1
   ;
   ;
   ;
   ;
Return

Debug_Info:
   ListLines
Return

Init_Gui:
   ; Detect Screensize, means where is the Taskbar, Is it Multi-Monitor ?
   ; ... Either very Short directly here or as a Helper-Function only Returning x0,y0,w,h ?

   ; Start gdi+ , we dont need it until we draw on surface with lines etc.
   if (0) {
      If !pToken := Gdip_Startup()
      {
         MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
         ExitApp
      }
   }
   
   ; Copy bounds of all monitors to an array.
   SysGet, mc, MonitorCount
   Loop, %mc% {
      if ( A_Index > 1 )
         continue
     
      SysGet, mon%A_Index%, MonitorWorkArea, %A_Index%
      md := A_Index
      WorkArea_Top    := mon%md%Top  ; + 50
      WorkArea_Left   := mon%md%Left ; + 50
       WorkArea_Width  := mon%md%Right - mon%md%Left ; - 50
       WorkArea_Height := mon%md%Bottom - mon%md%Top ; - 50
   
      ; create Gui For Each Monitor, because we want to hide them all

      Gui +AlwaysOnTop -Caption  +Toolwindow +Owner +LastFound ; +OwnDialogs ; +E0x80000       
      Gui Show,  Hide w%WorkArea_Width% h%WorkArea_Height% x%WorkArea_Left% y%WorkArea_Top%, EXPOSE_GUI_%A_Index%
      ;Gui Show,  Hide w%WorkArea_Width% h%WorkArea_Height% x%WorkArea_Left% y%WorkArea_Top%,   »Expose«

    ;   Gui %A_Index%:Color, %gui_background%
   ;   WinSet, TransColor, %gui_backgroundcolor% 128

   ;      hwnd%A_Index% := WinExist() ; grab handle for this new gui-window for later use   
 
   }

   ; Create a Gui, but Hide it Immediately, so preparing in Background, we dont want to see
   ; ... whats going on
   ;Gui Show, Hide ..... , EXPOSE_GUI

   ; Create Buffers
   
   ; Buffer 1: Main-Display "frontbuffer" is the EXPOSE_GUI, the only thing which we SEE
   ; ... nothing to do here, its a real window ! we cannot paint directly on Desktop as
   ; ... we need to remove it when closing Expose. Also the window holds the old "state"
   md := 1 ; use monitor 1 (which should be main-monitor with taskbar by default)
   Width :=  ( mon%md%Right - mon%md%Left )
   Height:=  ( mon%md%Bottom - mon%md%Top )
  DetectHiddenWindows ON
  WinGet Expose_ID , ID, EXPOSE_GUI_1
  WinGet Desktop_ID, ID, Program Manager
  DetectHiddenWindows OFF

   ;   tooltip, "e: " %Expose_ID% " + " %Expose2_ID%  " - " %Desktop_ID% + " w " %Width%
   
   hdc_gui := GetDC( Expose_ID )

   ; Buffer 2: Print-Window; This is our Handle to Read the Current Look of one of the
   ; ... Application-Windows. Is it needed or can we read it directly ?
   hdc_thumb := CreateCompatibleDC(     hdc_gui )
   hbm_thumb := CreateCompatibleBitmap( hdc_gui, Width , Height )
   hbm_old   := SelectObject(        hdc_thumb, hbm_thumb )

   ; Buffer 3: Backbuffer; This holds the Screen for Rendering Our "Scene", We do it in Background,
   ; ... so there is no flicker while Drawing, giving a nice View. This also prevents funny
   ; ... drawings when windows get reaaranged due to chaning of windows.
   ; ... Is it really needed or can we directly paint on the frontbuffer ?
   ; ... One Problem could be flicker, because we clear the "scene" in each round to paint the
   ; ... Desktop-Wallpaper. Done in Realtime will result in flicker as thumbs are hidden by wallpaper.
   ; visible Gui
   ; ???
   hdc_display := CreateCompatibleDC(     hdc_gui )
   hbm_display := CreateCompatibleBitmap( hdc_gui, Width , Height )
   hbm_old := SelectObject(        hdc_display, hbm_display )

   ; Buffer 4: Wallpaper; This holds the Wallpaper from Desktop and is the Base for Repaint
   ; ... On each Loop whe paint first the Wallpaper and then the Thumbnails.
   ; ... Optimization is not to clear all from Backbuffer, but draw over the Backbuffer all
   ; ... the time because only little is changing. If we have a Gap, or Window-Rearrangement
   ; ... then we need to copy "repair" this sections with the Wallpaper and the new Thumbnail
   hdc_desktop := CreateCompatibleDC(     hdc_gui )
   hbm_desktop := CreateCompatibleBitmap( hdc_gui, Width , Height )
   hbm_old   := SelectObject(        hdc_desktop, hbm_desktop )
   

   ;SetStretchBltMode(hdc_thumb   ,4) ;
   ;SetStretchBltMode(hdc_gui     ,4) ;
   SetStretchBltMode(hdc_display ,4) ;
   ;SetStretchBltMode(hdc_desktop ,4) ;

   ; to front
   Gui Show
   PaintDesktop( hdc_gui ) ; Paint Desktop-Wallpaper on Top of GUI:1
   BitBlt( hdc_desktop , 0,0, Width, Height, hdc_gui , 0,0, 0xCC0020 ) ; Copy Surface of GUI:1 to Buffer:Desktop
   BitBlt( hdc_display , 0,0, Width, Height, hdc_gui , 0,0, 0xCC0020 ) ; Copy Surface of GUI:1 to Buffer:Desktop
   Gui  Hide

   ; autostart on launch of expose ??
   ;Gosub, Window_Choose

   ;Gui 1:Hide
   ; Hide and wait for user to start

   ; Restore Minimized Windows here as we also want to show them in Expose mode
   ; ... Remember their State and Minimize them Later when needed. (When Hide, Close ExposeGUI !)
Return

Window_Hidden( w, h, title, class) {
   global
   Return w < show_min_win_w or h < show_min_win_h or InStr(title ,"EXPOSE_GUI_") or title ="" or class ="tooltips_class32"
}

Window_Choose:
   ; Open The Gui (with Animate_In-Effect )
   ; ... and Start Repainting the Thumbnail in a Loop
   ; ... Until User Activates a Window, or Closes/Hides the ExposeGUI
   ; ... Actually Hide/Close also Calls Window_Activate and Activates the old one
   ;Gui 1:Show
   WinGet ActiveID, ID, A

   Gui, Show
   can_repaint := 1 ; start/allow repaint loop
   Gosub, Repaint
Return

Window_Activate:
   ; Find the Window which is under the Mouse-Pointer (Hovered)
   ; ... And Zoom this Window out with "Animate_Out" and make it the Active One.
   Gui 1:Hide
   can_repaint := 0 ; stop repainting loop
Return

Repaint:
   ; Loop through all Active Tasks and Paint them with help of PrintWindow() to the
   ; ... Backbuffer. Then flip the Backbuffert to the Frontbuffer to show the updated Scene.
   ; ... BitBlt from Backbuffer to Frontbuffer is quite fast.
   ; ... But Update of the Thumbnails could be Painted to Frontbuffer Directly if we are
   ; ... Good in "Repairing" the Gaps etc.
   ; ... Maybe we use the Backbuffer only for one Tile (eg. one Thumbnail + Wallpaper as Background)
   ; ... and Minimize Repainting of screen but Prevent Flicker this way.
   ; ... If we Repaint less pixels with BitBlt (or Strechblt) then the App will be faster / smoother!

   Sleep %cpu_yield% ; give CPU some Rest otherwise Expose tries to grab 100% CPU, always updating windows
   
   ; count visible windows (windows we should paint)
      win_count_old := win_count ;
      win_count := 0
      WinGet task, list,,,Program Manager      ; all active windows-tasks (processes)
        Loop %task% {
         ; if needed Restore part of Wallpaper on this Tile to Backbuffer
         ; copy Applicationwindow to Backbuffer with Printwindow() using StrechBlt to Resize
         ; ... (Minimize it)
         ; ... is Gdip_Worldtransform a better alternative to StrechBlt, or is it internally the same ?
         ; copy Backbuffer to Frontbuffer
         id := task%A_Index%
         WinGetClass class, ahk_id %id%
         WinGetTitle title, ahk_id %id%
         WinGetPos ,,, w,h, ahk_id %id%

         if Window_Hidden(w,h,title,class)
            Continue
         win_count ++
      }
   


   if (do_zoom = 0 or force_refresh = 1) {
      Gui 1:Show
      ; refresh the canvas if number of windows changed, which changes layout !
      ; later only when layout changes (eg. rows and/or cols of thumbnail-grid !)
      if (1 or win_count <> win_count_old ) {
         ; can be optimized !
         BitBlt( hdc_display, 0,0, Width,Height, hdc_desktop, 0,0 ) ; Restore Wallpaper   
      }   
      titles := ""
      win_nr := 0
      WinGet task, list,,,Program Manager      ; all active windows-tasks (processes)
        Loop %task% {
         ; if needed Restore part of Wallpaper on this Tile to Backbuffer
         ; copy Applicationwindow to Backbuffer with Printwindow() using StrechBlt to Resize
         ; ... (Minimize it)
         ; ... is Gdip_Worldtransform a better alternative to StrechBlt, or is it internally the same ?
         ; copy Backbuffer to Frontbuffer
         id := task%A_Index%
         WinGetClass class, ahk_id %id%
         WinGetTitle title, ahk_id %id%
         WinGetPos ,,, w,h, ahk_id %id%

         if Window_Hidden(w,h,title,class)
            Continue

         win_nr ++
         titles := titles "`n" A_Index ": " class ", " title  "(" w  "," h ")"
         

         PrintWindow( id , hdc_thumb , 0 )

         ;Put the Painted window in
         MouseGetPos X, Y
         X=0
         Y=0
      ; Render into Display_Buffer
         WW :=  Width/win_count
         HH := WW * h / w ; make proportional zu original window
         YY := (Height / 2) - ( HH ) / 2
         StretchBlt( hdc_display , (WW) * (win_nr - 1 ) + X, YY + Y
                  ;, w/win_count, w*Height/Width/win_count
                  , WW , HH
                  ,  hdc_thumb ,  0 , 0, w, h,0xCC0020 ) ;
         ;sleep , 100
      }
     
         BitBlt( hdc_gui , 0 , 0  ,Width,Height,  hdc_display ,  0 , 0 ) ;
   ;   tooltip, iff
   } else {
      ; Only Repaint the Hovered Window/Thumbnail
      ; ... Here Backbuffer comes Handy, as we keep the current State in Backbuffer
      ; ... and only Paint the Zoomed Thumbnail/Live-Window over the Backbuffer
      ; ... or we use another GUI-Window On-Top and let Windows do the Updating which
      ; ... holds the Zoomed Version
     
   ;   tooltip, elsee
   }
;   tooltip, aaa
   ; As an optimization, we could repaint all Thumbnails in low-priority even if in zoomed mode
   ; like every 10seconds, so we react correctly on changes in them and opened/closed windows.
   ;   MouseGetPos X, Y
   ;   if ( X>0 and Y>0 ) {
   ;      UpdateLayeredWindow(hwnd1, hdc, X, Y, Width, Height)
   ;   }
   ;tooltip , %titles% ,,1

   if ( can_repaint = 1 )
      Goto, Repaint ; call self in a loop
Return

Animate_In:
   ; Make Screenshot of Current Desktop or Active-Window and Un-Zoom it into Thumbnail - Possition
   ; .. This makes Expose MUCH more integrated. Small Animation , Big Effect
Return

Animate_Out:
   ; Simulate Zoom Back to Real size
Return

; I cant remember but there was some sense in using the "Shown" -Variable,
; ... maybe this is not used/needed anymore ?

Gui_Show() {
   ; prevent showing twice when active already
}

Gui_Hide() {
   ; hide only when visible
}

Handle_Exit:
   ; Clean Up all Resources so we dont get MemoryLeaks when Closing Expose
   ; for each monitor
    SysGet, mc, MonitorCount
   Loop, %mc% {
      Gui %A_Index%: Destroy
   }

;

   ReleaseDC(hw_frame,hdc_gui)

   SelectObject(hdc_display,hdc_display_old )
   DeleteObject(hbm_display)
   DeleteDC(    hdc_display)

   SelectObject(hdc_thumb,hdc_thumb_old)
   DeleteObject(hbm_thumb)
   DeleteDC(    hdc_thumb)

   SelectObject(hdc_desktop,hdc_desktop_old)
   DeleteObject(hbm_desktop)
   DeleteDC(    hdc_desktop)

   Gui Destroy

   Gdip_Shutdown(pToken)
ExitApp

; -- Library now will be #include Gdip.ahk
; vim:ts=3:sw=3:ft=c
; http://www.autohotkey.net/~tic/Gdip.ahk

; -- Function now integrated in new gdip.ahk

 
; PaintDesktop(  hdc ) {
;  return DllCall("PaintDesktop", UInt, hdc )
; }

; CreateCompatibleBitmap( hdc , w, h ) {
;     return DllCall("gdi32.dll\CreateCompatibleBitmap", UInt,hdc, Int,w, Int,h)
; }


; SetStretchBltMode( hdc , value ) {
;     return DllCall("gdi32.dll\SetStretchBltMode", UInt,hdc, "int",value)
; }


Last edited by holomind on Tue May 25, 2010 6:07 pm; edited 47 times in total
Back to top
View user's profile Send private message Visit poster's website
Veovis



Joined: 13 Feb 2006
Posts: 389
Location: Utah

PostPosted: Sun Oct 01, 2006 2:38 am    Post subject: Reply with quote

EXCELLENT!!!

this is way cool!

i have always loved macs expose. its so useful and intuitive. unlike alt-tabbing through a bunch of icons or looking for the name of your program in the taskbar, expose is intuitive and easy.

While this does go a little slow on my 1 Ghz lappy, i am very pleased with the feel. I noticed that there is a lot of black space if you have some small windows open, but that isnt a problem really, and it would be complicated to compute window sizes so the fit together better.

I also changed the transparency so it goes black because it was slightly disorienting to see parts of a different window behind the small thumbnails.

Overall, Very nice job!
_________________

"Power can be given overnight, but responsibility must be taught. Long years go into its making."
Back to top
View user's profile Send private message Send e-mail Visit poster's website
koro



Joined: 24 Sep 2006
Posts: 61

PostPosted: Sun Oct 01, 2006 2:44 am    Post subject: bogus? Reply with quote

The first time i tried it worked fine, but now it's randomly showing 1 or 2 windows only, not all of the open windos. in fact right now it only shows 1, everytime. I re-downloaded the script since i may have pasted something wrong but no...
Back to top
View user's profile Send private message
Veovis



Joined: 13 Feb 2006
Posts: 389
Location: Utah

PostPosted: Sun Oct 01, 2006 3:03 am    Post subject: Reply with quote

hmmmm your right. right now it only shows 4 of the 6 that are open. it might be due to the ... somewhat odd nature of the google talk windows, but i recall them working earlier... any ideas?
_________________

"Power can be given overnight, but responsibility must be taught. Long years go into its making."
Back to top
View user's profile Send private message Send e-mail Visit poster's website
SoggyDog



Joined: 02 May 2006
Posts: 783
Location: Greeley, CO

PostPosted: Sun Oct 01, 2006 5:45 am    Post subject: Reply with quote

I absolutely love it...
However, I also have windows that don't show up.

Exclamation This really is a fantastic script Exclamation
_________________

SoggyDog
Dwarf Fortress:
"The most intriguing game I've ever played."
Back to top
View user's profile Send private message Send e-mail Visit poster's website MSN Messenger
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sun Oct 01, 2006 9:26 am    Post subject: Reply with quote

i also noticed that windows sometimes do not show acutally they are completele black (but not missing). its a problem with the printwindow() function. and perhaps shows up when many windows are open. if i have 4windows or 8windows it works but with more it can give black windows.

the msdn api says it returns if it was successfull, but in my case it also returns 1 if its black. one trick would be to draw it repeatadly calling the draw_thumbnails in a loop (every second) to repaint it, then the chance is quite good next time its correct.
in the beginning i had the gui: add picture just after the printwindow and got lots of black frames, i move the gui add to a different location in the code and it didnt interfere anymore. there are many people complaining about black frames in printwindow and its quite unreliable. even commercial tools have this problem.
perhaps one could do a pixel search on the lower half of the thumbnail and if its black then repaint the window. perhaps search on the windowborder so you dont hit real black text or background by accident.

you have the code so you can tweak it.
performace should not be the greatest as all is done in printwindow and bitblt. (fast but slower than directx or opengl).

on the other hand bitblt-ing the desktop never gives black frames, so you could buffer the images and then show them, but this makes it more complicate.

as i didnt notice blackframes in my useage i hadnt the need to optimize it.

for debugging it would be interessting:
a) number of windows when showing expose
b) your screenresolution
c) ghz of cpu, and perhaps brand of gfx-card (shared or realmemory)

eg. i have 6windows, 1400x1050 intel-i850 gfx with no problems
Back to top
View user's profile Send private message Visit poster's website
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sun Oct 01, 2006 9:28 am    Post subject: Reply with quote

did you notice the size-filter? it hides windows smaller than 200px-width or lower than 200px height. this way i hide windows on purpose like taskbar. maybe some sidebars and other small windows "disappear", this is by purpouse.
you can tweak the min_w and min_h in the readconfig functions to allow other windows.
Back to top
View user's profile Send private message Visit poster's website
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sun Oct 01, 2006 9:39 am    Post subject: Reply with quote

Veovis wrote:

While this does go a little slow on my 1 Ghz lappy, i am very pleased with the feel. I noticed that there is a lot of black space if you have some small windows open, but that isnt a problem really, and it would be complicated to compute window sizes so the fit together better.


it is a bit slow due to the fade_in/out also the printwindow (actually repainting each of your windows in realtime instead of just making a screenshot, printwindow() is much slower than bitblt the desktop) you could speed this up with buffers but then need more memory etc. (many expose tools give you the option to optimize it for speed, memory or smoothness etc. this is the "basic" version Wink

the windows could be zoomed but the complicated part is not to distort the image, you can easily set thumb_w2 = thumb_w and thumb_h2=thumb_h and it uses all space but distorts then, i tried it but didnt do the math right Wink also it makes the code longer and harder to understand.
(also if width > height you need to reduce width, otherwise the width, not so easy)

thanks for the compliments Wink
Back to top
View user's profile Send private message Visit poster's website
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sun Oct 01, 2006 10:50 am    Post subject: Reply with quote

the script is now a bit longer, but i implemented the suggested ideas:

a) small windows are scaled to fit the avalable space in this grid-zone.
no tetris stacking yet Wink (which i personally dont like)

b) you can set the end of animation to solid if you set
read_config: translevel_stop_solid to 1

c) the window filter is now in a separate function so you can easily adopt it to your needs. i have to hide my deskman window and my objectdock-tab-folderbar, which would mess it up. also expose itself is hidden.

i think there is not a big problem with black frames in printwindow, but windows are hidden because of their size. for me expose works like expected Wink
Back to top
View user's profile Send private message Visit poster's website
majkinetor



Joined: 24 May 2006
Posts: 4511
Location: Belgrade

PostPosted: Sun Oct 01, 2006 10:55 am    Post subject: Reply with quote

Superb homind, this is exactly what I wanted up to the animation.

The bugs are of course, present in this first release, windows are dropped somehow. First time when I run it, all were there except console. I restarted the script and only console and opera were there, and on next F12, console dissappeared leaving opera small in one corner. On next F12, Opera was big, using all the screen. Smile))


BTW, I have an advice to you. You should change the layout of your presentation with something more structural. I had a problem with your other script using this and that - well, not really a problem but it was more time consuming then it should be. So, I suggest you to put download cleanly visible and direct links to scripts u used if you didn't merge all scripts at the end (ExpandIncludes.ahk). You can also provide archive with all the additionals used by your main script. I also noticed that Chris created overview for one of your scripts witch shouldn't happen in the first place if they are structured well. Consider that some of us don't have enough time to read every word and/or entire thread, and want to "jump in" in fastest way. If you supply usability & installation data clearly visible and separated of other text, they are able to do that.
_________________
Back to top
View user's profile Send private message
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sun Oct 01, 2006 10:59 am    Post subject: Reply with quote

majkinetor wrote:
...visible and direct links to scripts u used if you didn't merge all scripts at the end (ExpandIncludes.ahk).


you dont understand its only this script and no includes whatsoever.
i always put the download link above the code so people can easliy download it instead of copy+paste it into notepad and save ..

is this to complicated ? this forum is an exchange of script-CODE and not to sell executables.
Back to top
View user's profile Send private message Visit poster's website
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sun Oct 01, 2006 11:31 am    Post subject: Reply with quote

the scale function is now bugfixes, i hope it scales the windows without distortion now.

majkinetor suggested to use wallpaper instead of black background, so we wait what he comes up with, as i dont use any wallpaper i dont know how to do it Wink
Back to top
View user's profile Send private message Visit poster's website
majkinetor



Joined: 24 May 2006
Posts: 4511
Location: Belgrade

PostPosted: Sun Oct 01, 2006 11:48 am    Post subject: Reply with quote

Quote:
you dont understand its only this script and no includes whatsoever.
i always put the download link above the code so people can easliy download it instead of copy+paste it into notepad and save ..

I don't talk about this script.

Quote:
is this to complicated ? this forum is an exchange of script-CODE and not to sell executables.

It is not too complicated. Who is talking about selling executables ?
I wish there is some standard form of presentation here....
_________________
Back to top
View user's profile Send private message
holomind



Joined: 11 Mar 2006
Posts: 341
Location: Munich, Germany

PostPosted: Sun Oct 01, 2006 11:54 am    Post subject: Reply with quote

majkinetor wrote:
I wish there is some standard form of presentation here....


ok, thats what you want, but you wont get this in short term. there are too many different ways presenting script in this forum , also the codestyle etc.

you would need a "template" or "form" to fill out and have consistency. this is a "forum" software Wink

its hard enough that the code is in the first post and updated there Wink
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sun Oct 01, 2006 5:26 pm    Post subject: Reply with quote

This is a very nice script. I will use a version of it all the time. Thanks Holomind for sharing it. (Don't worry about the comments on the format. It is fine!).

I only have problems with disappearing command prompt (console) windows (Version 0.3). They randomly show up or remain black after pressing F12. All other windows behave properly.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3 ... 18, 19, 20  Next
Page 1 of 20

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group