Jump to content

Recommended Posts

Posted (edited)

Years back JamesBrooks posted this thread: ColourUnderMouse.  I was interested in it because I was looking for a way to get started in AutoIt and so I latched onto this script.  Believe it or not after all this time I still find ways to modify the script!  Something about it intrigues me.  Here is the latest version.

Changelog:

[02/03/2014] -- New feature to display the checksum of the zoom rectangle surrounding the mouse!  Also, many optimizations to speed the script up considerably.  The zoom window is no longer a separate window.

Edit B: Now the checksum isn't calculated with every mouse move.  Press F4 or hold down shift plus an arrow key to get the checksum.

Edit C:  The checksum wasn't accurate when using shift + arrow keys.

Edit D: OOPS.  I get so excited I release way too early.

[02/01/2014] -- Now you have to hold down shift to activate the zoom feature.  Also, while holding down shift the arrow keys will move the mouse one pixel at a time.  This is to allow for picking out an exact pixel.  Try it out!

[01/06/2014] -- I finally got around to integrating UEZ's >zoom window code from 2011!  Totally awesome!  Check it out.  Scroll the mouse wheel to zoom in and out.

[08/25/2013] -- I have once again found a way to update this script.  Now the script uses a low level mouse procedure to watch for mouse movement.  I believe this translates to a higher resolution.  Requires latest beta (3.3.9.19).  Tested on Windows7 x64.

Removed until furthur notice.

downloads:101

Note: credit goes to JamesBrooks for the original.  Also credit to UEZ for the Zoom Window code.  Thanks.

Edited by jaberwacky
Posted

Great Script!

Another idea for enhancement: Output the hex RGB values in decimal for the three colours. If I want to set a custom colour in MS Word I have to input the RGB values in decimal e.g. #99CCFF needs to be 153 204 255.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted (edited)

Another idea for enhancement: Output the hex RGB values in decimal for the three colours. If I want to set a custom colour in MS Word I have to input the RGB values in decimal e.g. #99CCFF needs to be 153 204 255.

Please see if the latest version does what you asked.

Edit: I realized that it wouldn't and so I corrected it.

Using BlockInput() in the While/WEnd loop is a bit annoying because the mouse becomes stumbeling.

Removed.

Edited by LaCastiglione
Posted

Please see if the latest version does what you asked.

Perfect! This version does exactly what I need!

Thanks a lot for sharing!

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Posted (edited)

A zoom window would be great to pick detailed pixel color.

Something like that:

;coded by UEZ
#include <GDIPlus.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1)
Opt("GUICloseOnESC", 0)
TraySetState (2)

Global $zx = 0, $zy = 0, $up = 1
Global $zoom_level = 6, $zoom_min = 0.5, $zoom_max = 30
Global $esc

$zoom_level = 6
$esc = False
Zoom()
Exit

Func Zoom()
    Local $w, $h, $mpos = MouseGetPos(), $pixel_color
    Local $hGUI_Dot = GUICreate("", 1, 1, 18, 18, BitOR($WS_POPUP, $WS_CLIPSIBLINGS), $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle()))
    GUISetBkColor(0, $hGUI_Dot)
    GUISetState(@SW_SHOW, $hGUI_Dot)
    HotKeySet("{ESC}", "_Exit_CSR")

    Local Const $zw = 256
    Local Const $zh = 256
    Local Const $lW = 40
    Local Const $lH = 40
    Local Const $dist_x = 24, $dist_y = 24, $radius = 160
    Local $dirx = 1, $drx = 0, $diry = 1, $dry = 0, $lower_border, $right_border
    Local $zoomW = Int($zw / $zoom_level)
    Local $zoomH = Int($zh / $zoom_level)
    Local $hGUI_Zoom = GUICreate("Zoom", $zw, $zh, $zx, $zx, BitOR($WS_POPUP,$DS_MODALFRAME), BitOR($WS_EX_OVERLAPPEDWINDOW,$WS_EX_TOPMOST,$WS_EX_WINDOWEDGE), WinGetHandle(AutoItWinGetTitle()))
    GUISetState(@SW_SHOW, $hGUI_Zoom)
    Local $hDC_Zoom = _WinAPI_GetDC(0)
    Local $hGUI_ZoomDC = _WinAPI_GetDC($hGUI_Zoom)
    _WinAPI_SetBkMode($hGUI_ZoomDC, $TRANSPARENT)

    GUIRegisterMsg(0x020A, "WM_MOUSEWHEEL")
    Local $aLastPos[2]

    Do
        If $esc Then ExitLoop
        $mpos = MouseGetPos()
        GUISetState(@SW_SHOW, $hGUI_Zoom)
        If $mpos[0] <> $aLastPos[0] Or $mpos[1] <> $aLastPos[1] Then
            $pixel_color = Hex(PixelGetColor($mpos[0], $mpos[1]), 6)
            WinMove($hGUI_Dot, "", $mpos[0], $mpos[1])
            ToolTip("ESC to abort"& @CRLF & @CRLF & _
                          "Position: " & $mpos[0] & "," & $mpos[1] & @CRLF & _
                          "Pixel Color: 0x" & $pixel_color, $drx + $mpos[0] + $dirx * ($dist_x + $zoomW / 3) , $dry + $mpos[1] + $diry * ($dist_y + $zoomH / 3))
            $aLastPos = $mpos

            $right_border = Pixel_Distance($mpos[0], $mpos[1], @DesktopWidth, $mpos[1])
            If $right_border < $radius Then
                $dirx = -1
                $drx = -$radius
            Else
                $dirx = 1
                $drx = 0
            EndIf
            $lower_border = Pixel_Distance($mpos[0], $mpos[1], $mpos[0], @DesktopHeight)
            If $lower_border < $radius Then
                $diry = -1
                $dry = -$radius
            Else
                $diry = 1
                $dry = 0
            EndIf
        EndIf

        If CheckRectCollision($zx - $lW, $zy - $lH , $zx + $zw + $lW, $zy + $zh + $lH, $mpos[0], $mpos[1]) Then
            $up *= -1
            If $up = -1 Then
                $zx = @DesktopWidth - $zw - 4
                WinMove($hGUI_Zoom, "", $zx, $zy)
            Else
                $zx = 0
                WinMove($hGUI_Zoom, "", $zx, $zy)
            EndIf
        EndIf
        _WinAPI_StretchBlt($hGUI_ZoomDC, 0, 0, $zw, $zh, $hDC_Zoom, $mpos[0] - $zoomW / 2, $mpos[1] - $zoomH / 2, $zoomW, $zoomH, $SRCCOPY)
        $zoomW = Int($zw / $zoom_level)
        $zoomH = Int($zh / $zoom_level)

        Sleep(20)
    Until 0
    ToolTip("")
    _WinAPI_ReleaseDC($hGUI_Zoom, $hGUI_ZoomDC)
    _WinAPI_ReleaseDC(0, $hDC_Zoom)
    _WinAPI_DeleteDC($hGUI_ZoomDC)
    _WinAPI_DeleteDC($hDC_Zoom)
    GUIDelete($hGUI_Dot)
    GUIDelete($hGUI_Zoom)
