Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

ScreenMagnifier


  • Please log in to reply
104 replies to this topic
Icarus
  • Members
  • 851 posts
  • Last active: Jan 02 2012 11:17 AM
  • Joined: 24 Nov 2005
Well,

To share some of my own magnifier experiments, this is something a little different and much simpler, but it does the trick for me.

The primary thing I dont like about the MS magnifier, is the fact that it is too stupid to move the window when my mouse goes inside it (in windowed mode - hate the docked)

So, I thought WinMove would be simple enough to do, only the MS magnifier remembers its location and goes back to it - so, the way I found to be working was to simulate as if the user dragged it, with the mouse.

Run MS Magnifier, in windowed mode, then run this script.

It will move the magnifier window whenever the mouse is inside it.
This makes it much more usable to me.

#SingleInstance Force
#Persistent

OnExit ESC

CoordMode Mouse, Screen

MAGNIFYER_WIN   := "Magnifier ahk_class #32770"
BORDER_BUFFER   := 20   ; This makes sure that the mouse is 
                        ; not on the border of the magnifier
                        ; plus, it allows us to move/size manually
                        ; since the caption is "off limits" for us

IfWinExist %MAGNIFYER_WIN%
    Gosub MonitorMagnifier
Else 
    ExitApp

Return

MonitorMagnifier:
    WinGetPos WX, WY, WW, WH, %MAGNIFYER_WIN%
    MouseGetPos MX, MY, MWin
    
    Offset := WH
    
    If( MX > WX+BORDER_BUFFER ) 
      and ( MY > WY+BORDER_BUFFER ) 
      and ( MX < WX+WW-BORDER_BUFFER ) 
      and ( MY < WY+WH-BORDER_BUFFER ) {        
      
        If( WY+WH/2 > A_ScreenHeight/2 ) 
            Offset := -Offset
            
        MouseClickDrag Left, 0, 0, 0, %Offset%, 0, R
        Click %MX%, %MY%, 0     ; Move the cursor to where we 
                                ; remember it should be
    }
    
    SetTimer MonitorMagnifier, 300
Return

ESC::
    SoundPlay *64
    ExitApp
Return


Newpie
  • Guests
  • Last active:
  • Joined: --
Hello, I admire this zoomer script, good work. I have a simple script I use for work, but I would like to use this zoomer script at the same time as my other scripts.

My basic question is how do I combine my scripts I have already with this script into one so that I may turn on and off the Magnifier script with hitting a button like F10. Is this possible?

GOAL: I would want the "Magnifier script" to be imbedded with my other scripts so I can keep Autohotkey running in the background and just turn on and off the zoomer as necessary in my work.

Thanks for everyone's help in advance.

newpie
  • Guests
  • Last active:
  • Joined: --
I figured out how to do it. Thank you for everyone's time. I do have some other questions, but don't pertain to the magnifier script so I will post in other areas of the forum.

newpie
  • Guests
  • Last active:
  • Joined: --
Hello I have a quick question. How do I change the script in order for it to let me use the mouse on my dual monitor. It won't let me drag my mouse over to the other dual monitor. My main monitor is on the left side and my secondary monitor is on the right side.

GOAL: I need to drag my mouse to the right sided screen and see the box on the left hand side screen.

I appreciate any help

newpie
  • Guests
  • Last active:
  • Joined: --
Hello, is there anyway to this magnifier to work on a dual screen? I posted a question before this one. I appreicate everyone's help.

Icarus
  • Members
  • 851 posts
  • Last active: Jan 02 2012 11:17 AM
  • Joined: 24 Nov 2005
I dont see a reason why not.
Let me check it, stand by.
---
Ok, as it turns out I do not have access to my triple monitor computer now, but, I took the code from the previous page which seems to be a nice implementation, and I do not see anything in the code that should prevent it from working on your entire desktop.

I saw that some of the original postings used A_ScreenWidth (which is considering only the primary monitor) so this is why the version you were using did not work (the magnifier got stuck to the primary monitor right?)

So, for your convenience, I am posting the code that looks good here, let me know if it works ok for you, and if not - tell me whats not working.

