Jump to content

Color Under Mouse -- Reborn [02/03/2014 D]


jaberwacky
 Share

Recommended Posts

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
Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

  • 2 months later...

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

  • 2 months later...

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
Link to comment
Share on other sites

@LaCastiglione script very good and very useful, congratulations.

@UEZ, zoom option also execelente

Edited by Belini
Link to comment
Share on other sites

  • 1 year later...

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

Link to comment
Share on other sites

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

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
 Share

  • Recently Browsing   0 members

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