EndFunc

Func _Exit_CSR()
    $esc = True
    Return
EndFunc

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    Local $wheel_Dir = _WinAPI_HiWord($wParam)
    If $wheel_Dir > 0 Then
        If $zoom_level < $zoom_max Then
            $zoom_level += 0.25
        EndIf
    Else
        If $zoom_level  > $zoom_min Then
            $zoom_level  -= 0.25
        EndIf
    EndIf
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_MOUSEWHEEL

Func _WinAPI_StretchBlt($hDestDC, $iXDest, $iYDest, $iWidthDest, $iHeightDest, $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iRop)
    Local $Ret  = DllCall('gdi32.dll', 'int', 'StretchBlt', 'hwnd', $hDestDC, 'int', $iXDest, 'int', $iYDest, 'int', $iWidthDest, 'int', $iHeightDest, 'hwnd', $hSrcDC, 'int', $iXSrc, 'int', $iYSrc, 'int', $iWidthSrc, 'int', $iHeightSrc, 'dword', $iRop)
    If (@error) Or (Not $Ret[0]) Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_WinAPI_StretchBlt

Func CheckRectCollision($iLeft, $iTop, $iRight, $iBottom, $iX, $iY )
    Local $tagRECT = "int Left;int Top;int Right;int Bottom"
    Local $tRECT = DllStructCreate($tagRECT)
    DllStructSetData($tRECT, 1, $iLeft)
    DllStructSetData($tRECT, 2, $iTop)
    DllStructSetData($tRECT, 3, $iRight)
    DllStructSetData($tRECT, 4, $iBottom)
    Local $aResult = DllCall("User32.dll", "int", "PtInRect", "ptr", DllStructGetPtr($tRECT), "int", $iX, "int", $iY)
    Return $aResult[0] <> 0
EndFunc

Func Pixel_Distance($x1, $y1, $x2, $y2) ;Pythagoras theorem
    Local $a, $b
    If $x2 = $x1 And $y2 = $y1 Then Return 0
    $a = $y2 - $y1
    $b = $x2 - $x1
    Return Sqrt($a * $a + $b * $b)
EndFunc   ;==>Pixel_Distance

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted

both scripts are awesome! i get an error when running the zoom one after i hit ESC i get

_WinAPI_DeleteDC: The operation completed successfully.

How to I stop this from displaying?

  • 2 months later...
Posted

Hey,

im trying to make a colorpicker, zoom and screenshot script.

I figured out that GDI+ is the best way (but not the easiest) to draw rectangles on the desktop.

So i modified that great example from Malkey () to have a Zoom GUI

But i have a problem: drawn rectangles wont show up in the zoomed window.

I bet there is a window flag you have to set to get that included, but for that special case i cant find any information and im not a GDI+ expert.

Here is the Script (press and hold Ctrl to drag a rectangle)

#include <GDIPlus.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
; Modified from http://www.autoitscript.com/forum/index....=&showtopic=97126&view=findpos
;~ Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 1) ;1=absolute, 0=relative, 2=client
$GDIdll = DllOpen("gdi32.dll")
$ZoomSizeX = 256
$ZoomSizeY = 256
$ZoomGUI = GUICreate("Zoom", $ZoomSizeX, $ZoomSizeY, 400, 200, BitOR($WS_SIZEBOX,$WS_THICKFRAME, $WS_SYSMENU, $WS_BORDER, $WS_CAPTION), $WS_EX_TOPMOST)
WinSetTrans($ZoomGUI, "", 255); I dont know why but this excludes the ZoomGUI from being drawn with StretchBlt, neat!