Code taken from a post by ivanw

; Autohotkey script "Screen Magnifier"
;=================================================================================
#SingleInstance ignore
Process, Priority, , High
OnExit handle_exit
hotkey, Space,  toggle_follow
hotkey, Escape, GuiClose
hotkey, F18,    GuiClose
; Init variables
  follow    := 1
  ZOOMFX    := 1.189207115
  zoom      := 2
  antialias := 1
  delay     := 10

  whMax     := 400
  wh        := 200
  whMin     := 100

  wwMax     := 800
  ww        := 480
  wwMin     := 200


  mx        := 0
  my        := 0
  mxp       := mx
  myp       := my
  wwD       := 0
  whD       := 0


; Init zoom window

  MouseGetPos, mx, my

  Gui, +AlwaysOnTop  +Owner -Resize -ToolWindow +E0x00000020
  Gui, Show, NoActivate W%ww% H%wh% X-1000 Y-1000, MagWindow ; start offscreen

  WinSet, Transparent  , 254, MagWindow
  Gui, -Caption
  Gui, +Border

  WinGet, PrintSourceID, id
  hdd_frame := DllCall("GetDC", UInt, PrintSourceID)

  WinGet, PrintScreenID,  id, MagWindow
  hdc_frame := DllCall("GetDC", UInt, PrintScreenID)
  if(antialias != 0)
      DllCall("gdi32.dll\SetStretchBltMode", "uint", hdc_frame, "int", 4*antialias)


Gosub, Repaint
return
;=================================================================================
; Input events

WheelUp::       ; zoom in
  if zoom < 4
      zoom *= %ZOOMFX%
return

WheelDown::     ; zoom out
  if zoom > %ZOOMFX%
      zoom /= %ZOOMFX%
return


+WheelDown::    ; larger
  wwD =  32
  whD =  32
  Gosub, Repaint
return

+WheelUp::      ; smaller
  wwD = -32
  whD = -32
  Gosub, Repaint
return

;=================================================================================
; toggle_follow
toggle_follow:
    follow := 1 - follow
return

; Repaint
Repaint:
    CoordMode,   Mouse, Screen
    MouseGetPos, mx, my
    WinGetPos,   wx, wy, ww, wh, MagWindow

    if(wwD != 0)
    {
       ww  += wwD
       wh  += whD
       wwD = 0
       whD = 0
    }

    if(mx != mxp) OR (my !- myp)
    {
        DllCall( "gdi32.dll\StretchBlt"
                , UInt, hdc_frame
                , Int , 2                       ; nXOriginDest
                , Int , 2                       ; nYOriginDest
                , Int , ww-6                    ; nWidthDest
                , Int , wh-6                    ; nHeightDest
                , UInt, hdd_frame               ; hdcSrc
                , Int , mx - (ww / 2 / zoom)    ; nXOriginSrc
                , Int , my - (wh / 2 / zoom)    ; nYOriginSrc
                , Int , ww / zoom               ; nWidthSrc
                , Int , wh / zoom               ; nHeightSrc
                , UInt, 0xCC0020)               ; dwRop (raster operation)

       if(follow == 1)
           WinMove, MagWindow, ,mx-ww/2, my-wh/2, %ww%, %wh%

        mxp = mx
        myp = my
    }

    SetTimer, Repaint , %delay%
return

; GuiClose handle_exit
GuiClose:
handle_exit:
   DllCall("gdi32.dll\DeleteDC"    , UInt,hdc_frame )
   DllCall("gdi32.dll\DeleteDC"    , UInt,hdd_frame )
Process, Priority, , Normal
ExitApp

;=================================================================================


tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Is the 1 I posted for you not what you want newpie?

newpie
  • Guests
  • Last active:
  • Joined: --
Hello I appreciate your post and I can definitely use it. Originally when I posted I tried a program that showed the picture of what was being magnified in a separate box and when you moved the mouse it moved a separate box which magnified the object.

The problem was that the magnification mouse box(the one that you can move with your mouse) doesn't go on the second monitor attached, only the prmary monitor.

