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
holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006
this version is with crosshair (diagonal) from the code from the other thread.

the problem was with missing h_pen.

you can also play with these values for color, style and size/margin of cross
    ;margin to the inside of the region to start drawing the lines
    LineMargin = 50

    ;specify the style, thickness and color of the cross lines
    h_pen := DllCall( "gdi32.dll\CreatePen"
                   , "int", 1
                   , "int", 1
                   , "uint", 0x00333333) 


APP:
#NoEnv
SetBatchLines -1

CoordMode Mouse, Screen
OnExit #x
zoom = 2                ; initial magnification, 1..32
R = 128                 ; half side of magnifier window
Rz := R/zoom
                        ; GUI 2 shows the magnified image
Gui 2:+AlwaysOnTop -Caption +Resize +ToolWindow +E0x20
Gui 2:Show, % "w" 2*R+3 " h" 2*R+3 " 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 +AlwaysOnTop -Caption +ToolWindow +E0x20 +0x800000
Gui Color, 0x00CCCCCC
MouseGetPos x, y
Gui Show, % "w" 2*Rz " h" 2*Rz " x" x-Rz " y" y-Rz, Frame
WinSet TransColor, 0x00CCCCCC, Frame
WinGet FrameID, id , Frame

hdd_frame := DllCall("GetDC", UInt, PrintSourceID)
hdc_frame := DllCall("GetDC", UInt, MagnifierID)
hde_frame := DllCall("GetDC", UInt, FrameID)

;#############   draw cross lines   ###########################################
DrawCross( p_x , p_y, p_w, p_h, dc )
  {

    ;margin to the inside of the region to start drawing the lines
    LineMargin = 50

    ;specify the style, thickness and color of the cross lines
    h_pen := DllCall( "gdi32.dll\CreatePen"
                   , "int", 1
                   , "int", 1
                   , "uint", 0x00333333) 

    ;select the correct pen into DC
    DllCall( "gdi32.dll\SelectObject"
           , "uint", dc 
           , "uint", h_pen )
               
    ;update the current position to specified point
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", dc 
           , "int", p_x+LineMargin
           , "int", p_y+LineMargin
           , "uint", 0)
   
    ;draw a line from the current position up to, but not including, the specified point.
    DllCall( "gdi32.dll\LineTo"
           , "uint", dc 
           , "int", p_x+p_w-LineMargin
           , "int", p_y+p_h-LineMargin)
   
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", dc 
           , "int", p_x+p_w-LineMargin
           , "int", p_y+LineMargin
           , "uint", 0)

    DllCall( "gdi32.dll\LineTo"
           , "uint", dc 
           , "int", p_x+LineMargin
           , "int", p_y+p_h-LineMargin) 
}

SetTimer Repaint, 50   ; flow through

Repaint:
   MouseGetPos x, y
   xz := In(x-Rz-6,0,A_ScreenWidth-2*Rz) ; keep the frame on screen
   yz := In(y-Rz-6,0,A_ScreenHeight-2*Rz)
   WinMove Frame,,%xz%, %yz%, % 2*Rz, % 2*Rz
   DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*R, Int,2*R
   , UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Rz, Int,2*Rz, UInt,0xCC0020) ; SRCCOPY
   DrawCross( 0,0, R,R, hde_frame )
   DrawCross( 0,0, 2*R,2*R, hdc_frame )
   
   inside_old := inside
   inside := (( x < R*2 ) and ( y < R*2 ) ) * R*2 
   if ( %inside_old% <> %inside% )
       WinMove Magnifier,, ,%inside%
   
Return



#x::
   DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
   DllCall("gdi32.dll\DeleteDC", UInt,hdd_frame )
   DllCall("gdi32.dll\DeleteDC", UInt,hde_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
  Rz := R/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
} 


perhaps i will also try a variation with the bitblt xor method later...

Trombonisto
  • Members
  • 7 posts
  • Last active: Jan 19 2007 06:51 AM
  • Joined: 18 Aug 2006
Hi holomind!

Sorry for my bad English and my incapability in AHK. But I want to do my best for improving my knowledge!

Just in time I found your new version. Thank you for all the time you spent for me! If you really want to try it with bitblt, please draw the crosshair upright and not diagonal.

And the poit of your crosshair is allways "between" the pixels but my destination is to find exactly the position of one pixel. So I need a crooshair "through" the pixel. Chould you change that please too?

To your question from today in the morning: No, I don't need a black crosshair. It only should be easy to distinguish from the background.

Thank you again and I wish a nice day. Trombonisto

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

Hi holomind!
Sorry for my bad English and my incapability in AHK. But I want to do my best for improving my knowledge!


I am also not native english, and learning ahk. this forum helps me a lot with it, also the waz lazlo modifies my ahk-scripts and shows me always better ways to do it.

here is the version with bitblt. instead of xor-ing the cross (making it inverse, negative colors) i choose solid black as this is better "readable".
but one can experiment with the 0x00000042 in the later strechblts, in the post above are the allowed values for srccopy etc.

the aiming is a little offset ( you can try by drawing pixels with ms-paint ) then they are off by about 2-10 pixels, so somebody might want to make this script pixel-correct ;)

i found also a new solution where one simply has a small frame over the targetpixel, which is sufficient also.

