 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 12:00 am Post subject: ScreenMagnifier |
|
|
I played around with DC and DllCalls a little bit and built it into a Screen Magnifier similar to the one built in at Windows/Accessories.
The advantage of this vs. the builtin.
* you have the sourcecode and can customize it
* you can enable antializing (the built in has none!)
* you can set the speed of repaint (delay in ms with the slider, windows default is about 1000ms)
* you can define different zoomlevels, even unmagnify (shrink)
Due to a trick and using transparent 254 the window appears solid, but is invisible for BitBlt (DC_Copy), so the window does not copy itself and you even can magnify regions behind the loupe- window!
Like in the Builtin Magnifier, the mouseposition is watched and used for the selected region.
you also can resize the zoom window and the content is adopted automatically. (no distort, but large area)
I can even manage to zoom video (with 1-10ms delay) and watch it.
sometimes id like to zoom little flash-videos on websites without having to change my screen-resolution.
so now if somebody could find out how to save the contents of the DC to a file (BMP or other, DIB? Binarysave..) one could make nice tools with it.
=> solved see save screenshot with dgiplus only
there are many "mutations/variations" of this script, so choose the one you like. perhaps if find time to make a little "gallery" of the different versions and their differences. (there is no one size fits all, and the nice thing of having the sourcecode anybody can improve it)
this is the second code-section.
http://www.holomind.de/ahk/magnifier/magnifier_smooth.exe
| Code: |
OnExit handle_exit
Gui, +AlwaysOnTop +Owner +Resize +ToolWindow ; window for the dock
Gui, Show, NoActivate w400 h400 x300 y50 , PrintScreen
Gui, Add, DDL, vzoom , 0.5|1|2||4|8|16
Gui, Add, Checkbox, y12 x150 vantialize, Antialize ?
Gui, Add, Slider, vdelay x220 y0 Range15-200
Gui, Add, Text, x340 y12 w80 vdelay2
WinGet PrintScreenID, id ,PrintScreen ;
WinSet, Transparent , 254, PrintScreen
;retrieve the unique ID number (HWND/handle) of that window
WinGet, PrintSourceID, id
hotkey , #x , toggle_follow
hotkey , +$LButton , click_through
toolbar_def:=35
toolbar := toolbar_def
follow :=0
hdd_frame := DllCall( "GetDC", UInt, PrintSourceID )
hdc_frame := DllCall( "GetDC", UInt, PrintScreenID )
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)
Gosub, Repaint
return
toggle_follow:
follow := 1 - follow
if follow = 1
{
WinSet Region, 0-0 W%ww% H%wh% E , PrintScreen
toolbar := -32 ; height of window title
GuiControl, Hide, zoom
}
else
{
WinSet Region,, PrintScreen
toolbar :=toolbar_def
GuiControl, Show, zoom
}
Return
click_through:
if follow = 1
{
Gui, Hide
Send, {Click}
SetTimer, Repaint , Off
Sleep, 100
Gui, Show
SetTimer, Repaint, %delay%
}
Return
Repaint:
CoordMode, Mouse, Screen
MouseGetPos, start_x, start_y ; position of mouse
Gui, Submit, NoHide ; needed to read the dropdown and slidervalue
GuiControl,, delay2 , delay %delay% ms
WinGetPos, wx, wy, ww, wh , PrintScreen
wh2 := wh - toolbar
DllCall( "gdi32.dll\SetStretchBltMode", "uint", hdc_frame, "int", 4 * antialize ) ; Halftone better quality with stretch
DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,toolbar, Int,ww, Int,wh - toolbar
, UInt,hdd_frame, Int
, start_x-(ww / 2 / zoom)
, Int,start_y -( wh2 / 2/zoom), Int,ww / zoom, Int,wh2 / zoom ,UInt,0xCC0020) ; SRCCOPY
if follow = 1
WinMove, PrintScreen, ,start_x -ww/2 , start_y-wh/2
SetTimer, Repaint , %delay%
Return
GuiClose:
handle_exit:
DllCall("gdi32.dll\DeleteObject", UInt,hbm_buffer)
DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdd_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdc_buffer)
ExitApp
|
or with less gui, my current favorite (less frames is smoother)
| Code: |
#NoEnv
SetBatchLines -1
CoordMode Mouse, Screen
OnExit GuiClose
zoom = 2 ; initial magnification, 1..32
antialize = 0
Rx = 128 ; half vertical/horizontal side of magnifier window
Ry = 128
Zx := Rx/zoom ; frame x/y size
Zy := Ry/zoom
; GUI to show the magnified image
Gui +AlwaysOnTop +Resize +ToolWindow
Gui Show, % "w" 2*Rx " h" 2*Ry " x0 y0", Magnifier
WinGet MagnifierID, id, Magnifier
WinSet Transparent, 255, Magnifier ; makes the window invisible to magnification
WinGet PrintSourceID, ID
hdd_frame := DllCall("GetDC", UInt, PrintSourceID)
hdc_frame := DllCall("GetDC", UInt, MagnifierID)
SetTimer Repaint, 50 ; flow through
Repaint:
MouseGetPos x, y
xz := In(x-Zx-6,0,A_ScreenWidth-2*Zx) ; keep the frame on screen
yz := In(y-Zy-6,0,A_ScreenHeight-2*Zy)
; WinMove Frame,,%xz%, %yz%, % 2*Zx, % 2*Zy
DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*Rx, Int,2*Ry
, UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Zx, Int,2*Zy, UInt,0xCC0020) ; SRCCOPY
Return
GuiSize:
Rx := A_GuiWidth/2
Ry := A_GuiHeight/2
Zx := Rx/zoom
Zy := Ry/zoom
TrayTip,,% "Frame = " Round(2*Zx) " × " Round(2*Zy) "`nMagnified to = " A_GuiWidth "×" A_GuiHeight
Return
#a::
antialize := !antialize
DllCall( "gdi32.dll\SetStretchBltMode", "uint", hdc_frame, "int", 4*antialize ) ; Antializing ?
Return
#x::
GuiClose:
DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdd_frame )
ExitApp
#p::
MButton::
if paused =
{
Gui, 2:Hide
Gui, Hide
SetTimer, Repaint, Off
paused = 1
}
else
{
Gui, 2:Show
Gui, Show
SetTimer, Repaint, 50
paused =
}
Return
^+Up::
^+Down::
^+WheelUp:: ; Ctrl+Shift+WheelUp to zoom in
^+WheelDown:: ; Ctrl+Shift+WheelUp to zoom out
If (zoom < 31 and ( A_ThisHotKey = "^+WheelUp" or A_ThisHotKey = "^+Up" ))
zoom *= 1.189207115 ; sqrt(sqrt(2))
If (zoom > 1 and ( A_ThisHotKey = "^+WheelDown" or A_ThisHotKey = "^+Down" ))
zoom /= 1.189207115
Zx := Rx/zoom
Zy := Ry/zoom
TrayTip,,% "Zoom = " Round(100*zoom) "%"
Return
In(x,a,b) { ; closest number to x in [a,b]
IfLess x,%a%, Return a
IfLess b,%x%, Return b
Return x
}
|
Last edited by holomind on Fri Aug 25, 2006 3:46 pm; edited 3 times in total |
|
| Back to top |
|
 |
