Search code examples
autoit

How to add crosshairs to magnifying glass?


I'm stuck adding crosshairs to the magnifying glass. This is what my source code is based on:

#include <GUIConstants.au3>

$MagWidth = 50
$MagHeight = 50
$MagZoom = 3

Global $dll[3], $DeskHDC, $GUIHDC

$dll[1] = DllOpen ( "user32.dll")
$dll[2] = DllOpen ( "gdi32.dll")

Global $GUI = GUICreate ("Zoom x2 Au3", $MagWidth * $MagZoom, $MagHeight * $MagZoom, _
    MouseGetPos (0), MouseGetPos (1), $WS_POPUP+$WS_BORDER, $WS_EX_TOPMOST)
Global $divider_x = GUICtrlCreateGraphic(5,25,$MagWidth * $MagZoom,1)

GUISetState(@SW_SHOW)

Global $LastPos[2] = [0,0]

While 1
    MAG()
    $MousePos = MouseGetPos()
    If ($LastPos[0] <> $MousePos[0] Or $LastPos[1] <> $MousePos[1]) Then
        WinMove("Zoom x2 Au3", "", $MousePos[0] + $MagWidth/2 + 5, $MousePos[1])
        $LastPos[0] = $MousePos[0]
        $LastPos[1] = $MousePos[1]
    EndIf

    Sleep(10)
WEnd

Func MAG()
    $DeskHDC = DLLCall("user32.dll","int","GetDC","hwnd",0)
    $GUIHDC = DLLCall("user32.dll","int","GetDC","hwnd",$GUI)
    If Not @error Then
        DLLCall("gdi32.dll", "int", "StretchBlt", "int", $GUIHDC[0], "int", _
            0, "int", 0, "int", $MagWidth * $MagZoom, "int", $MagHeight * $MagZoom, "int", $DeskHDC[0], "int", _
            MouseGetPos (0) - $MagWidth/2, "int", MouseGetPos (1) - $MagHeight/2, "int", $MagWidth ,"int", $MagHeight, _
            "long", $SRCCOPY)
        DLLCall("user32.dll","int","ReleaseDC","int",$DeskHDC[0],"hwnd",0)
        DLLCall("user32.dll","int","ReleaseDC","int",$GUIHDC[0],"hwnd",$GUI)
    EndIf
EndFunc

Func OnAutoItExit()
    DllClose ( $dll[1] )
    DllClose ( $dll[2] )
EndFunc

I tried adding thin lines using GUICtrlCreateGraphic() and GUICtrlCreateLabel() but that just reduces the magnified display on the GUI's window. How do I add a crosshair?