you can turn on or of the aiming with aim-frame-pixel and/or draw_cross.
simply change from 1 to 0 in the beginning of the script.

it would be possible to make the crosshair smaller by modifying the coordinates. but its not so easy as you have the target and the streched coordinates for the source.
if you only use black color you could also simply strechblt or bitblt from hdd_frame (dest) to hdd_frame and not care about zooming.

now one also needs a slowdown for mouse to find the 1 pixel.
some mouse drivers support this with holding "shift" while moving mouse to have more precision.

due to the "keep frame on screen" the crosshair does not follow correctly on the screenborders.

#NoEnv
SetBatchLines -1

CoordMode Mouse, Screen
OnExit #x
zoom = 8                ; initial magnification, 1..32
R = 128                 ; half side of magnifier window
Rz := R/zoom
config_drawcross := 1 ; 
config_drawaim   := 1 ; 

                        ; GUI 2 shows the magnified image
Gui 2:+AlwaysOnTop -Caption +Resize +ToolWindow +E0x20
Gui 2:Show, % "w" 2*R+3 " h" 2*R+3 " x0 y0", Magnifier
WinGet MagnifierID, id,  Magnifier
WinSet Transparent, 255, Magnifier ; makes the window invisible to magnification
WinGet PrintSourceID, ID

Gui 3:+AlwaysOnTop -Caption +ToolWindow +E0x20 +0x800000
Gui 3:Color, 0x00CCCCCC
Gui 3:Show, % "w" zoom " h" zoom " x" R " y" R "", Aim
WinSet TransColor, 0x00CCCCCC, Aim

if config_drawaim <> 1
	Gui 3:Hide
                        ; Frame around magnified area
Gui +AlwaysOnTop -Caption +ToolWindow +E0x20 +0x800000
Gui Color, 0x00CCCCCC
MouseGetPos x, y
Gui Show, % "w" 2*Rz " h" 2*Rz " x" x-Rz " y" y-Rz, Frame
WinSet TransColor, 0x00CCCCCC, Frame
WinGet FrameID, id , Frame

hdd_frame := DllCall("GetDC", UInt, PrintSourceID)
hdc_frame := DllCall("GetDC", UInt, MagnifierID)
hde_frame := DllCall("GetDC", UInt, FrameID)



SetTimer Repaint, 50   ; flow through

Repaint:
   MouseGetPos x, y
   xz := In(x-Rz-6,0,A_ScreenWidth-2*Rz) ; keep the frame on screen
   yz := In(y-Rz-6,0,A_ScreenHeight-2*Rz)
   m  := zoom  ; margin
   mz := m / zoom
   
   WinMove Frame,,%xz%, %yz%, % 2*Rz, % 2*Rz
  
   ; copy frame to magnifier
   DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*R, Int,2*R
   , UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Rz, Int,2*Rz, UInt,0xCC0020) ; SRCCOPY
 
   if config_drawcross = 1
   	Gosub, DrawCross
 
   inside_old := inside
   inside  := (( x < R*2 ) and ( y < R*2 ) ) * R*2 
   inside2 := (( x < R*2 ) and ( y < R*2 ) ) * R*2 + R -3
   if ( %inside_old% <> %inside% )
   {
    WinMove Magnifier,, ,inside
    WinMove Aim,, ,inside2
   }   
Return

DrawCross:
   ;vertical 
   DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,R-m/2, Int,0, Int,m, Int,2*R
   , UInt,hdd_frame, UInt,xz+Rz-mz/2, UInt,yz-mz/2, Int,mz, Int,2*Rz, UInt,0x00000042) ; SRCCOPY

   ;horizontal
   DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,R-m/2, Int,2*R, Int,m
   , UInt,hdd_frame, UInt,xz-mz/2, UInt,yz+Rz-mz/2, Int,2*Rz, Int,mz, UInt,0x00000042) ; SRCCOPY

   ;restore center point
   DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,R-m/2, Int,R-m/2, Int,m, Int,m
   , UInt,hdd_frame, UInt,xz+Rz-mz/2, UInt,yz+Rz-mz/2, Int,mz, Int,mz, UInt,0xCC0020) ; SRCCOPY

Return


#x::
   DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
   DllCall("gdi32.dll\DeleteDC", UInt,hdd_frame )
   DllCall("gdi32.dll\DeleteDC", UInt,hde_frame )
ExitApp

^+Up::
^+WheelUp::                      ; Ctrl+Shift+WheelUp to zoom in
^+Down::
^+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
  Rz := R/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
} 



Trombonisto
  • Members
  • 7 posts
  • Last active: Jan 19 2007 06:51 AM
  • Joined: 18 Aug 2006
Hello!
Here is my version with a double crosshair.
#NoEnv
SetBatchLines -1

CoordMode Mouse, Screen
OnExit #x
zoom = 6                ; initial magnification, 1..32
R = 128                 ; half side of magnifier window
Rz := R/zoom
                        ; GUI 2 shows the magnified image
Gui 2:+AlwaysOnTop -Caption +Resize +ToolWindow +E0x20
Gui 2:Show, % "w" 2*R+3 " h" 2*R+3 " 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 +AlwaysOnTop -Caption +ToolWindow +E0x20 +0x800000
Gui Color, 0x00CCCCCC
MouseGetPos x, y
Gui Show, % "w" 2*Rz " h" 2*Rz " x" x-Rz " y" y-Rz, Frame
WinSet TransColor, 0x00CCCCCC, Frame
WinGet FrameID, id , Frame