d-man
Joined: 08 Jun 2006 Posts: 268
|
Posted: Fri Aug 11, 2006 12:04 am Post subject: |
|
|
| That is sweet , good job ! |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5438 Location: /b/
|
Posted: Fri Aug 11, 2006 12:12 am Post subject: |
|
|
Hell yeah, thanks. _________________
 |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 12:53 am Post subject: |
|
|
Thanks, i hope you like it.
Some things i noticed myself.
* 40ms delay is 1sec / 25, means 25Frames / sec, which should be enough for video playback. (so perhaps instead of ms show framerate ?)
* having a flash movie in background does not cause flicker when the zoom window is in foreground (having video with hardware overlay flickers )
* even quicktime and wmv can be zoomed. dont know why but it works. often its difficult to work with video as it gets blacked out.
* the antialize sometimes does not *kick in* when there is only text on the zoomed part. if there is a graphic or a button or windowborder antialize is normally on. (m$'s fault)
* as this is scriptable, one could make zoom my tray-icons on hover ? the mouse then is on the perfect correct position already!
* the zoomwindow could easily follow the mouse (winmove zoomwindow x%startx%-offset ...) and simulate a real "loupe"
* clickthrough could be good but idealy should not disable the gui-controls for slider and dropdown, also moving the window on the windowtitle.
so something like if coordmode mouse relative => getmousepos is inside region x0 y%toolbar% winw winH. then let mouseclicks through
ala $LButton::
;hide loupe
Send {Click}
;show loupe
Return
* the impact of antialize is quite recognizable, also the strech/zooming.
* simply copy with 1 zoom no antialize has very little speed impact. |
|
| Back to top |
|
 |
M. Phelps Guest
|
Posted: Fri Aug 11, 2006 6:06 am Post subject: |
|
|
Your mission, holomind, if you accept it, is to
- Dock the ScreenMagnifier window in the top of the screen, without title bar, so when a window is created it can't overlap the magnifier's one (like in the original one)
- follow the text entered in dialog boxes, test fields, etc...
This SD Card will be destroyed in 10 seconds, and if you or one of your partners is dicovered, we'll say that we don't know anyone of you. |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 2:12 pm Post subject: |
|
|
I added some funstuff, now you can simulate a real Loupe with win-x (on/off) where the window gets into a circle and follows your mouse.
you even can clickthrough with shift-leftMouseButton.
Actually its not so usefull (usability) but its fun. |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 2:20 pm Post subject: |
|
|
| M. Phelps wrote: |
- Dock the ScreenMagnifier window in the top of the screen, without title bar, so when a window is created it can't overlap the magnifier's one (like in the original one)
|
this could be done with moving the window a little offscreen so the titlebar is invisible. or clip it away with winset region... making it owner/always ontop, no other program should go in foreground.
do you really want the effect that the whole desktop shifts down when you start the loupe ? you already can see the regions behind the zoomed window!
another solution would be to make the zoom window automatically move out of the way. means you move your mouse inside the zoomwindow and then it jumps to the other side of the screen (y or x axis) and you see what you want.
| M. Phelps wrote: |
- follow the text entered in dialog boxes, test fields, etc...
|
hm, i dont understand this exactly. do you want that the region around the cursor / selection is zoomed ? hmm perhaps with a click you could "freeze/unfreeze" the following of the mouse (manual selection of region of interest) ? or using drag-select to define the region of interest ? |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5438 Location: /b/
|
Posted: Fri Aug 11, 2006 2:25 pm Post subject: |
|
|
Would it be possible to save the current image (as bitmap)? _________________
 |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 2:30 pm Post subject: |
|
|
| Titan wrote: | | Would it be possible to save the current image (as bitmap)? |
if you know how to copy the contents of the DC (DeviceContext) to a file, then yes. but i dont know an easy solution.
if somebody manages to convert this VB-Code into AHK it would work.
http://www.codeguru.com/cpp/g-m/bitmap/article.php/c1741/
isnt there a thread in the forum to run VB-Code inside of AHK ? Or is it only VB-Script ?
http://www.autohotkey.com/forum/viewtopic.php?t=5379
Can this be used to run VB-Code ? Is there a big difference between VB-Code and VB-Script ?
e.g VB-Code
| Code: |
memDC.CreateCompatibleDC(&dc);
|
translates int AHK-Code (hdc_frame == &dc ? memDC == hdc_buffer ?)
| Code: |
hdc_buffer := DllCall("gdi32.dll\CreateCompatibleDC", UInt, hdc_frame)
|
|
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 3:10 pm Post subject: |
|
|
ist there a way to use CImage::Save
http://msdn2.microsoft.com/en-us/library/d06f3fhw.aspx
as a DLLCall (with help from gdi32.dll?) or similar..
this seams quite straightforward
| Code: |
// Demonstrating saving various file formats
int _tmain(int argc, _TCHAR* argv[])
{
CImage myimage;
// load existing image
myimage.Load("image.bmp");
// save an image in BMP format
myimage.Save("c:\image1.bmp");
// save an image in BMP format
myimage.Save("c:\image2",ImageFormatBMP);
// save an image in JPEG format
myimage.Save("c:\image3.jpg");
// save an image in BMP format, even though jpg file extension is used
myimage.Save("c:\image4.jpg",ImageFormatBMP);
return 0;
}
|
so if one manages to create a CImage "object", and copies the DC with SelectObject or BitBlt into the myimage, then perhaps its possible to save DC to BMP with AHK ?
this looks similar to :
http://www.autohotkey.com/forum/viewtopic.php?t=7792&highlight=dib#46244
so perhaps kiu might help us ? |
|
| Back to top |
|
 |
Blablabla Guest
|
Posted: Fri Aug 11, 2006 5:47 pm Post subject: |
|
|
My Dear Friend holomind:
Wow! What a holomind!
Here's my mod base on your code (and I prefer mine ):
Note:
Just move your mouse around!
Alt+Shift+WheelUp/Down to zoom in/out.
Win+X to exit.
| Code: |
;original by: holomind
;see more: http://www.autohotkey.com/forum/topic11700.html
#NoTrayIcon
OnExit handle_exit
CoordMode, Mouse, Screen
zoom = 2
Gui, +AlwaysOnTop +Resize +ToolWindow -SysMenu +E0x00000020
MouseGetPos, start_x, start_y
start_x -= 200
start_y -= 200
Gui, Show, w400 h400 x%start_x% y%start_y% , Magnifier
SetTimer, MoveWin, 0
WinGet MagnifierID, id ,Magnifier
WinSet, Transparent , 254, Magnifier
Gui, -Caption
;retrieve the unique ID number (HWND/handle) of that window
WinGet, PrintSourceID, id
hdd_frame := DllCall( "GetDC", UInt, PrintSourceID )
hdc_frame := DllCall( "GetDC", UInt, MagnifierID )
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)
Gosub, Repaint
return
Repaint:
MouseGetPos, start_x, start_y ; position of mouse
WinGetPos, wx, wy, ww, wh , Magnifier
wh2 := wh
DllCall( "gdi32.dll\SetStretchBltMode", "uint", hdc_frame, "int", 0 ) ; No Antializing
DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,ww, Int,wh
, UInt,hdd_frame, Int, start_x-(ww / 2 / zoom)
, Int,start_y -( wh2 / 2/zoom), Int,ww / zoom, Int,wh2 / zoom ,UInt,0xCC0020) ; SRCCOPY
SetTimer, Repaint , 0
Return
MoveWin:
MouseGetPos, now_x, now_y
now_x -= 200
now_y -= 200
WinMove, Magnifier, , %now_x%, %now_y%
Return
GuiClose:
handle_exit:
#x::
DllCall("gdi32.dll\DeleteObject", UInt,hbm_buffer)
DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdd_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdc_buffer)
ExitApp
!+WheelUp:: ; Alt+Shift+WheelUp to zoom in
If zoom != 16
zoom *= 2
Return
!+WheelDown:: ; Alt+Shift+WheelUp to zoom out
If zoom != 2
zoom /= 2
Return
|
I am confused now:
1) Why the main window keeps trembling when user moving it?
2) Is there a way to zoom the mouse cursor?
Thanks! |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 6:10 pm Post subject: |
|
|
| Blablabla wrote: | My Dear Friend holomind:
Wow! What a holomind!
...
Here's my mod base on your code (and I prefer mine ):
I am confused now:
1) Why the main window keeps trembling when user moving it?
2) Is there a way to zoom the mouse cursor?
Thanks! |
Nice to see, somebody uses it
the clickthrough effect is nice, is it done with " +E0x00000020" ?
so the gui never gets activated ?
i have problems using hotkey with Mousewheel on a laptop-touchpad but the idea is good. perhaps i make it fallback to something like alt-shift-arrow-up arrow-down for zoom.
1) the winmove is to slow, so it has a delay i guess. hmm perhaps hide the window until winmove is finished ? another perhaps better way would be to
have the zoom window fullscreen (0,0,A_ScreenHeight, A_ScreenWidth) , and then WinSet Region... Clip the visible part and also use CallDLL Stetchblt to paint in this region.
then no winmove is neededn and it should react much more smooth.
i also would not use delay 0 "SetTimer, Repaint , 0 " , as this uses 100% cpu, and you cant see that fast. 15 or 40 ms (25 or 60 Frames/s) should be enough ?
2) i dont think so , as the mouse is not part of the DC and drawn by hardware directly but you could change the whole mousepointer, and use a bigger one. or a crosshair for example. (dont know how to ahk-script this) |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 8:38 pm Post subject: |
|
|
Hi, i experimented a little bit and solved the flicker problem in a way:
the solution is not beatiful, but works.
now the Desktop (original) is copied to the Magnify image to restore the zoomed areas with the original. to make things faster and not repaint the whole screen all the time it only restores the zoomwindow.
so every second there is a full screen refresh to restore errors. also your desktop could have changed.
i sneaked in some hotkeys. so zoom also works with alt-shift-up down, not only mousewheel, and i can toggle antialize with alt-shilft a.
the bmp buffers are not needed here, they come from another script i copied but here the DCs are copied diretly!
I experimented with "Winset Region" and "Gui Show ..size" and "Winmove" but they all flicker. so this kind of doublebuffer works better.
it would be much better, to only change the size of the Magnifier window, but this flickers
i changed the dimensions to variables so you can change the radius easily.
when you comment "SetTimer, Init" and uncomment "SetTimer, ClipWindow", then you can see how slow the "WinSet Region" is.
i guess the "winset region" forces a full refresh/redraw of the Window!
| Code: | ;original by: holomind
;modified by: Blablabla
;modified again by: holomind ;)
;see more: http://www.autohotkey.com/forum/topic11700.html
#NoTrayIcon
OnExit handle_exit
SetBatchLines, -1
CoordMode, Mouse, Screen
zoom = 2
antialize = 0
refresh_delay = 40
refresh_full = 1000
radius = 400
m_w := radius ; magnifiere_width
m_h := radius
m_wh := m_w / 2 ; half
m_hh := m_h / 2
Gui, +AlwaysOnTop -Resize -Caption -Border +ToolWindow -SysMenu +E0x00000020
Gui,Show, x0 y0 w%A_ScreenWidth% h%A_ScreenHeight% , Magnifier
WinGet MagnifierID, id ,Magnifier
WinSet, Transparent , 254, Magnifier
;retrieve the unique ID number (HWND/handle) of that window
WinGet, SourceWinID, id
hdc_source_frame := DllCall( "GetDC", UInt, SourceWinID )
hdc_target_frame := DllCall( "GetDC", UInt, MagnifierID )
SetTimer, Init , %refresh_full% ; force full refresh 1 each second
SetTimer, Repaint , %refresh_delay%
; SetTimer, ClipWindow, 500
Gosub, Init
Gosub, Repaint
return
Init:
DllCall("gdi32.dll\BitBlt", UInt,hdc_target_frame
, Int , 0
, Int , 0
, Int , A_ScreenWidth
, Int , A_ScreenHeight
, UInt , hdc_source_frame
, Int , 0
, Int , 0
, UInt , 0xCC0020) ; SRCCOPY
Return
Repaint:
MouseGetPos, start_x, start_y ; position of mouse
now_x := start_x - m_wh
now_y := start_y - m_hh
if now_x <> old_x ; only repaint if mouse is moved ?
{
; redraw original desktop
DllCall("gdi32.dll\BitBlt", UInt,hdc_target_frame
, UInt , old_x
, UInt , old_y
, Int , m_w
, Int , m_h
, UInt , hdc_source_frame
, UInt , old_x
, UInt , old_y
, UInt , 0xCC0020) ; SRCCOPY
}
DllCall("gdi32.dll\StretchBlt", UInt,hdc_target_frame
, Int , now_x
, Int , now_y
, Int , m_w
, Int , m_h
, UInt , hdc_source_frame
, Int , start_x - m_wh / zoom
, Int , start_y - m_hh / zoom
, Int , m_w / zoom
, Int , m_h / zoom
, UInt , 0xCC0020) ; SRCCOPY
old_x := now_x
old_y := now_y
Return
ClipWindow:
WinSet, Region, %now_x%-%now_y% W%m_w% H%m_h% , Magnifier
Return
GuiClose:
handle_exit:
#x::
DllCall("gdi32.dll\DeleteDC", UInt,hdc_target_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdc_source_frame )
ExitApp
!+a::
antialize := 4 - antialize
DllCall( "gdi32.dll\SetStretchBltMode", "uint", hdc_target_frame, "int", antialize ) ; Antializing ?
Return
!+WheelUp:: ; Alt+Shift+WheelUp to zoom in
!+Up::
If zoom != 16
zoom *= 2
Return
!+WheelDown:: ; Alt+Shift+WheelUp to zoom out
!+Down::
If zoom != 2
zoom /= 2
Return
|
|
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4428 Location: Pittsburgh
|
Posted: Fri Aug 11, 2006 10:54 pm Post subject: |
|
|
These are very nice scripts! I did not think that a fully functional magnifier can be coded with 50 AHK commands!
I also played a little with both flavors, and found the original fixed window for the magnified image easier to use. Navigation is simpler if a frame is drawn around the magnified area. Also, if it could get partially out of the screen, ugly side effects occur, so we'd better keep this frame fully on screen. Interestingly, semi transparent windows remain invisible, even if the transparency level is set to full opaque (255).
I made a few more trivial changes, like finer control of the magnification, showing the current zoom factor in a TrayTip for a short time after a change and putting the window size in a variable (R) for easy change. | Code: | #NoEnv
SetBatchLines -1
CoordMode Mouse, Screen
OnExit GuiClose
zoom = 2 ; initial magnification, 1..32
Rx = 128 ; half vertical/horizontal side of magnifier window
Ry = 128
Zx := Rx/zoom ; frame x/y size
Zy := Ry/zoom
; GUI to show the magnified image
Gui +AlwaysOnTop +Resize +ToolWindow
Gui Show, % "w" 2*Rx " h" 2*Ry " x0 y0", Magnifier
WinGet MagnifierID, id, Magnifier
WinSet Transparent, 255, Magnifier ; makes the window invisible to magnification
WinGet PrintSourceID, ID
; Frame around magnified area
Gui 2:+AlwaysOnTop -Caption +ToolWindow +0x800000
Gui 2:Color, C
MouseGetPos x, y
Gui 2:Show, % "w" 2*Zx " h" 2*Zy " x" x-Zx " y" y-Zy, Frame
WinSet TransColor, C, Frame
hdd_frame := DllCall("GetDC", UInt, PrintSourceID)
hdc_frame := DllCall("GetDC", UInt, MagnifierID)
SetTimer Repaint, 50 ; flow through
Repaint:
MouseGetPos x, y
xz := In(x-Zx-6,0,A_ScreenWidth-2*Zx) ; keep the frame on screen
yz := In(y-Zy-6,0,A_ScreenHeight-2*Zy)
WinMove Frame,,%xz%, %yz%, % 2*Zx, % 2*Zy
DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*Rx, Int,2*Ry
, UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Zx, Int,2*Zy, UInt,0xCC0020) ; SRCCOPY
Return
GuiSize:
Rx := A_GuiWidth/2
Ry := A_GuiHeight/2
Zx := Rx/zoom
Zy := Ry/zoom
TrayTip,,% "Frame = " Round(2*Zx) " × " Round(2*Zy) "`nMagnified to = " A_GuiWidth "×" A_GuiHeight
Return
GuiClose:
DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
DllCall("gdi32.dll\DeleteDC", UInt,hdd_frame )
ExitApp
^+WheelUp:: ; Ctrl+Shift+WheelUp to zoom in
^+WheelDown:: ; Ctrl+Shift+WheelUp to zoom out
If (zoom < 31 and A_ThisHotKey = "^+WheelUp")
zoom *= 1.189207115 ; sqrt(sqrt(2))
If (zoom > 1 and A_ThisHotKey = "^+WheelDown")
zoom /= 1.189207115
Zx := Rx/zoom
Zy := Ry/zoom
TrayTip,,% "Zoom = " Round(100*zoom) "%"
Return
In(x,a,b) { ; closest number to x in [a,b]
IfLess x,%a%, Return a
IfLess b,%x%, Return b
Return x
} |
Last edited by Laszlo on Sat Aug 12, 2006 3:23 am; edited 1 time in total |
|
| Back to top |
|
 |
holomind
Joined: 11 Mar 2006 Posts: 300 Location: Munich, Germany
|
Posted: Fri Aug 11, 2006 11:11 pm Post subject: |
|
|
| Laszlo wrote: | These are very nice scripts! I did not think that a fully functional magnifier can be coded with 50 AHK commands!
|
to make it even shorter, i recognized the buffers are not used.
so you can remove the codelines with hdc_buffer and hdm_buffer.
due to +E0x20, the magnifier is stuck in the top-left corner. perhaps it could be made "move out of way align top-right ?" when the mouse enters the magnifier region? and snap back when the mouse is in ?
or have a hotkey to move it topleft or top-right ? |
|
| 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
|