I am not sure how to fix it. Thanks for your help and time.



The code is below:

#NoEnv 
SetBatchLines -1 

CoordMode Mouse, Screen 
OnExit GuiClose 
zoom = 2                ; initial magnification, 1..32 
Rx = 300                ; 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 
}

F6:: 
Exit: 
ExitApp


newpie
  • Guests
  • Last active:
  • Joined: --
Don't worry about fixing the code that I mentioned right before this post, I think I like how the other code works anyway (where the zoom box moves with the mouse)

Thanks anyway

Icester
  • Guests
  • Last active:
  • Joined: --
Awesome bit of work. Just 2 questions regarding the holomind's original code (or variants):

1) Is there a way to capture the "window" contents to the clipboard? My IrfanView capture screen will not capture the contents of the GUI window. :(

2) Is there a way to make it work with multiple monitors? I know that you use SysGet instead of A_ScreenWidth, but what about monitors with different resolutions?


Thanks.

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
? Can this be used to build an image slide show presenter with dynamic zoom in/out effects (+ additional fades) and ready would be nice slideshows based on your images.
? How many variants do we have now of this original code? Is the first in the thread "the best"?

holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006

Can this be used to build an image slide show presenter with dynamic zoom in/out effects (+ additional fades) and ready would be nice slideshows based on your images.

in theory it might be possible, in the "real expose clone" script there is a litte animation for resizing screenshots/buffers and even with fade-effect. which means you are able to do it completely with ahk and dll-calls (windows built-in functions). BUT. the speed will not be that great, as you manually repaint the fading images. i guess doing similar with a flash would be more efficient. i guess its better so search for a image-viewer which can show slideshows of your images, i guess its not worth the effort.

see here: akh: real expose clone
  animate_in_delay     = 5 
  animate_in_steps       = 5 
  animate_out_delay    = 5 
  animate_out_steps    = 5 
  show_taskbar          = 1 
  ;fade_in_steps       = 5 
  ;fade_in_delay       = 5 
  ;fade_out_steps      = 5 
  ;fade_out_delay      = 50
you can see in the config-part of the script that you can enable animation (eg. zooming an image from big (fullscreen) to smaller, and also enable fading in/out) which is commented out in the original script, as this may hurt performance)

combining the two scripts might be enough to create a presentation-app.
(perhaps you also need the function to read a directory and load the images from file into the screenbuffer, expose clone uses doublebuffer and keeps invisible copies of your images in memory, this could also be filled with images which come from your harddrive)

you could even change the offset where your image is beeing displayed and thus "move" the zoomed image around.

i guess finally you want to create an image-slideshow with ken-burns effect. perhaps you are happier with a image viewer like here:
presenter with kim-burns effect

How many variants do we have now of this original code? Is the first in the thread "the best"?

i didnt count them, but there are many. there is no "single best one", as all scripts are customized to fit another need. some want it to be fast, others to be comfortable. with keyboard or not etc. the underlying algorithm to read your screen (hdc) and repaint it in a zoomed manner is always nearly the same. only the "gui" changes.
you should read the comments at the variations and choose the one you like best.

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
Thanks for the clarifications.

automaticman
  • Members
  • 658 posts
  • Last active: Nov 20 2012 06:10 PM
  • Joined: 27 Oct 2006
I like Nostalgic screensaver, now I need a version which is free from being a screensaver. (Ideally also supporting the command line.)

canadaman123
  • Guests
  • Last active:
  • Joined: --
Hey, I wasn't able to read all posts between the first pages and here at the end, so this may have already been covered. I liked holomind's version seen here, but it lacked dual monitor support. I've added that feature with the following:

SysGet, TotalScreenWidth, 78
SysGet, TotalScreenHeight, 79

...then just changed out A_ScreenHeight and A_ScreenWidth with those vars:

Repaint:
MouseGetPos x, y
xz := In(x-Rz-6,0,TotalScreenWidth-2*Rz) ; keep the frame on screen
yz := In(y-Rz-6,0,TotalScreenHeight-2*Rz)

Thanks for this great script!