hdd_frame := DllCall("GetDC", UInt, PrintSourceID)
hdc_frame := DllCall("GetDC", UInt, MagnifierID)
hde_frame := DllCall("GetDC", UInt, FrameID)


;#############   draw cross lines   ###########################################
DrawCross( p_x , p_y, p_w, p_h, dc )
  {

    ;margin and position of the lines
    LineMargin = 10
    t = 127
    z = 7
    
    ;specify the style, thickness and color of the cross lines
    h_pen := DllCall( "gdi32.dll\CreatePen"
                   , "int", 0
                   , "int", 1
                   , "uint", 0x00333333)

    ;select the correct pen into DC
    DllCall( "gdi32.dll\SelectObject"
           , "uint", dc
           , "uint", h_pen )
              
    ;update the current position to specified point
    ; 1st Vertical
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", dc
           , "int", LineMargin
           , "int", t
           , "uint", 0)
              
    ;draw a line from the current position up to, but not including, the specified point.
    DllCall( "gdi32.dll\LineTo"
           , "uint", dc
           , "int", p_w-2*LineMargin
           , "int", t) 
            
    ; 2nd vertical
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", dc
           , "int", LineMargin
           , "int", t+z
           , "uint", 0)
              
    DllCall( "gdi32.dll\LineTo"
           , "uint", dc
           , "int", p_w-2*LineMargin
           , "int", t+z) 
            
    ; 1st horizontal
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", dc
           , "int", t
           , "int", LineMargin
           , "uint", 0)

    DllCall( "gdi32.dll\LineTo"
           , "uint", dc
           , "int", t
           , "int", p_h-2*LineMargin)

    ; 2nd horizontal
    DllCall( "gdi32.dll\MoveToEx"
           , "uint", dc
           , "int", t+z
           , "int", LineMargin
           , "uint", 0)

    DllCall( "gdi32.dll\LineTo"
           , "uint", dc
           , "int", t+z
           , "int", p_h-2*LineMargin)
}

SetTimer Repaint, 50   ; flow through

Repaint:
   MouseGetPos x, y
   xz := In(x-Rz+1,0,A_ScreenWidth-2*Rz) ; keep the frame on screen
   yz := In(y-Rz+1,0,A_ScreenHeight-2*Rz)
   WinMove Frame,,%xz%, %yz%, % 2*Rz, % 2*Rz
   DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*R, Int,2*R
   , UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Rz, Int,2*Rz, UInt,0xCC0020) ; SRCCOPY
   DrawCross( 0,0, R,R, hde_frame )
   DrawCross( 0,0, 2*R,2*R, hdc_frame )
   
   inside_old := inside
   inside := (( x < R*2 ) and ( y < R*2 ) ) * R*2
   if ( %inside_old% <> %inside% )
       WinMove Magnifier,, ,%inside%
   
Return



#x::
   DllCall("gdi32.dll\DeleteDC", UInt,hdc_frame )
   DllCall("gdi32.dll\DeleteDC", UInt,hdd_frame )
   DllCall("gdi32.dll\DeleteDC", UInt,hde_frame )
ExitApp

^+Up::
^+WheelUp::                      ; Ctrl+Shift+WheelUp to zoom in
^+Down::
^+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
  Rz := R/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
}
I am satisfied with it, but only in one magnification. If I change the zoom the lines get offset.

How can I bring variables e.g. the variable R and zoom into the drawing section in the GDI functions? I tried R, "R" and %R% but nothing works. Nowhere in the net I could find a help site for this GDI functions. Could you help me please?!

Beside the double crosshair I changed
xz := In(x-Rz-6,0,A_ScreenWidth-2*Rz)
to
xz := In(x-Rz+1,0,A_ScreenWidth-2*Rz)
So I think the crosshair shows now the actual pixel.

Thank you and greetings.

Trombonisto

holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006
DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*R, Int,2*R
   , UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Rz, Int,2*Rz, UInt,0xCC0020) ; SRCCOPY 

this already shows the usage of "R" in the DllCall.

your problem is that DrawCross is a "Function" and all Variables from outside the function like "R" are not "visible". you can only access variables given as parameters like p_x, p_y etc. (so you could add additional variables like R to the parameterlist. ) maybe a good programmingstyle.
or you use the quick and dirty solution and define R as global inside the function and use it like you intended.