Solution

  • Here I show you a solution, I've made some time:

    #include <WindowsConstants.au3>
    #include <WinAPI.au3>
    #include <StructureConstants.au3>
    OnAutoItExitRegister('OnAutoItExit')
    
    Global $iMagZoom = 5
    
    
    Global $iMagWidth = Ceiling(100/$iMagZoom)
    Global $iMagHeight = Ceiling(100/$iMagZoom)
    
    Global $hDCDesk, $hDCZoom, $hPen
    Global $hUser32 = DllOpen("user32.dll")
    Global $hGDI32 = DllOpen("gdi32.dll")
    
    Global $__hMouseProc = DllCallbackRegister("_MouseProc", "long", "int;wparam;lparam")
    Global $__hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($__hMouseProc), _WinAPI_GetModuleHandle(0))
    
    Global $hCross = GUICreate('', 48, 48, -1, -1, $WS_POPUP, $WS_EX_TOPMOST)
    WinSetTrans($hCross, '', 10)
    GUISetCursor(3, 1, $hCross)
    
    Global $hZoom = GUICreate("Zoom Window", $iMagWidth * $iMagZoom, $iMagHeight * $iMagZoom, _
        MouseGetPos(0), MouseGetPos(1), $WS_POPUP+$WS_BORDER, $WS_EX_TOPMOST)
    
    GUISetState(@SW_SHOW, $hCross)
    GUISetState(@SW_SHOW, $hZoom)
    
    ; once at start, than from mouse-callback-function
    _Magnify()
    
    
    While 1
        Sleep(10)
    WEnd
    
    Func _ende()  ; called by mouse left click
        Exit
    EndFunc
    
    Func _Magnify($_iX=-1, $_iY=-1)
        Local Static $fInit = True
        If $fInit Then
            $fInit = False
            $hDCDesk = (DLLCall($hUser32, "int", "GetDC", "hwnd", 0))[0]
            $hDCZoom = (DLLCall($hUser32, "int", "GetDC", "hwnd", $hZoom))[0]
            $hPen = (DLLCall($hGDI32, "int", "CreatePen", "int", 0, "int", 3, "int", 0x00800000))[0] ; 0=PS_SOLID, dark-blue (0x00BBGGRR)
            DLLCall($hGDI32, "int", "SelectObject", "int", $hDCZoom, "hwnd", $hPen)
            $_iX = MouseGetPos(0)
            $_iY = MouseGetPos(1)
        EndIf
        Local $iW = $iMagWidth * $iMagZoom, $iH = $iMagHeight * $iMagZoom
        If Not @error Then
            DLLCall($hGDI32, "int", "StretchBlt", "int", $hDCZoom, "int", _
                0, "int", 0, "int", $iW, "int", $iH, "int", $hDCDesk, "int", _
                $_iX - $iMagWidth/2, "int", $_iY - $iMagHeight/2, "int", $iMagWidth ,"int", $iMagHeight, _
                "long", $SRCCOPY)
            ; draw the crosshair
            _GDI32_DrawLine($hDCZoom, ($iW/2)-2, $iH/8, ($iW/2)-2, 3*($iH/8), $hGDI32)     ; vertical
            _GDI32_DrawLine($hDCZoom, ($iW/2)-2, 5*($iH/8), ($iW/2)-2, 7*($iH/8), $hGDI32) ; vertical
            _GDI32_DrawLine($hDCZoom, $iW/8, ($iH/2)-2, 3*($iW/8), ($iH/2)-2, $hGDI32)     ; horicontal
            _GDI32_DrawLine($hDCZoom, 5*($iW/8), ($iH/2)-2, 7*($iW/8), ($iH/2)-2, $hGDI32) ; horicontal
        EndIf
    EndFunc
    
    Func _GDI32_DrawLine(ByRef $_hDC, $_iX0, $i_Y0, $_iX1, $i_Y1, $_hDll=-1)
        If $_hDll = -1 Then $_hDll = "gdi32.dll"
        Local $tCurrent = DllStructCreate("struct; long X;long Y; endstruct")
        DllCall($_hDll, "int", "MoveToEx", "int", $_hDC, "int", $_iX0, "int", $i_Y0, "ptr", DllStructGetPtr($tCurrent))
        DllCall($_hDll, "int", "LineTo", "int", $_hDC, "int", $_iX1, "int", $i_Y1)
        Return $tCurrent
    EndFunc
    
    Func _MouseProc($_nCode, $_wParam, $_lParam)
        Local $tMSLLHOOKSTRUCT = DllStructCreate("struct; long X;long Y; endstruct; " & _
            "DWORD mouseData; DWORD flags; DWORD time; ULONG_PTR dwExtraInfo;endstruct", $_lParam)
        If $_nCode < 0 Then Return _WinAPI_CallNextHookEx($__hHook, $_nCode, $_wParam, $_lParam)
        Local $iX = $tMSLLHOOKSTRUCT.X, $iY = $tMSLLHOOKSTRUCT.Y
        Switch $_wParam
            Case $WM_LBUTTONDOWN
                _ende()
    
            Case $WM_MOUSEMOVE
                WinMove($hCross, "", $iX -24, $iY -24)
                Local $iXz = ($iX +24 + $iMagWidth*$iMagZoom > @DesktopWidth) ? $iX -(24 + $iMagWidth*$iMagZoom) : $iX +24
                Local $iYz = ($iY +24 + $iMagHeight*$iMagZoom > @DesktopHeight) ? $iY -(24 + $iMagHeight*$iMagZoom) : $iY +24
                WinMove($hZoom, "", $iXz + $iMagWidth/2, $iYz)
                _Magnify($iX, $iY)
        EndSwitch
        Return _WinAPI_CallNextHookEx($__hHook, $_nCode, $_wParam, $_lParam)
    EndFunc
    
    Func OnAutoItExit()
        DLLCall($hUser32, "int", "ReleaseDC", "int", $hDCZoom, "hwnd", $hPen)
        DLLCall($hUser32, "int", "ReleaseDC", "int", $hDCDesk, "hwnd", 0)
        DLLCall($hUser32, "int", "ReleaseDC", "int", $hDCZoom, "hwnd", 0)
        DllClose($hUser32)
        DllClose($hGDI32)
        _WinAPI_UnhookWindowsHookEx($__hHook)
        DllCallbackFree($__hMouseProc)
    EndFunc