 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Laszlo
Joined: 14 Feb 2005 Posts: 4002 Location: Pittsburgh
|
Posted: Tue Oct 03, 2006 11:42 pm Post subject: |
|
|
Here is another version of Holomind's cleaned up "real expose clone" Version 0.6. Sometimes some windows were not restored properly, so I added #WinActivateForce. I added a few speed-up directives (no dramatic improvement), removed a few more unnecessary lines, changed the hotkey to Win-TAB (as it has similar functionality as Alt-TAB) kept the middle mouse button, added ESC as an "I changed my mind" hotkey.
Could someone figure out the simplest way to add little numbers to the thumbnails?
Edit: Removed the code. Use the improved version.
Last edited by Laszlo on Thu Oct 05, 2006 7:40 pm; edited 1 time in total |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Wed Oct 04, 2006 12:23 am Post subject: |
|
|
| Quote: |
i found some more details about how expose works.
http://www.flipcode.com/cgi-bin/fcarticles.cgi?show=64630
(30 lines of cpp code, oh this ahk script is longer ;(
""- It's written in C++, uses straight Win32 API, OpenGL, and is around 30k lines of code. Windows XP only at the moment.""
|
ohh, i missed a little character, the article says "30k" K K K hmm, 30000 lines or does it mean 30kbyte of .cpp-file? ???
this ahk version of expose clone is much much smaller in code my day is saved ) but no opengl yet...
Last edited by holomind on Wed Oct 04, 2006 1:12 am; edited 1 time in total |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4002 Location: Pittsburgh
|
Posted: Wed Oct 04, 2006 12:50 am Post subject: |
|
|
| If you set "translevel_start" to 200, or so, you see that not PrintWindow eats up the time, but "Gui Add, Pic...". The first time the script takes 5 sec to put up 10 thumbnails, but later the refresh easily finishes in 1 sec (seen if you have open the date and time properties window with its free running clock). If I set the height and width of the picture in GUI to 0, it finishes in 2 sec instead of 5, but then you cannot click on this single dots. |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Wed Oct 04, 2006 12:52 am Post subject: |
|
|
i looked a bit into the gdi documentation for transform. in my understanding its more like a "filter" which is applied when you do a gdi operation like drawing lines or perhaps bitblt.
in my understanding its similar to strechblt vs. bitblt. strechblit transforms/scales your image/hdc when you copy it. and that is the point.
it is only applied if you copy from one hdc (eg. bitmap ) to another hdc( eg. window/desktop). maybe i am wrong, but i doubt that this will work.
you need to get the image from somewhere and copy it somewhere.
but there is a little chance that by setting the worldtransform windows can be "tricked" to paint the window smaller after this.
in gdi the windows dont have doublebuffer but only a frontbuffer (what you see exists, what you dont see on screen dont exists!) a printwindow gets all its information as the window is drawn again at this moment and copied into the specified hdc (bitmap-buffer). if you do alt tab the window behind has no visual representatio and therefore no "hdc". there are only "hidden buffers" and the desktop. but you cant read the window directly. (which will be different with directx10/vista/wmf which uses a technique like apple-quarz or linux-xgl. ) but with printwindow one can "simulate" a backbuffer which is refreshed seldom. perhaps this helps in understanding what is going on in gdi and window-destop display-routine.
i would be happy if proofed wrong and simply skale a window.
at least its very easy to scale a website in internet-explorer in an iframe.
but scaling "after" you have the dc-contents is not the problem. getting the dc-content is the problem.
in deskman i regularly copy the desktop into a kind of backbuffer (=thumbnail images) and have no performance hit. |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Wed Oct 04, 2006 1:00 am Post subject: |
|
|
| Laszlo wrote: | | If you set "translevel_start" to 200, or so, you see that not PrintWindow eats up the time, but "Gui Add, Pic...". The first time the script takes 5 sec to put up 10 thumbnails, but later the refresh easily finishes in 1 sec (seen if you have open the date and time properties window with its free running clock). If I set the height and width of the picture in GUI to 0, it finishes in 2 sec instead of 5, but then you cannot click on this single dots. |
hmm, so add picture is another speed-hit, but printwindow is definietly one slow part. but you may be right. adding pictures to gui forces a repaint of the gui or so. so perhaps this is not a good solution. so one should detect the mouseclick by
a) register hotkey LButton, find_clicked_thumb
b) wait for click
c) read mousepos of click and calculate in which thumbail it would have been (simply looping through the processes one more time and if the x,y matches you found it)
d) unregister hotkey for LButton so it works normally again
d) activate the connected window. (ahk_id)
as the window sizes change relative to number of windows the gui (add pic) cannot be static.
this idea would be more complicated to implement but perhaps speed is more important than short code  |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4002 Location: Pittsburgh
|
Posted: Wed Oct 04, 2006 1:19 am Post subject: |
|
|
| Well, the timing depends on the complexity of the windows. In another experiment I measured the time of the initial rounds of putting up the thumbnails. With Gui Add, Pic the time was 1.7 sec, without it: 1.4 sec. It is not as bad as my previous estimate (simply counting aloud). Still, it looks better to remove Gui Add, Pic and use the mouse coordinates at click. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4002 Location: Pittsburgh
|
Posted: Wed Oct 04, 2006 1:40 am Post subject: |
|
|
Here is the version w/o Gui Add, Picture commands. It is actually a few lines shorter, because we don't have to worry about adding the pictures only once. Mouse clicks are caught by the LButton hotkey, which is only active, when our Expose window is open. The activated window is computed from the location of the mouse click. We get some 20% faster startup, which is not much, but something. | Code: | #SingleInstance Force
#NoEnv
SetBatchLines -1
SetWinDelay -1 ; 0 if -1 fails
SetControlDelay -1
Process Priority,,High
#WinActivateForce ; otherwise some windows are not always fully restored
OnExit handle_exit
fade_delay = 0 ; msec to wait for next animation frame
fade_steps = 1 ; steps in animation, 2 = fast, 10 = slow (smooth)
min_w = 110 ; min width of windows to be shown
min_h = 110 ; min height of windows to be shown (hides taskbar etc)
translevel = 255 ; transparency of end of animation
translevel_start = 220 ; 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 = 1000 ; msec repaint the windows in expose mode, 0 = off
Return
#TAB:: ; WIN-TAB hotkey (~ Alt-TAB)
MButton::
IfWinExist Expose ; toggle off if already active
GoTo destroy_gui
GoSub create_gui ; prepare gui to draw onto it
GoSub calculate_sizes ; sets "cols" , "rows"
GoSub draw_thumbnails
GoSub fade_in
SetTimer draw_thumbnails, %live_repaint%
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, `,
{
WinGetTitle title, ahk_id %A_LoopField%
WinGetPos,,, w, h, ahk_id %A_LoopField%
If (!is_excluded_win() ) { ; small windows not shown (eg taskbar)
win_now++
task_ids_%win_now%:= A_LoopField ; for activation
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
}
}
pwin := DllCall("PrintWindow", UInt,A_LoopField, UInt,hdc_buffer, UInt,0)
DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame
, Int,pos_x + (thumb_w - thumb_w2 ) / 2
, Int,pos_y + (thumb_h - thumb_h2 ) / 2, 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
Return
is_excluded_win() {
Global
Return w < min_w or h < min_h or title ="Expose" or title =""
}
fade_in:
Loop %fade_steps% {
WinSet Transparent, % A_Index * translevel / fade_steps
Sleep %fade_delay%
}
If translevel_stop_solid
WinSet Transparent, off
Return
fade_out:
Loop %fade_steps% {
WinSet Transparent, % translevel - A_Index * translevel / fade_steps
Sleep %fade_delay%
}
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_gui:
Gui Destroy ; clear old stuff if expose hotkey is running in background
Gui +AlwaysOnTop -Caption +LastFound
Gui Color, 006666
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)
Return
#IfWinExist Expose
LButton::
MouseGetPos X, Y
pos := 1 + X*cols//A_ScreenWidth + Y*rows//A_ScreenHeight * cols
task_id := task_ids_%pos%
WinActivate ahk_id %task_id%
Esc::
destroy_gui:
SetTimer draw_thumbnails, OFF
Gosub fade_out
Gui Destroy
DllCall("gdi32.dll\DeleteObject", UInt,hbm_buffer)
DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdc_buffer)
Return
handle_exit:
Gosub destroy_gui
ExitApp |
|
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Wed Oct 04, 2006 2:04 am Post subject: |
|
|
@lazlo: this is noticable faster on my computer. so we could also improve another think, perhaps wasting a bit resources.
the script runs in background waiting for activation.
so we dont need to create and destroy the gui all the time. we can simply hide and show it.
also the GETDC etc. could be done only once and we keep the DC (perhaps not so good, but one should experiment) and destroy it only after exiting the script. at least the dc for our gui window can stay. the hw_frame = desktop perhaps should be closed and opened if some other app needs to use it. eg. printscreen.
this would separate the create_gui into two functions the second called show_gui, and the destroy gui could be split in two parts destoy and hide.
this should minimize things going on surround and only printwindow() uses ressources.
then we really need the hidden buffers for the windows, so they are shown from the cached version instead of the realtime gui-repaint=printwindow(). |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4002 Location: Pittsburgh
|
Posted: Wed Oct 04, 2006 2:14 am Post subject: |
|
|
| This is a good idea! In the mean time I experiment with modifying get_wins(), so window titles and sizes need not be acquired twice. I will post that version later tonight. (You go to sleep, it is quarter past 3 in the morning!) |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4002 Location: Pittsburgh
|
Posted: Wed Oct 04, 2006 4:26 am Post subject: |
|
|
Here is the version, which acquires window titles and sizes only once, and removes excluded windows from the list at the first time seen, so re-draws also get faster. Size parameters are stored in arrays, so they also get computed only at start up. It is slightly faster (by about another 20%) than the previous version.
I tested the script with 10..12 open windows, randomly switching between them hundreds of times. Every now and then there was a window not properly redrawn. In my PC "SetWinDelay 30" solved the problem. Other PC's may need longer or shorter delays. This does not slow down the script noticeably, because there is only one window created at start up, so only 30 ms delay is added there. At selection the GUI is destroyed and a window is activated. It is practically instantaneous, the 60 ms delay does not matter, but the script becomes much more robust.
Edit: Removed the code. Use the improved version.
Last edited by Laszlo on Thu Oct 05, 2006 7:43 pm; edited 1 time in total |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3624 Location: Belgrade
|
Posted: Wed Oct 04, 2006 7:52 am Post subject: |
|
|
This latest script works fast enough here.
Now it is really usable.
I doubt that WorldTransform can help here. It appears that every visible control and its DC must be changed ither, and also its width & height  _________________
 |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3624 Location: Belgrade
|
Posted: Wed Oct 04, 2006 9:31 am Post subject: |
|
|
I anylised your code and I have following to add.
1. get_wins() should be changed to use API function GetWindow with GW_HWNDNEXT to get next TOP LEVEL window. So you don't get controls
like taskbar etc... WinGet list will return buch of other windows we don't need
2. Maybe display can be more faster - instead of taking screenshots of windows then shrinking eatch and copy to Expose window, we can first use big Expose window and arange original window screenshots without shrinking to Expose, then shrink Expose to Scren at the end. This will maybe be faster. The + is you call Stretch only once. The - is you copy bigger images.
| Laszlo wrote: | | With a TrayTip in the right place could you check if the off-screen windows reported the right size? |
The windows return the right size. I check using this code in is_excluded_win:
MsgBox, %title% %w% %min_w% | %h% %min_h%
MSDN wasn't present among screenshots but I saw here that it is "included" window.
2 all
Until there are some GUI for exclusions, people can tweek this function. This is my example:
| Code: | is_excluded_win() {
Global
if InStr(title, "Winamp")
return 1
if title = Google Talk
return 1
Return w < min_w or h < min_h or title ="Expose" or title =""
}
|
This is also faster and better code for wallpaper background
Add this among the options
Change create_gui function
| Code: | create_gui:
Gui +AlwaysOnTop -Caption +LastFound
Gui Color, 006666
WinSet, Transparent, %translevel_start%
if (useWallpaper)
{
RegRead, wall_path, HKCU, Control Panel\Desktop, Wallpaper
Gui, Add, Picture, x0 y0 w%A_ScreenWidth% h%A_ScreenHeight%, %wall_path%
}
Gui Show, w%A_ScreenWidth% h%A_ScreenHeight% x0 y0, Expose
...
...
|
I also added this shortcut:
| Code: | ~ESC::
IfWinExist, Expose
GoTo destroy_gui
return, |
This is to activate via tray:
| Code: | OnExit handle_exit
useWallpaper = 1
fade_delay = 10 ; msec to wait for next animation frame
fade_steps = 3 ; steps in animation, 2 = fast, 10 = slow (smooth)
min_w = 110 ; min width of windows to be shown
min_h = 110 ; min height of windows to be shown (hides taskbar etc)
translevel = 250 ; transparency of end of animation
translevel_start = 0 ; transparency of start of animation (see offscreen painting)
scale_thumb_space = 1
live_repaint = 1000 ; msec repaint the windows in expose mode, 0 = off
Menu, Tray, Add, Show, MenuH
Menu, Tray, Default, Show
Menu, Tray, NoStandard
Menu, Tray, Click, 1
Return
#TAB:: ; WIN-TAB hotkey (~ Alt-TAB)
MenuH:
|
_________________

Last edited by majkinetor on Wed Oct 04, 2006 10:36 am; edited 2 times in total |
|
| Back to top |
|
 |
Hacker
Joined: 10 Jun 2006 Posts: 65 Location: Bratislava, Slovakia
|
Posted: Wed Oct 04, 2006 10:16 am Post subject: |
|
|
Hm, the last script by Laszlo is quite fast, however, here it often seems to activate the wrong window (Firefox instead of Excel, etc.). Additionally, sometimes the windows "overlap", so for instance the cursor from an editor blinks in Firefox.
Roman |
|
| Back to top |
|
 |
majkinetor
Joined: 24 May 2006 Posts: 3624 Location: Belgrade
|
Posted: Wed Oct 04, 2006 10:22 am Post subject: |
|
|
I have all kind of artifacts on the screen sometimes
Cursor in editor is also frozzen after usage... strange indeed... _________________
 |
|
| Back to top |
|
 |
SanskritFritz
Joined: 17 Feb 2005 Posts: 283 Location: Hungary, Budapest
|
Posted: Wed Oct 04, 2006 10:38 am Post subject: |
|
|
For me it simply disables my mouse left clicks!
Hey all TC users here  _________________ Is there another word for synonym? |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|