e.g. add more parameters
;#############   draw cross lines   
DrawCross( p_x , p_y, p_w, p_h, dc , R)
  {
...

or using globals
;#############   draw cross lines   
DrawCross( p_x , p_y, p_w, p_h, dc )
  {
    global R
...

the ahk-documentation for using "global" is here:
http://www.autohotke...ions.htm#Locals


documentation for the DllCalls can be found in MSDN (Micro Soft Developer Network) which is referenced often in this forum. This MSDN documentation is often quite confusing and very "technical" with lots of geek-speek like DC vor DeviceContext. so you should look if you find an example in plain english in this AHK-Forum where somebody used this DllCall before, and then jump into MSDN. ;)
eg. hdc_frame is short for "Hardware-Device-Context-Frame" and means in plain english "The canvas of your window where the pixel are drawn".
i only use dll-calls when this function is not available in ahk and otherwise avoid VB or C# which is quite complicated (compared to the result you get).

A start with available GDI-Functions would be here:
http://msdn.microsof...itmaps_87eb.asp

Example "api" for BitBlt
BOOL BitBlt(
  HDC hdcDest, // handle to destination DC
  int nXDest,  // x-coord of destination upper-left corner
  int nYDest,  // y-coord of destination upper-left corner
  int nWidth,  // width of destination rectangle
  int nHeight, // height of destination rectangle
  HDC hdcSrc,  // handle to source DC
  int nXSrc,   // x-coordinate of source upper-left corner
  int nYSrc,   // y-coordinate of source upper-left corner
  DWORD dwRop  // raster operation code
);

this gives you hints how to use the dllcall. "HDC" and "int" are of type Int or Uint in AHK-DllCall. etc. its best to search in this forum if somebody has used it, and if you want to use a "new" function you need to figure it out yourself with the help of msdn. on windows2000 or windowsXP you can call most of the GDI or GDI+/GdiPlus functions directly as they are built into windows (they reside in the windows/system32 folder). on some systems you need to download gdiplus.dll.

Trombonisto
  • Members
  • 7 posts
  • Last active: Jan 19 2007 06:51 AM
  • Joined: 18 Aug 2006
Hello holomind!

It took a while to twig that e.g. the R value already via parameter by calling the function comes into the function. Now I understand that a little better.

Meanwhile I changed the script in some details. I made a double cross for better finding the pixel. The crosshair is no longer offset the mousepoint in no zoom. I added Hotkeys for moving the mouse by the arrowkeys together with the Win Key.

For my purpose it is not good to keep the frame on screen so I deleted that section.

And I modifed the way to avoid the collision between magnifier and magnified area.

Here is my code:
#NoEnv
SetBatchLines -1

CoordMode Mouse, Screen
OnExit #x
  zoom = 8                ; initial magnification, 1..32
  halfside = 128          ; circa halfside of the magnifier
  part := halfside/zoom
  Rz := Round(part)
  R := Rz*zoom
  LineMargin := 10 
                        ; GUI 2 shows the magnified image
Gui 2:+AlwaysOnTop -Caption +Resize +ToolWindow +E0x20
Gui 2:Show, % "w" 2*R+zoom+3 " h" 2*R+zoom+3 " 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 +AlwaysOnTop -Caption +ToolWindow +E0x20 +0x800000
Gui Color, 0x00CCCCCC
MouseGetPos x, y
Gui Show, % "w" 2*Rz " h" 2*Rz " x" x-Rz " y" y-Rz, Frame
WinSet TransColor, 0x00CCCCCC, Frame
WinGet FrameID, id , Frame

hdd_frame := DllCall("GetDC", UInt, PrintSourceID)
hdc_frame := DllCall("GetDC", UInt, MagnifierID)

;#############   draw cross lines   ###########################################
DrawCross( M_C , R_C, zoom_c, dc )
  {
        ;specify the style, thickness and color of the cross lines
    h_pen := DllCall( "gdi32.dll\CreatePen", "int", 0, "int", 1, "uint", 0x0000FF)
        ;select the correct pen into DC
    DllCall( "gdi32.dll\SelectObject", "uint", dc, "uint", h_pen )         
        ;update the current position to specified point - 1st horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", M_C, "int", R_C, "uint", 0)
        ;draw a line from the current position up to, but not including, the specified point.
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", R_C)
        ; 2nd horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", M_C, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", R_C+zoom_c)
        ; 3rd horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", R_C, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", 2*R_C+zoom_c-M_C, "int", R_C)
        ; 4th horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", 2*R_C+zoom_c-M_C, "int", R_C+zoom_c)       
        ; 1st vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C, "int", M_C, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", R_C)
        ; 2nd vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", M_C, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C+zoom_c, "int", R_C)
        ; 3rd vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", 2*R_C+zoom_c-M_C)
        ; 4th vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C+zoom_c, "int", 2*R_C+zoom_c-M_C)
}
SetTimer Repaint, 50   ; flow through

Repaint:
     MouseGetPos x, y
     xz := x-Rz
     yz := y-Rz
     WinMove Frame,,%xz%, %yz%, % 2*Rz, % 2*Rz
     DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*R+zoom, Int,2*R+zoom
     , UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Rz+1, Int,2*Rz+1, UInt,0xCC0020) ; SRCCOPY
     
     DrawCross( LineMargin, R, zoom, hdc_frame )
     
                          ; keep the frame outside the magnifier
     If (x < (2*R+zoom+8) and y < (2*R+zoom+8))
        WinMove Magnifier,, ,(2*R+zoom+8)
     Else
        WinMove Magnifier,,0 ,0

Return

#x::
     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" or A_ThisHotKey ="#+") )
       zoom *= 1.189207115         ; sqrt(sqrt(2))
    If (zoom >  1 and ( A_ThisHotKey = "^+WheelDown" or A_ThisHotKey = "#-"))
       zoom /= 1.189207115
    
    part := halfside/zoom           ;new calculation of the magnified image
    Rz := Round(part)
    R := Rz*zoom
    Gui 2:Show, % "w" 2*R+zoom+3 " h" 2*R+zoom+3 " x0 y0", Magnifier
    TrayTip,,% "Zoom = " Round(100*zoom) "%"
   