GUISetBkColor(0xEEEEEE)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitF")
GUISetState()
Main()
Func Main()
    Local $hBitmap, $hGui, $hGraphic, $hImage2, $GuiSizeX = @DesktopWidth, $GuiSizeY = @DesktopHeight
    Local $GuiSize = 70, $hWnd, $hDC, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend
    Local $iX1 = 0, $iY1 = 0, $tPoint, $pPoint, $hBMPBuff, $hGraphicGUI, $hPen, $aMPosNew
    Local $iOpacity = 255, $dll = DllOpen("user32.dll")
Local $aMPos = -1
    $hGui = GUICreate("L1", $GuiSizeX, $GuiSizeY, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST + $WS_EX_TRANSPARENT))
    GUISetState()
    _GDIPlus_Startup()
    $hWnd = _WinAPI_GetDC(0)
    $hDC = _WinAPI_CreateCompatibleDC($hWnd)
    $hBitmap = _WinAPI_CreateCompatibleBitmap($hWnd, $GuiSizeX, $GuiSizeY)
    _WinAPI_SelectObject($hDC, $hBitmap)
    $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphic)
    $hGraphicGUI = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    _GDIPlus_GraphicsClear($hGraphic); Add ,0x01000000) to disable underling desktop
    $hPen = _GDIPlus_PenCreate(0xffff0000, 10)
    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", $GuiSizeX);$iWidth )
    DllStructSetData($tSize, "Y", $GuiSizeY);$iHeight)
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", 1)
    $tPoint = DllStructCreate($tagPOINT); Create point destination structure here
    $pPoint = DllStructGetPtr($tPoint); Create pointer to this dll data structure, $pPTDest parameter
    DllStructSetData($tPoint, "X", $iX1)
    DllStructSetData($tPoint, "Y", $iY1)
    _WinAPI_UpdateLayeredWindow($hGui, $hWnd, $pPoint, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
    Do
 
  $ZoomDC = _WinAPI_GetDC($ZoomGUI)
  $DeskDC = _WinAPI_GetDC(0)
 
        Select
            Case _IsPressed("11", $dll); Ctrl to start drag rect
                Do

     $aMPosNew = MouseGetPos()
     If $aMPos = -1 Then ; Drag Start
      $aMPos = $aMPosNew
     EndIf
     _GDIPlus_GraphicsClear($hGraphic)
    
     ; I used _Iif() from Misc.au3 instead using of _Min() from Math.au3.
     $RectStartX = _Iif($aMPos[0] < $aMPosNew[0], $aMPos[0], $aMPosNew[0])
     $RectStartY = _Iif($aMPos[1] < $aMPosNew[1], $aMPos[1], $aMPosNew[1])
     _GDIPlus_GraphicsDrawRect($hGraphic, $RectStartX, $RectStartY, Abs($aMPosNew[0] - $aMPos[0]), Abs($aMPosNew[1] - $aMPos[1]), $hPen)
    
     _WinAPI_UpdateLayeredWindow($hGui, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)

                    Sleep(10)
                Until Not _IsPressed("11", $dll)
    $aMPos = -1 ; Drag End
              
            Case _IsPressed("04", $dll) Or _IsPressed("11", $dll) ; Middle mouse button 0r Ctrl key <=======  Clear screen of rectangles.
                _GDIPlus_GraphicsClear($hGraphic)
                _WinAPI_UpdateLayeredWindow($hGui, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
   Case Else
   
    $aMPosNew = MouseGetPos()
    _WinAPI_StretchBlt($ZoomDC, 0, 0, $ZoomSizeX, $ZoomSizeY, $DeskDC, $aMPosNew[0], $aMPosNew[1], 256/2, 256/2, $MERGECOPY) ; 256/2 = Double Zoom
   
  EndSelect
 
  _WinAPI_ReleaseDC(0, $DeskDC)
  _WinAPI_ReleaseDC($ZoomGUI, $ZoomDC)
    
        Sleep(10)
    Until _IsPressed("1B", $dll); ESC key
    DllClose($dll)
DllClose($GDIdll)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphicGUI)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_ReleaseDC(0, $hWnd)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hDC)
    _GDIPlus_Shutdown()
EndFunc   ;==>Main

Func _WinAPI_StretchBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iROP)
;~   Local $aResult = _WinAPI_BitBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iROP)
    Local $aResult = DllCall($GDIdll, "int", "StretchBlt", "hwnd", $hDestDC, "int", $iXDest, "int", $iYDest, "int", $iWidth, "int", $iHeight, _
            "hwnd", $hSrcDC, "int", $iXSrc, "int", $iYSrc, "int", $iWidthSrc, "int", $iHeightSrc, "int", $iROP)
    If @error Then Return SetError(@error, 0, False)
    Return $aResult[0] <> 0
EndFunc   ;==>_WinAPI_StretchBlt
Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite
Posted

From davidkim's post by adding a BitBlt to the _WinAPI_StretchBlt function, a layered window is able to be captured.