Return

      ; Mouse slow down:
      ; The first parameter is always 0x71 (SPI_SETMOUSESPEED).
      ; The third parameter is the speed (range is 1-20, 10 is default).
F9::
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 3, UInt, 0)
    KeyWait F9  ; This prevents keyboard auto-repeat from doing the DllCall repeatedly.
return

F9 up::
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 10, UInt, 0)
Return

;Mouse move one step with arrow keys
#Up::
    MouseMove, 0, -1, 0, R
Return

#Down::
    MouseMove, 0, 1, 0, R
Return

#Left::
    MouseMove, -1, 0, 0, R
Return

#Right::
    MouseMove, 1, 0, 0, R
Return
I also tried to slow the motion of the mouse, see ;Mouse slow down. The code from <!-- m -->http://www.autohotke... ... 3934#33934<!-- m --> worked in a seprerate script very well but here it don't work. Do you know why?

I hope this will be my last ask in that matter. :lol:

Thank you so much for all your help and advises, Laszlo too.

Greetings

Trombonisto

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

your script works quite good. also the red crosshair makes it easy to find the pixel.
my guess is that keywait, stops the whole script "while" this key is pressed.
and therefore it also stops the repaint of frame and magnifier.

one solution could be to have an hotkey to make mouse slow and another to make it fast. so you dont hold the key but only "click it" press+release.

another trick could be to unregister the hotkey "f9" so it does not get repeated calls. and re-register it when you press "f9 up".
on the other hand it would not hurt (perhaps only speed) to have set the SystemSpeedParametersInfo multiple times.
if windows is smart enough it will detect that the value is already 3 and not execute the write operation. (reads should be fast and writes should be slow)

or you do a manual "bugfixing" and save the state of the mousespeed, similar to the thing i use for toggle antialize on and off.

e.g.
F9::
   if  mouse_slow = 
   {
; http://msdn.microsoft.com/library/default.asp?url=/library/en-

us/sysinfo/base/getting_hardware_information.asp
; http://www.autohotkey.com/forum/topic5264.html
       ; you could even read the current mousespeed for later use ?
       ; maybe not every body uses speed=10 ?
       ; my guess is that SysParaInfo will return the current speed

    DllCall("SystemParametersInfo", UInt, 0x70, UInt, 0, UIntP, mouse_speed_old, UInt, 0) ; 

important UintP (eg. return P(ointer) ?) 
    TrayTip,, your old mousespeed was %mouse_speed_old% , setting to 3
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 3, UInt, 0)
    mouse_slow = 1
   }
return

F9 up::
       
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, mouse_speed_old, UInt, 0)
    TrayTip,, restoring your mousespeed to  %mouse_speed_old%
    mouse_slow = 
return


i noticed your script is *really* slow, the problem lies with the many move and drawlines, which are to slow if you do them on a each 50ms (20frames a second).
as you do not often change the zoomfactor you could draw an empty frame (black or white) and your doublecross. then bitblit this region into an invisible buffer (created with createcompatibleDC and bitmap...)
and then after the bitblit for source2target (eg. frame into magnifier) you do another bitblit to "restore" the doublecross from the buffer.
this will be much faster and more smooth.
there is also a pattern mode for bitblt so perhaps you can define your doublecross as a mask and apply it directly while doing the bitblt ?

holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006
just another idea to make it faster.
as you only draw horizontal and vertical red lines you can also do this with bitblt. setting color to red and using the rectangle for destination as the line. making it only one pixel wide or only one pixel high. using blitmode solid color. (or black).

holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006
now the idea of using bitblt to draw black lines applied.
(the lines go offset if you change zoom, i didnt understand the usage of M_C and R_C and zoom_c. so it does not adopt. i only want to show, how to use bitblt to draw lines (by copying black pixels from the DC to itself)
or in other words. fill a rectangle which is only one pixel high or wide.
perhaps this is faster as the drawline algorythm, as there is no need to detect the steps and angles. but lines are drawn by hardware-accelleration so one should not see a difference. also if the programmers implementing the line algo were smart they use bitblt for horizontal and vertical lines anyways.

one difference is that you can draw a line with one dll-call with drawline you have 2 dllcalls, one for move (define start) and draw (to define end).

you could make the cross even with less dllcalls (4) if you first draw the black cross (1hor 1 ver) and then repaint the inside of the cross not with copy-style solid but copy-style src-copy (frame2magnifiert) which needs more calulation for the right coordinates (you need strechblt and cant do it with bitblt)
bitblt: copy without zoom from src to dest. so you only define the start of src. (src-witdh/heihght are same with dest.w/h !)
strechblt: copy with zoom, so you define both rectangles src + dest for the drawing engine to know what to do.

after applying this change , the reactiontime was still slow, so maybe the drawline dllcalls arent so bad.

the problem was with your "optimization" of the move-magnifier.
in honor of lazlo i used supercompressed codestyle to move the window only when it changed. you removed this from your script and winmove (which is painfully slow) was called every repaint (and not only when it changes).
AHK is not smart enough to detect that the new position is the same and nothing is needed to be done. but on some posts in this forum this "bug" is used to force a repaint of the window calling winmove with old or no position.

so here my modified script:
* changed drawlines to bitblit draw horizontal vertial (note that this will never work with diagonal lines!)
* bugfixed the move-away function to make the script react much faster.

you can simply exchange the DrawCross function with the old one if you want your red lines back (which probably are not as slow as i suggested)

#NoEnv
SetBatchLines -1

CoordMode Mouse, Screen
OnExit #x
  zoom = 8                ; initial magnification, 1..32
  halfside = 128          ; circa halfside of the magnifier
  part := halfside/zoom
  Rz := Round(part)
  R := Rz*zoom
  LineMargin := 10
                        ; GUI 2 shows the magnified image
Gui 2:+AlwaysOnTop -Caption +Resize +ToolWindow +E0x20
Gui 2:Show, % "w" 2*R+zoom+3 " h" 2*R+zoom+3 " 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 +AlwaysOnTop -Caption +ToolWindow +E0x20 +0x800000
Gui Color, 0x00CCCCCC
MouseGetPos x, y
Gui Show, % "w" 2*Rz " h" 2*Rz " x" x-Rz " y" y-Rz, Frame
WinSet TransColor, 0x00CCCCCC, Frame
WinGet FrameID, id , Frame

hdd_frame := DllCall("GetDC", UInt, PrintSourceID)
hdc_frame := DllCall("GetDC", UInt, MagnifierID)

;#############   draw cross lines   ###########################################
DrawCross( M_C , R_C, zoom_c, dc )
  {


   ;vertical
   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,R_C, Int,0, Int,1, Int,R_C
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)

   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,R_C+M_C-2, Int,0, Int,1, Int,R_C
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)

   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,R_C, Int,R_C+M_C, Int,1, Int,R_C
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)

   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,R_C+M_C-2, Int,R_C+M_C, Int,1, Int,R_C
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)

   ;horizontal
   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,1, Int,R_C, Int,R_C, Int,1
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)

   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,1, Int,R_C+M_C, Int,R_C, Int,1
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)

   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,R_C+M_C-1, Int,R_C, Int,R_C, Int,1
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)

   DllCall("gdi32.dll\BitBlt", UInt,dc, Int,R_C+M_C-1, Int,R_C+M_C, Int,R_C, Int,1
   , UInt,dc, UInt,0, UInt,0, UInt,0x00000042) ; SOLID_BLACK (42)


}
SetTimer Repaint, 50   ; flow through

Repaint:
     MouseGetPos x, y
     xz := x-Rz
     yz := y-Rz
     WinMove Frame,,%xz%, %yz%, % 2*Rz, % 2*Rz
     WinGetPos, mx, my, mw,mh, Magnifier
     DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*R+zoom, Int,2*R+zoom
     , UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Rz+1, Int,2*Rz+1, UInt,0xCC0020) ; SRCCOPY
     
     DrawCross( LineMargin, R, zoom, hdc_frame )
     
     ; keep the frame outside the magnifier

     If (x < (2*R+zoom+8) and y < (2*R+zoom+8))
           pos_new := (2*R+zoom+8)
     Else
           pos_new := 0

    if ( pos_old <> pos_new )
        WinMove Magnifier,, ,pos_new
    
    pos_old := pos_new
    
Return

#x::
     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" or A_ThisHotKey ="#+") )
       zoom *= 1.189207115         ; sqrt(sqrt(2))
    If (zoom >  1 and ( A_ThisHotKey = "^+WheelDown" or A_ThisHotKey = "#-"))
       zoom /= 1.189207115
   
    part := halfside/zoom           ;new calculation of the magnified image
    Rz := Round(part)
    R := Rz*zoom
    Gui 2:Show, % "w" 2*R+zoom+3 " h" 2*R+zoom+3 " x0 y0", Magnifier
    TrayTip,,% "Zoom = " Round(100*zoom) "%"
   
Return

      ; Mouse slow down:
      ; The first parameter is always 0x71 (SPI_SETMOUSESPEED).
      ; The third parameter is the speed (range is 1-20, 10 is default).
F9::
   if  mouse_slow = 
   {
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getting_hardware_information.asp
; http://www.autohotkey.com/forum/topic5264.html
       ; you could even read the current mousespeed for later use ?
       ; maybe not every body uses speed=10 ?
       ; my guess is that SysParaInfo will return the current speed

    DllCall("SystemParametersInfo", UInt, 0x70, UInt, 0, UIntP, mouse_speed_old, UInt, 0) ; important UintP (eg. return P(ointer) ?) 
    TrayTip,, your old mousespeed was %mouse_speed_old% , setting to 3
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 3, UInt, 0)
    mouse_slow = 1
   }
return

F9 up::
       
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 10, UInt, 0)
    TrayTip,, restoring your mousespeed to  %mouse_speed_old%
    mouse_slow = 
return


;Mouse move one step with arrow keys
#Up::
    MouseMove, 0, -1, 0, R
Return

#Down::
    MouseMove, 0, 1, 0, R
Return

#Left::
    MouseMove, -1, 0, 0, R
Return

#Right::
    MouseMove, 1, 0, 0, R
Return 


holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006
i remembered that the little frame also uses a lot of winmoves, which i learned is slow.

actually you dont need the frame (as you have your mouse there and the real value is small when you only want to find the right pixel.

so this version without any winmoves is really smooth, updating your zoomed area without noticable delay.

* this version is with red lines again,
* the #up etc. is compressed to oneliners
* little bit more comments inside code

#NoEnv
SetBatchLines -1

CoordMode Mouse, Screen
OnExit #x
  zoom = 8                ; initial magnification, 1..32
  halfside = 128          ; circa halfside of the magnifier
  part := halfside/zoom
  Rz := Round(part)
  R := Rz*zoom
  LineMargin := 10
                        ; GUI 2 shows the magnified image
Gui 2:+AlwaysOnTop -Caption +Resize +ToolWindow +E0x20
Gui 2:Show, % "w" 2*R+zoom+3 " h" 2*R+zoom+3 " 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)

;#############   draw cross lines   ###########################################
DrawCross( M_C , R_C, zoom_c, dc )
  {
        ;specify the style, thickness and color of the cross lines
    h_pen := DllCall( "gdi32.dll\CreatePen", "int", 0, "int", 1, "uint", 0x0000FF)
        ;select the correct pen into DC
    DllCall( "gdi32.dll\SelectObject", "uint", dc, "uint", h_pen )         
        ;update the current position to specified point - 1st horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", M_C, "int", R_C, "uint", 0)
        ;draw a line from the current position up to, but not including, the specified point.
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", R_C)
        ; 2nd horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", M_C, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", R_C+zoom_c)
        ; 3rd horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", R_C, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", 2*R_C+zoom_c-M_C, "int", R_C)
        ; 4th horizontal
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", 2*R_C+zoom_c-M_C, "int", R_C+zoom_c)       
        ; 1st vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C, "int", M_C, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", R_C)
        ; 2nd vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", M_C, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C+zoom_c, "int", R_C)
        ; 3rd vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C, "int", 2*R_C+zoom_c-M_C)
        ; 4th vertical
    DllCall( "gdi32.dll\MoveToEx", "uint", dc, "int", R_C+zoom_c, "int", R_C+zoom_c, "uint", 0)
    DllCall( "gdi32.dll\LineTo", "uint", dc, "int", R_C+zoom_c, "int", 2*R_C+zoom_c-M_C)
} 
SetTimer Repaint, 50   ; flow through

Repaint:
     MouseGetPos x, y
     xz := x-Rz
     yz := y-Rz

     DllCall("gdi32.dll\StretchBlt", UInt,hdc_frame, Int,0, Int,0, Int,2*R+zoom, Int,2*R+zoom
     , UInt,hdd_frame, UInt,xz, UInt,yz, Int,2*Rz+1, Int,2*Rz+1, UInt,0xCC0020) ; SRCCOPY
     
     DrawCross( LineMargin, R, zoom, hdc_frame )
     
     ; keep the frame outside the magnifier and precalculate wanted position
     If (x < (2*R+zoom+8) and y < (2*R+zoom+8))
           pos_new := (2*R+zoom+8)
     Else
           pos_new := 0

     if ( pos_old <> pos_new )          ; only move if the real position of window needs to change
        WinMove Magnifier,, ,pos_new
    
     pos_old := pos_new     ; store value for next loop
    
Return

#x::
     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" or A_ThisHotKey ="#+") )
       zoom *= 1.189207115         ; sqrt(sqrt(2))
    If (zoom >  1 and ( A_ThisHotKey = "^+WheelDown" or A_ThisHotKey = "#-"))
       zoom /= 1.189207115
   
    part := halfside/zoom           ;new calculation of the magnified image
    Rz := Round(part)
    R := Rz*zoom
    Gui 2:Show, % "w" 2*R+zoom+3 " h" 2*R+zoom+3 " x0 y0", Magnifier
    TrayTip,,% "Zoom = " Round(100*zoom) "%"
   
Return

      ; Mouse slow down:
      ; The first parameter is always 0x71 (SPI_SETMOUSESPEED).
      ; The third parameter is the speed (range is 1-20, 10 is default).
F9::
   if  mouse_slow = 
   {
      ; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getting_hardware_information.asp
      ; http://www.autohotkey.com/forum/topic5264.html

    DllCall("SystemParametersInfo", UInt, 0x70, UInt, 0, UIntP, mouse_speed_old, UInt, 0) ; important UintP (eg. return P(ointer) ?) 
    TrayTip,, your old mousespeed was %mouse_speed_old% , setting to 3
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 3, UInt, 0)
    mouse_slow = 1
   }
return

F9 up::
    DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 10, UInt, 0)
    TrayTip,, restoring your mousespeed 
    mouse_slow = 
return

;Mouse move one step with arrow keys
#Up::MouseMove, 0, -1, 0, R

#Down::MouseMove, 0, 1, 0, R

#Left::MouseMove, -1, 0, 0, R

#Right::MouseMove, 1, 0, 0, R


holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006
with very little more code this could be made into a colorpicker, showing the colors in RGB and #HEXHEX for html usage.
with an hotkey to copy the targeted pixel-color into clipboard.

eg. (dont know if this works, may be black or white if it captures mouse-pointer color)
<!-- m -->http://www.autohotke... ... lor colour<!-- m -->