#include <GDIPlus.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>

;Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 1) ;1=absolute, 0=relative, 2=client
Local $f = 0, $GDIdll = DllOpen("gdi32.dll")
Local $ZoomSizeX = 256
Local $ZoomSizeY = 256
Local $ZoomGUI = GUICreate("Zoom", $ZoomSizeX, $ZoomSizeY, 400, 200, BitOR($WS_SIZEBOX, $WS_THICKFRAME, $WS_SYSMENU, $WS_BORDER, $WS_CAPTION), $WS_EX_TOPMOST)
WinSetTrans($ZoomGUI, "", 255)
GUISetBkColor(0xEEEEEE)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitF")
GUISetState()
Main()


Func Main()
    Local $hBitmap, $hGui, $hGraphic, $hImage2, $GuiSizeX = @DesktopWidth, $GuiSizeY = @DesktopHeight
    Local $GuiSize = 70, $hWnd, $hDC, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend, $ZoomDC, $DeskDC, $RectStartX, $RectStartY
    Local $iX1 = 0, $iY1 = 0, $tPoint, $pPoint, $hBMPBuff, $hGraphicGUI, $hPen, $aMPosNew
    Local $iOpacity = 255, $dll = DllOpen("user32.dll")
    Local $aMPos = -1
    $hGui = GUICreate("L1", $GuiSizeX, $GuiSizeY, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST + $WS_EX_TRANSPARENT))
    GUISetState()
    _GDIPlus_Startup()
    $hWnd = _WinAPI_GetDC(0)
    $hDC = _WinAPI_CreateCompatibleDC($hWnd)
    $hBitmap = _WinAPI_CreateCompatibleBitmap($hWnd, $GuiSizeX, $GuiSizeY)
    _WinAPI_SelectObject($hDC, $hBitmap)
    $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphic)
    $hGraphicGUI = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    _GDIPlus_GraphicsClear($hGraphic); Add ,0x01000000) to disable underling desktop
    $hPen = _GDIPlus_PenCreate(0xffff0000, 10)
    $tSize = DllStructCreate($tagSIZE)
    $pSize = DllStructGetPtr($tSize)
    DllStructSetData($tSize, "X", $GuiSizeX);$iWidth )
    DllStructSetData($tSize, "Y", $GuiSizeY);$iHeight)
    $tSource = DllStructCreate($tagPOINT)
    $pSource = DllStructGetPtr($tSource)
    $tBlend = DllStructCreate($tagBLENDFUNCTION)
    $pBlend = DllStructGetPtr($tBlend)
    DllStructSetData($tBlend, "Alpha", $iOpacity)
    DllStructSetData($tBlend, "Format", 1)
    $tPoint = DllStructCreate($tagPOINT); Create point destination structure here
    $pPoint = DllStructGetPtr($tPoint); Create pointer to this dll data structure, $pPTDest parameter
    DllStructSetData($tPoint, "X", $iX1)
    DllStructSetData($tPoint, "Y", $iY1)
    _WinAPI_UpdateLayeredWindow($hGui, $hWnd, $pPoint, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
    $ZoomDC = _WinAPI_GetDC($ZoomGUI)
    $DeskDC = _WinAPI_GetDC(0)
    Do
        Select
            Case _IsPressed("11", $dll); Ctrl to start drag rect
                Do
                    $aMPosNew = MouseGetPos()
                    If $aMPos = -1 Then ; Drag Start
                        $aMPos = $aMPosNew
                    EndIf
                    _GDIPlus_GraphicsClear($hGraphic)
                    ; I used _Iif() from Misc.au3 instead using of _Min() from Math.au3.
                    $RectStartX = _Iif($aMPos[0] < $aMPosNew[0], $aMPos[0], $aMPosNew[0])
                    $RectStartY = _Iif($aMPos[1] < $aMPosNew[1], $aMPos[1], $aMPosNew[1])
                    _GDIPlus_GraphicsDrawRect($hGraphic, $RectStartX, $RectStartY, Abs($aMPosNew[0] - $aMPos[0]), Abs($aMPosNew[1] - $aMPos[1]), $hPen)
                    _WinAPI_UpdateLayeredWindow($hGui, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
                    Sleep(10)
                Until Not _IsPressed("11", $dll)
                $aMPos = -1 ; Drag End
            Case _IsPressed("04", $dll) Or _IsPressed("11", $dll) ; Middle mouse button 0r Ctrl key <=======  Clear screen of rectangles.
                _GDIPlus_GraphicsClear($hGraphic)
                _WinAPI_UpdateLayeredWindow($hGui, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
            Case Else
                $aMPosNew = MouseGetPos()
                _WinAPI_StretchBlt($ZoomDC, 0, 0, $ZoomSizeX, $ZoomSizeY, $DeskDC, $aMPosNew[0], $aMPosNew[1], 256 / 2, 256 / 2, $MERGECOPY)
        EndSelect

        If _IsPressed("1B", $dll) Then $f = 1; ESC key
        Sleep(50)
    Until $f
    _WinAPI_ReleaseDC(0, $DeskDC)
    _WinAPI_ReleaseDC($ZoomGUI, $ZoomDC)
    DllClose($dll)
    DllClose($GDIdll)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphicGUI)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_ReleaseDC(0, $hWnd)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($hDC)
    _GDIPlus_Shutdown()
EndFunc   ;==>Main

Func _WinAPI_StretchBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iROP)
;~   Local $aResult = _WinAPI_BitBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iROP)
    Local $srcDC = _WinAPI_GetDC(0)
    Local $trgDC = _WinAPI_CreateCompatibleDC($srcDC)
    Local $hBitmap = _WinAPI_CreateCompatibleBitmap($srcDC, @DesktopWidth, @DesktopHeight)
    Local $old = _WinAPI_SelectObject($trgDC, $hBitmap)
    ;select area copy
    _WinAPI_BitBlt($trgDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $srcDC, $iXSrc - $iWidthSrc / 2, $iYSrc - $iHeightSrc / 2, BitOR($SRCCOPY, 0x40000000))

    Local $aResult = DllCall($GDIdll, "int", "StretchBlt", _
            "hwnd", $hDestDC, "int", $iXDest, "int", $iYDest, "int", $iWidth, "int", $iHeight, _
            "hwnd", $trgDC, "int", $iXSrc, "int", $iYSrc, "int", $iWidthSrc, "int", $iHeightSrc, "int", $iROP)
    If @error Then Return SetError(@error, 0, False)
    _WinAPI_DeleteObject($hBitmap)
    _WinAPI_DeleteDC($trgDC)
    _WinAPI_ReleaseDC(0, $srcDC)
    Return $aResult[0] <> 0
EndFunc   ;==>_WinAPI_StretchBlt

Func ExitF()
    $f = 1
EndFunc   ;==>ExitF
Posted (edited)

Malkey thats cool, i learned quite something today :)

You use BitOR($SRCCOPY, 0x40000000) for the raster operation code with BitBlt, which is $CAPTUREBLT (which is exactly what i needed).

But the thing is: you also can use it directly with StretchBlt since it has the same $iROP parameter.

So my code works if i just replace $MERGECOPY with BitOR($SRCCOPY, $CAPTUREBLT)

But then i noticed that the zoom window is being visible again in the zoomed view, which is kind of one step further, one step back.

Then i thought it must be possible to take a bitmap of the original Desktop (without layered windows) and additionally merge in the bitmap of the layered rectangle window.

Your code was very helpful in the process of doing that ;)

Here is the script:

#include <GDIPlus.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
; Modified from http://www.autoitscript.com/forum/index....=&showtopic=97126&view=findpos
;~ Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)
Opt("MouseCoordMode", 1) ;1=absolute, 0=relative, 2=client
Local $f = 0, $GDIdll = DllOpen("gdi32.dll")

Local $hBitmap, $hGui, $hGraphic, $hImage2, $GuiSizeX = @DesktopWidth, $GuiSizeY = @DesktopHeight
Local $GuiSize = 70, $hWnd, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend
Local $iX1 = 0, $iY1 = 0, $tPoint, $pPoint, $hBMPBuff, $hGraphicGUI, $hPen, $aMPosNew
Local $iOpacity = 255, $dll = DllOpen("user32.dll")
Local $aMPos = -1
$hGui = GUICreate("L1", $GuiSizeX, $GuiSizeY, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST + $WS_EX_TRANSPARENT))
GUISetState()

$ZoomSizeX = 256
$ZoomSizeY = 256
$ZoomGUI = GUICreate("Zoom", $ZoomSizeX, $ZoomSizeY, 400, 200, BitOR($WS_SIZEBOX, $WS_THICKFRAME, $WS_SYSMENU, $WS_BORDER, $WS_CAPTION), $WS_EX_TOPMOST)
WinSetTrans($ZoomGUI, "", 255); I dont know why but this excludes the ZoomGUI from being drawn with StretchBlt, neat!

GUISetBkColor(0xEEEEEE)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitF")
GUISetState()