^!z::  Control+Alt+Z hotkey.
MouseGetPos, MouseX, MouseY
PixelGetColor, color, %MouseX%, %MouseY%
MsgBox The color at the current cursor position (%Mousex%,%MouseY%) is %color%.
return

documentation:
<!-- m -->http://www.autohotke... ... tColor.htm<!-- m -->

or similar to this:
<!-- m -->http://www.autohotke... ... lor colour<!-- m -->
(showing color hexvalue on top)


<!-- m -->http://www.autohotke...c/Clipboard.htm<!-- m -->
copying the value into clipboard
#c::
  clipboard = "your color here"
return


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

Would it be possible to save the current image (as bitmap)?


yes !!! ;)

http://www.autohotke...pic.php?t=12012

Trombonisto
  • Members
  • 7 posts
  • Last active: Jan 19 2007 06:51 AM
  • Joined: 18 Aug 2006

with very little more code this could be made into a colorpicker, showing the colors in RGB and #HEXHEX for html usage.
with an hotkey to copy the targeted pixel-color into clipboard.

Yes this is possible but no my destination. I want to transfer the coordinates of drawings or graphs to an Excel spreadsheet.

The bitblt version don't satisfied me. But your last improvement of my version works very well. Thank you! :D I think in that kind I will use it in future.

Now I have a Problem with sending the coordinates. With a hotkey I start the following:
WinGet, active_id, ID, A
CoordMode, Mouse
MouseGetPos, xpos, ypos 
clipboard = ; Empty the clipboard
clipboard = %xpos%%A_Tab%%ypos%  ;A_Tab for fill in two Excel columns
IfWinExist, Microsoft Excel
	WinActivate ; use the window found above
Send ^v
Send {DOWN}
WinActivate, ahk_id %active_id% ;aktivate the window before
If works but always changing the window makes nervous. For sending in the background Laszlo recommended in this thread CONTROLSEND:
CoordMode, Mouse
MouseGetPos, xpos, ypos 
clipboard = ; Empty the clipboard
clipboard = %xpos%%A_Tab%%ypos%  
ControlSend, , ^v, Microsoft Excel
ControlSend, , {ENTER}, Microsoft Excel
WinActivate, ahk_id %active_id% ;aktivate the window before
If Excel is in the foreground it works, otherwise not! I tried Unbenannt - Editor instead of Excel. The same result. :?:
For testing I inserted
ControlSend, , It works, Unbenannt - Editor
ControlSend, , {ENTER}, Unbenannt - Editor
The words I can read but no pixel position. But I checked - they are in the clipbord.
Also SetKeyDelay didn't help.
It is very strange to me! I have no idea furthermore.

A confused Trombonisto

holomind
  • Members
  • 341 posts
  • Last active: Aug 23 2015 03:27 PM
  • Joined: 11 Mar 2006
hi, sending keystrokes is not perfectly stable.

but this one works quite good for me
F9::
    CoordMode, Mouse
	MouseGetPos, xpos, ypos
	clipboard = %xpos%%A_Tab%%ypos%
    sleep, 50
	ControlSend, Edit1 , ^v, ahk_class XLMAIN
    sleep, 50
	ControlSend, Edit1 , {down}, ahk_class XLMAIN
return

#x::ExitApp

i can even collect many points while pressing F9.
but sometimes the {ctrl} from ^v is mixed up with the {down}
and jumps to excel end {ctrl down}.
this sleep 50 helps a little bit but "sendkeywait" may be better.
on my excel version the {enter} did not work.
i looked for the ahk_class with windowspy. (rightclick the trayicon of ahk near your clock and choose "Window Spy" from menu.
this way it always grabs excel and does not look for the windowtitle.
but perhaps its better to use wintitle (eg. if you have many different excels open?)

IMO it would be better not to send the coordinates on every click/keypress but to collect them and send them all at once with another hotkey.
then you avoid random errors with ctrl+down. and also it should be faster as you dont send messages to excel all the time.

seems you do something similar to defining an imagemap. the edges. so it would be good enough to collect the whole edges/corners into a variable and send them later.
you even could write them to file directly without excel using .csv format and AHK write to file function.

you can use my livewindows script to watch your excel which can be in background. and watch how the numbers are entered.

http://www.autohotke...topic11588.html
run the livewindows.exe , then activate excel , then press win-w, and you have excel always visible. you can zoom in a little bit by defining a region with strg-shift left-mouse down + drag + mouse up.

Trombonisto
  • Members
  • 7 posts
  • Last active: Jan 19 2007 06:51 AM
  • Joined: 18 Aug 2006
Hi holomind!

Thank you again for all your help. That's really great!

No, I'm not working with imagemaps. I get graphs of mathematical functions (Kurvenscharen) and have to find the best fitting function. In the past I printed the PDFs out and took a simple ruler. That's a stone age method.

With help of the current script it is already much more easy and more precise. For me the script now works good enough but I thought about to give a compiled version to friends working at similar tasks. That's why I e.g. couldn't use .csv files, unfortunately.

To collect the coordinates seems to be a very good idea! But multidimensional arrays I couldn't handle, may be caused by the early time :wink: The help file isn't very helpful for working with arrays. And in the forum until now I only found one dimensional arrays.

BTW the livewindows script sounds good. I will try it - tomorrow. Good night

Tombonisto