_GDIPlus_Startup()
$hWnd = _WinAPI_GetDC(0)
$L1hDC = _WinAPI_CreateCompatibleDC($hWnd)
$hBitmap = _WinAPI_CreateCompatibleBitmap($hWnd, $GuiSizeX, $GuiSizeY)
_WinAPI_SelectObject($L1hDC, $hBitmap)
$hGraphic = _GDIPlus_GraphicsCreateFromHDC($L1hDC)
$hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphic)
$hGraphicGUI = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
_GDIPlus_GraphicsClear($hGraphic); Add ,0x01000000) to disable underling desktop
$hPen = _GDIPlus_PenCreate(0xffff0000, 10)
;~     $hBrush = _GDIPlus_BrushCreateSolid(0xffff0000)
$tSize = DllStructCreate($tagSIZE)
$pSize = DllStructGetPtr($tSize)
DllStructSetData($tSize, "X", $GuiSizeX);$iWidth )
DllStructSetData($tSize, "Y", $GuiSizeY);$iHeight)
$tSource = DllStructCreate($tagPOINT)
$pSource = DllStructGetPtr($tSource)
$tBlend = DllStructCreate($tagBLENDFUNCTION)
$pBlend = DllStructGetPtr($tBlend)
DllStructSetData($tBlend, "Alpha", $iOpacity)
DllStructSetData($tBlend, "Format", 1)
$tPoint = DllStructCreate($tagPOINT); Create point destination structure here
$pPoint = DllStructGetPtr($tPoint); Create pointer to this dll data structure, $pPTDest parameter
DllStructSetData($tPoint, "X", $iX1)
DllStructSetData($tPoint, "Y", $iY1)
_WinAPI_UpdateLayeredWindow($hGui, $hWnd, $pPoint, $pSize, $L1hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
$ZoomDC = _WinAPI_GetDC($ZoomGUI)
Global $DeskDC = _WinAPI_GetDC(0)

Do
    Select
        Case _IsPressed("11", $dll); Ctrl to start drag rect
            Do
                $aMPosNew = MouseGetPos()
                If $aMPos = -1 Then ; Drag Start
                    $aMPos = $aMPosNew
                EndIf
                _GDIPlus_GraphicsClear($hGraphic)
                ; I used _Iif() from Misc.au3 instead using of _Min() from Math.au3.
                $RectStartX = _Iif($aMPos[0] < $aMPosNew[0], $aMPos[0], $aMPosNew[0])
                $RectStartY = _Iif($aMPos[1] < $aMPosNew[1], $aMPos[1], $aMPosNew[1])
                _GDIPlus_GraphicsDrawRect($hGraphic, $RectStartX, $RectStartY, Abs($aMPosNew[0] - $aMPos[0]), Abs($aMPosNew[1] - $aMPos[1]), $hPen)
                _WinAPI_StretchBltNOTLayCombine($ZoomDC, 0, 0, $ZoomSizeX, $ZoomSizeY, $DeskDC, $aMPosNew[0] - 64, $aMPosNew[1] - 64, 256 / 2, 256 / 2, $SRCCOPY, $L1hDC) ; 256/2 = Double Zoom
;~                 _WinAPI_StretchBlt($ZoomDC, 0, 0, $ZoomSizeX, $ZoomSizeY, $DeskDC, $aMPosNew[0]-64, $aMPosNew[1]-64, 256 / 2, 256 / 2, $SRCCOPY) ; less CPU

                _WinAPI_UpdateLayeredWindow($hGui, $hWnd, 0, $pSize, $L1hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
                Sleep(10)
            Until Not _IsPressed("11", $dll)
            $aMPos = -1 ; Drag End
        Case _IsPressed("04", $dll) Or _IsPressed("11", $dll) ; Middle mouse button 0r Ctrl key <=======  Clear screen of rectangles.
            _GDIPlus_GraphicsClear($hGraphic)
            _WinAPI_UpdateLayeredWindow($hGui, $hWnd, 0, $pSize, $L1hDC, $pSource, 0, $pBlend, $ULW_ALPHA)
        Case Else
            $aMPosNew = MouseGetPos()
            _WinAPI_StretchBltNOTLayCombine($ZoomDC, 0, 0, $ZoomSizeX, $ZoomSizeY, $DeskDC, $aMPosNew[0] - 64, $aMPosNew[1] - 64, 256 / 2, 256 / 2, $SRCCOPY, $L1hDC) ; 256/2 = Double Zoom
;~             _WinAPI_StretchBlt($ZoomDC, 0, 0, $ZoomSizeX, $ZoomSizeY, $DeskDC, $aMPosNew[0]-64, $aMPosNew[1]-64, 256 / 2, 256 / 2, $SRCCOPY) ; less CPU
    EndSelect
    Sleep(10)
Until $f

_WinAPI_ReleaseDC(0, $DeskDC)
_WinAPI_ReleaseDC($ZoomGUI, $ZoomDC)
DllClose($dll)
DllClose($GDIdll)
_GDIPlus_PenDispose($hPen)
_GDIPlus_GraphicsDispose($hGraphicGUI)
_GDIPlus_GraphicsDispose($hGraphic)
_WinAPI_ReleaseDC(0, $hWnd)
_WinAPI_DeleteObject($hBitmap)
_WinAPI_DeleteDC($L1hDC)
_GDIPlus_Shutdown()


Func _WinAPI_StretchBltNOTLayCombine($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iROP, $hAddDC); $hAddDC = DC to a bitmap to mix in with black transparency

    ; create a Memory Bitmap to combine the Desktop DC(without any layered Windows) with the DC of the layered rectangle window (fullscreen)
    Local $MashDC = _WinAPI_CreateCompatibleDC($DeskDC)
    Local $hMashBitmap = _WinAPI_CreateCompatibleBitmap($DeskDC, @DesktopWidth, @DesktopHeight)
    Local $old = _WinAPI_SelectObject($MashDC, $hMashBitmap)

    ; copy whole Desktop Bitmap to memory (without layered windows)
    _WinAPI_BitBlt($MashDC, 0, 0, @DesktopWidth, @DesktopHeight, $DeskDC, 0, 0, $iROP)

    ; copy additional bitmap with black color made transparent (only red rectangles visible)
    Local $aResult = DllCall($GDIdll, "int", "GdiTransparentBlt", "hwnd", $MashDC, "int", 0, "int", 0, "int", @DesktopWidth, "int", @DesktopHeight, _
            "hwnd", $hAddDC, "int", 0, "int", 0, "int", @DesktopWidth, "int", @DesktopHeight, "uint", 0x000000); make black color transparent (BGR format)

    ; copy merged bitmap from memory to Desktop
    _WinAPI_StretchBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $MashDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iROP)

    _WinAPI_DeleteObject($hMashBitmap)
    _WinAPI_DeleteDC($MashDC)

    If @error Then Return SetError(@error, 0, False)
    Return $aResult[0] <> 0
EndFunc   ;==>_WinAPI_StretchBltNOTLayCombine

Func _WinAPI_StretchBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iROP)
;~   Local $aResult = _WinAPI_BitBlt($hDestDC, $iXDest, $iYDest, $iWidth, $iHeight, $hSrcDC, $iXSrc, $iYSrc, $iROP)
    Local $aResult = DllCall($GDIdll, "int", "StretchBlt", "hwnd", $hDestDC, "int", $iXDest, "int", $iYDest, "int", $iWidth, "int", $iHeight, _
            "hwnd", $hSrcDC, "int", $iXSrc, "int", $iYSrc, "int", $iWidthSrc, "int", $iHeightSrc, "int", $iROP)
    If @error Then Return SetError(@error, 0, False)
    Return $aResult[0] <> 0
EndFunc   ;==>_WinAPI_StretchBlt

Func ExitF()
    $f = 1
EndFunc   ;==>ExitF

But this way is much more CPU intensive than simply use StretchBlt, is there another way to make it more slim?

The rectangles show up for me. WIndows 7 x64

Yeah i have the same, but it has to do with Aero. I have turned it off and therefore BitBlt will behave different. Edited by qsek
Teamspeak 3 User Viewer - Quick and functional TS3 Query script, which shows online users.Cached Screenshot Deleter - Deletes older Fraps Screenshots if they exceed a specified limit.Unresolved Topics:Intercept and modify dragdrop text behaviour in scite
  • 2 months later...
Posted (edited)

Add these changes to toggle the dot in UEZ's excellent code above Posted 04 November 2011 - 08:00 AM

Local $aLastPos[2]
    Local $begin = TimerInit()
    Local $color = 0
    Do
        If $esc Then ExitLoop
        $mpos = MouseGetPos()

        ;toggle dot color
        If TimerDiff($begin) &gt; 250 Then  ;1/4 second
            $begin = TimerInit()    ;reset timer
            if $color = 0 Then      ;toggle color
                $color = 0xffffff   ;white
            Else
                $color = 0          ;black
            EndIf
        EndIf

        GUISetState(@SW_SHOW, $hGUI_Zoom)
... rest of UEZ's code
Edited by ahha
Posted (edited)

@LaCastiglione script very good and very useful, congratulations.

@UEZ, zoom option also execelente

Edited by Belini
  • 1 year later...
Posted

I added "color to clip board" to UEZ's Code which makes this very useful to me.

;coded by UEZ
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <Array.au3>

Opt("MustDeclareVars", 1)
Opt("GUICloseOnESC", 0)
TraySetState(2)

Global $zx = 0, $zy = 0, $up = 1
Global $zoom_level = 6, $zoom_min = 0.5, $zoom_max = 30
Global $esc, $pixel_color, $Copy
HotKeySet("!x", "CaptureColor")

$zoom_level = 7 ;5 ;6
$esc = False
Zoom()
Exit

Func Zoom()
    Local $w, $h, $mpos = MouseGetPos(), $pixel_color
    Local $hGUI_Dot = GUICreate("", 1, 1, 18, 18, BitOR($WS_POPUP, $WS_CLIPSIBLINGS), $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle()))
    GUISetBkColor(0, $hGUI_Dot)
    GUISetState(@SW_SHOW, $hGUI_Dot)
    HotKeySet("{ESC}", "_Exit_CSR")

    Local Const $zw = 256
    Local Const $zh = 256
    Local Const $lW = 40
    Local Const $lH = 40
    Local Const $dist_x = 24, $dist_y = 24, $radius = 160
    Local $dirx = 1, $drx = 0, $diry = 1, $dry = 0, $lower_border, $right_border
    Local $zoomW = Int($zw / $zoom_level)
    Local $zoomH = Int($zh / $zoom_level)
    Local $hGUI_Zoom = GUICreate("Zoom", $zw, $zh, $zx, $zx, BitOR($WS_POPUP, $DS_MODALFRAME), BitOR($WS_EX_OVERLAPPEDWINDOW, $WS_EX_TOPMOST, $WS_EX_WINDOWEDGE), WinGetHandle(AutoItWinGetTitle()))
    GUISetState(@SW_SHOW, $hGUI_Zoom)
    Local $hDC_Zoom = _WinAPI_GetDC(0)
    Local $hGUI_ZoomDC = _WinAPI_GetDC($hGUI_Zoom)
    _WinAPI_SetBkMode($hGUI_ZoomDC, $TRANSPARENT)

    GUIRegisterMsg(0x020A, "WM_MOUSEWHEEL")
    Local $aLastPos[2]

    Do
        If $esc Then ExitLoop
        $mpos = MouseGetPos()
        GUISetState(@SW_SHOW, $hGUI_Zoom)
        If $mpos[0] <> $aLastPos[0] Or $mpos[1] <> $aLastPos[1] Then
            $pixel_color = Hex(PixelGetColor($mpos[0], $mpos[1]), 6)
            $Copy = $pixel_color
            WinMove($hGUI_Dot, "", $mpos[0], $mpos[1])
            ToolTip("ESC to abort" & @CRLF & @CRLF & _
                    "ALT + x = Capture " & @CRLF & _
                    "Color to clip board" & @CRLF & @CRLF & _
                    "Position: " & $mpos[0] & "," & $mpos[1] & @CRLF & _
                    "Pixel Color: 0x" & $pixel_color, $drx + $mpos[0] + $dirx * ($dist_x + $zoomW / 3), $dry + $mpos[1] + $diry * ($dist_y + $zoomH / 3))
            $aLastPos = $mpos

            $right_border = Pixel_Distance($mpos[0], $mpos[1], @DesktopWidth, $mpos[1])
            If $right_border < $radius Then
                $dirx = -1
                $drx = -$radius
            Else
                $dirx = 1
                $drx = 0
            EndIf
            $lower_border = Pixel_Distance($mpos[0], $mpos[1], $mpos[0], @DesktopHeight)
            If $lower_border < $radius Then
                $diry = -1
                $dry = -$radius
            Else
                $diry = 1
                $dry = 0
            EndIf
        EndIf

        If CheckRectCollision($zx - $lW, $zy - $lH, $zx + $zw + $lW, $zy + $zh + $lH, $mpos[0], $mpos[1]) Then
            $up *= -1
            If $up = -1 Then
                $zx = @DesktopWidth - $zw - 4
                WinMove($hGUI_Zoom, "", $zx, $zy)
            Else
                $zx = 0
                WinMove($hGUI_Zoom, "", $zx, $zy)
            EndIf
        EndIf
        _WinAPI_StretchBlt($hGUI_ZoomDC, 0, 0, $zw, $zh, $hDC_Zoom, $mpos[0] - $zoomW / 2, $mpos[1] - $zoomH / 2, $zoomW, $zoomH, $SRCCOPY)
        $zoomW = Int($zw / $zoom_level)
        $zoomH = Int($zh / $zoom_level)

        Sleep(20)
    Until 0
    ToolTip("")
    _WinAPI_ReleaseDC($hGUI_Zoom, $hGUI_ZoomDC)
    _WinAPI_ReleaseDC(0, $hDC_Zoom)
    _WinAPI_DeleteDC($hGUI_ZoomDC)
    _WinAPI_DeleteDC($hDC_Zoom)
    GUIDelete($hGUI_Dot)
    GUIDelete($hGUI_Zoom)
EndFunc   ;==>Zoom

Func _Exit_CSR()
    $esc = True
    Return
EndFunc   ;==>_Exit_CSR

Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
    Local $wheel_Dir = _WinAPI_HiWord($wParam)
    If $wheel_Dir > 0 Then
        If $zoom_level < $zoom_max Then
            $zoom_level += 0.25
        EndIf
    Else
        If $zoom_level > $zoom_min Then
            $zoom_level -= 0.25
        EndIf
    EndIf
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_MOUSEWHEEL

Func _WinAPI_StretchBlt($hDestDC, $iXDest, $iYDest, $iWidthDest, $iHeightDest, $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iRop)
    Local $Ret = DllCall('gdi32.dll', 'int', 'StretchBlt', 'hwnd', $hDestDC, 'int', $iXDest, 'int', $iYDest, 'int', $iWidthDest, 'int', $iHeightDest, 'hwnd', $hSrcDC, 'int', $iXSrc, 'int', $iYSrc, 'int', $iWidthSrc, 'int', $iHeightSrc, 'dword', $iRop)
    If (@error) Or (Not $Ret[0]) Then Return SetError(1, 0, 0)
    Return 1
EndFunc   ;==>_WinAPI_StretchBlt

Func CheckRectCollision($iLeft, $iTop, $iRight, $iBottom, $iX, $iY)
    Local $tagRECT = "int Left;int Top;int Right;int Bottom"
    Local $tRECT = DllStructCreate($tagRECT)
    DllStructSetData($tRECT, 1, $iLeft)
    DllStructSetData($tRECT, 2, $iTop)
    DllStructSetData($tRECT, 3, $iRight)
    DllStructSetData($tRECT, 4, $iBottom)
    Local $aResult = DllCall("User32.dll", "int", "PtInRect", "ptr", DllStructGetPtr($tRECT), "int", $iX, "int", $iY)
    Return $aResult[0] <> 0
EndFunc   ;==>CheckRectCollision

Func Pixel_Distance($x1, $y1, $x2, $y2) ;Pythagoras theorem
    Local $a, $b
    If $x2 = $x1 And $y2 = $y1 Then Return 0
    $a = $y2 - $y1
    $b = $x2 - $x1
    Return Sqrt($a * $a + $b * $b)
EndFunc   ;==>Pixel_Distance

Func CaptureColor()
;~  MsgBox(0,"","HERE")
    ClipPut("0x" & $Copy)
EndFunc   ;==>CaptureColor

MEASURE TWICE - CUT ONCE

  • 4 months later...
  • 4 weeks later...
  • 4 months later...
Posted

@jaberwacky

Hello sir, I'm in dear need of a script like this and it would be great if you can send me the script :0. THank you very much

Updated!  See the changelog in the OP for details.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...