Jump to content

ScreenColorPicker snap color from screen with the mouse pointer


ioa747
 Share

Recommended Posts

ScreenColorPicker  snap color from screen with the mouse pointer to clipboard

:idea:  the idea comes from @Melba23's Magnify  post. Thanks for that!         forum1.png.fc97055140af69287ac9d6c5ba195cfe.png

;https://www.autoitscript.com/forum/topic/209412-screencolorpicker-snap-color-from-screen-with-the-mouse-pointer/

#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
;ScreenColorPicker.au3
;snap color from screen with the mouse pointer
#NoTrayIcon
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <WinAPI.au3>
#include <Misc.au3>
#include <StringConstants.au3>
#include <TrayConstants.au3>

; to avoid running it multiple times!
If _Singleton(@ScriptName, 1) = 0 Then Exit

Opt("TrayMenuMode", 3) ; These are options 1 and 2 for TrayMenuMode.

Global $hMag_GUI, $hMagDC, $hDeskDC, $hPen, $oObj, $aMouse_Pos[2], $iLast_Mouse_X = 0, $iLast_Mouse_Y = 0
Local $mColor, $hColor_Win, $ColorLabel, $ColorRec

TraySetIcon(StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", $STR_NOCASESENSEBASIC, -1) - 1) & "\Icons\MyAutoIt3_Red.ico")
TraySetToolTip("ColorPicker")

#Region === Tray_Menu ===
;~ Local $idPaused = TrayCreateItem("Pause", -1, -1, $TRAY_ITEM_RADIO)
;~ TrayItemSetState(-1, $TRAY_UNCHECKED)
Local $TrayColorPicker = TrayCreateItem("ColorPicker")
Local $TrayHelp = TrayCreateItem("Help")
TrayCreateItem("") ; Create a separator line.
Local $TrayExit = TrayCreateItem("Exit")
#EndRegion === Tray_Menu ===

Local $hDLL = DllOpen("user32.dll")

While 1
    Switch TrayGetMsg()
        Case $TRAY_EVENT_PRIMARYDOUBLE ;* ColorPicker
            ColorPicker()

        Case $TrayColorPicker ; ColorPicker
            ColorPicker()

        Case $TrayHelp ; Help
            HelpInfo()

        Case $TrayExit ; Exit
            GoToExit()

    EndSwitch

    ;if END key close ColorPicker
    If _IsPressed("23", $hDLL) Then
        Sleep(300)
        ColorPicker()
    EndIf

    Sleep(50)
WEnd

GoToExit()
;----------------------------------------------------------------------------------------
Func GoToExit()    ; exit
    CloseColorPicker()
    DllClose($hDLL)
    Exit
EndFunc   ;==>GoToExit
;----------------------------------------------------------------------------------------
Func ColorPicker()

    ; Create Color GUI
    $hColor_Win = GUICreate("Color", 100, 30, 0, 0, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
    GUICtrlCreateLabel("Label1", 0, 0, 100, 30, $SS_BLACKFRAME)
    $ColorLabel = GUICtrlCreateLabel(" ", 26, 7, 74, 20)
    $ColorRec = GUICtrlCreateLabel(" ", 1, 1, 25, 28)
    GUICtrlSetFont($ColorLabel, 10, 600, 0, "Consolas")
    GUICtrlSetBkColor($ColorLabel, $GUI_BKCOLOR_TRANSPARENT)
    GUISetState(@SW_SHOW, $hColor_Win)

    ; Create MAG GUI
    $hMag_GUI = GUICreate("MAG", 100, 100, 0, 0, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
    GUISetState(@SW_SHOW, $hMag_GUI)

    ; Get device context for Mag GUI
    $hMagDC = _WinAPI_GetDC($hMag_GUI)
    If @error Then Exit
    ; Get device context for desktop
    $hDeskDC = _WinAPI_GetDC(0)
    If @error Then
        _WinAPI_ReleaseDC($hMag_GUI, $hMagDC)
        Exit
    EndIf

    ; Create pen
    $hPen = _WinAPI_CreatePen($PS_SOLID, 5, 0x7E7E7E)
    $oObj = _WinAPI_SelectObject($hMagDC, $hPen)

    While 1

        ; Check if cursor has moved
        $aMouse_Pos = MouseGetPos()
        If $aMouse_Pos[0] <> $iLast_Mouse_X Or $aMouse_Pos[1] <> $iLast_Mouse_Y Then
            ; Redraw Mag GUI
            Loupe($aMouse_Pos)
            ; Reset position
            $iLast_Mouse_X = $aMouse_Pos[0]
            $iLast_Mouse_Y = $aMouse_Pos[1]
        EndIf

        Select
            Case _IsPressed("02", $hDLL) Or _IsPressed("10", $hDLL) ; 02 = Right mouse button ; 10 = SHIFT key
                TakeSnap()
                Return

            Case _IsPressed("23", $hDLL) ;23 END key
                TakeSnap()
                Return

            Case _IsPressed("1B", $hDLL) ;1B = ESC key
                CloseColorPicker()
                Return

            Case _IsPressed("25", $hDLL) ; 25 = LEFT ARROW key
                MouseMove($aMouse_Pos[0] - 1, $aMouse_Pos[1])
                Sleep(100)

            Case _IsPressed("26", $hDLL) ; 26 = UP ARROW key
                MouseMove($aMouse_Pos[0], $aMouse_Pos[1] - 1)
                Sleep(100)

            Case _IsPressed("27", $hDLL) ; 27 = RIGHT ARROW key
                MouseMove($aMouse_Pos[0] + 1, $aMouse_Pos[1])
                Sleep(100)

            Case _IsPressed("28", $hDLL) ; 28 = DOWN ARROW key
                MouseMove($aMouse_Pos[0], $aMouse_Pos[1] + 1)
                Sleep(100)

        EndSelect

    WEnd

EndFunc   ;==>ColorPicker
;----------------------------------------------------------------------------------------
Func Loupe($aMouse_Pos)
    Local $iX, $iY

    ; Fill Mag GUI with 10x expanded contents of desktop area (5 pixels around mouse)
    DllCall("gdi32.dll", "int", "StretchBlt", _
            "int", $hMagDC, "int", 0, "int", 0, "int", 100, "int", 100, _
            "int", $hDeskDC, "int", $aMouse_Pos[0] - 5, "int", $aMouse_Pos[1] - 5, "int", 10, "int", 10, _
            "long", $SRCCOPY)

    ; Original 10 x 10 expanded to 100 x 100 - 10x magnification

    $mColor = PixelGetColor($aMouse_Pos[0], $aMouse_Pos[1])
    $mColor = "0x" & Hex($mColor, 6) ;  * <--------------  color converted to hexadecimal
    GUICtrlSetData($ColorLabel, $mColor)
    GUICtrlSetBkColor($ColorRec, $mColor)

    ; Keep Mag GUI on screen
    If $aMouse_Pos[0] < (@DesktopWidth - 120) Then
        $iX = $aMouse_Pos[0] + 20
    Else
        $iX = $aMouse_Pos[0] - 120
    EndIf
    If $aMouse_Pos[1] < (@DesktopHeight - 150) Then
        $iY = $aMouse_Pos[1] + 20
    Else
        $iY = $aMouse_Pos[1] - 120
    EndIf
    WinMove($hMag_GUI, "", $iX, $iY, 100, 100)
    WinMove($hColor_Win, "", $iX, $iY + 100)

EndFunc   ;==>Loupe
;----------------------------------------------------------------------------------------
Func TakeSnap()
    ClipPut($mColor)
    ConsoleWrite($mColor & @CRLF)
    WinMove($hColor_Win, "", @DesktopWidth - 120, @DesktopHeight - 75)
    GUISetState(@SW_HIDE, $hMag_GUI)
    WinWait("[CLASS:#32768]", "", 1)
    If WinExists("[CLASS:#32768]") Then Send("{ESC}")
    Sleep(3000)
    CloseColorPicker()
EndFunc   ;==>TakeSnap
;----------------------------------------------------------------------------------------
Func CloseColorPicker()
    ; Clear up Mag GUI
    _WinAPI_SelectObject($hMagDC, $oObj)
    _WinAPI_DeleteObject($hPen)
    _WinAPI_ReleaseDC(0, $hDeskDC)
    _WinAPI_ReleaseDC($hMag_GUI, $hMagDC)
    GUIDelete($hMag_GUI)
    GUIDelete($hColor_Win)
EndFunc   ;==>CloseColorPicker
;----------------------------------------------------------------------------------------
Func HelpInfo()

    Local $Msg = @CRLF & "HotKey {END} call ColorPicker." & @CRLF & @CRLF _
             & "During ColorPicker is active" & @CRLF & @CRLF _
             & "{END} or {SHIFT} or Right mouse button" & @TAB & @CRLF _
             & "snap the Color to clipboard " & @CRLF & @CRLF _
             & "{LEFT}, {UP}, {RIGHT}, {DOWN}" & @CRLF _
             & "moves the mouse by 1 pixel" & @CRLF & @CRLF _
             & "{ESC} close ColorPicker to tray" & @CRLF & @CRLF _
             & "--->  Press {ESC} to exit  <---  " & @CRLF _
             & " " & @CRLF

    ToolTip($Msg, @DesktopWidth / 2, @DesktopHeight / 5, "info", 1)
    GUICtrlSetFont(-1, 14, 600, 0, "Arial")

    Do
        Sleep(100)
    Until _IsPressed("1B", $hDLL) ; 1B ESC key

    ToolTip("")

EndFunc   ;==>HelpInfo

 

Please, leave your suggestion , comments , experiences here. 

Thank you!  :)

 

Edited by ioa747

I know that I know nothing

Link to comment
Share on other sites

Hi @ioa747,

what I like is the Loupe() and the general idea 👍 . What I don't like or at least just do not understand is, the HotKeySet("{END}", "ColorPicker") on line 35. Each time I press end, the picker image is freezed. Is this intended and if yes, why and for what?

image.thumb.png.84350815fd595e4972b64f36b09acf05.png

Besides that, good job 😀 . As I small suggestion regarding code improvement, I would say you could restructure your code a bit more.

Best regards
Sven

________________
Stay innovative!

Stay innovative!

Spoiler

🌍 Au3Forums

🎲 AutoIt (en) Cheat Sheet

📊 AutoIt limits/defaults

💎 Code Katas: [...] (comming soon)

🎭 Collection of GitHub users with AutoIt projects

🐞 False-Positives

🔮 Me on GitHub

💬 Opinion about new forum sub category

📑 UDF wiki list

✂ VSCode-AutoItSnippets

📑 WebDriver FAQs

👨‍🏫 WebDriver Tutorial (coming soon)

Link to comment
Share on other sites

5 hours ago, SOLVE-SMART said:

What I don't like or at least just do not understand is, the HotKeySet("{END}", "ColorPicker") on line 35.

:oops:  You have right !!

With HotKeySet the script flow was trapped in loop.

I replace the code.   Thank you very much for response and your suggestion!  :)

I know that I know nothing

Link to comment
Share on other sites

  • 1 month later...

I really like the concept and overall functionality of this script! Being a little colorblind myself, I often use an app called "ColorPix" to grab colors from various places. It's great to see an AutoIt version that I might tweak to fit my needs.

I was wondering why it was so slow to respond and found the "Sleep(50)" in the main loop. Since the TrayGetMsg() "automatically idles the CPU", it should be safe to remove the sleep here. After removing that line, the program then becomes much more responsive. Just a thought.

It would also be nice to have some sort of indicator in the magnified window to show which color is selected, but that might be more effort than it's worth...
This is what it looks like in the ColorPix app with the little crosshair icon.

image.png.63142de8e81fc46b7766fa76129d3639.png

 

Link to comment
Share on other sites

On 1/3/2023 at 8:18 PM, ioa747 said:

the idea comes from @Melba23's Magnify  post.

StretchBlt has since been added to WinAPI, so in "proper" autoit...

Func Loupe($aMouse_Pos)
    Local $iX, $iY

_WinAPI_StretchBlt($hMagDC, 0, 0, 100, 100, $hDeskDC, $aMouse_Pos[0] - 5, $aMouse_Pos[1] - 5, 10, 10, $SRCCOPY)

    ; Original 10 x 10 expanded to 100 x 100 - 10x magnification

    $mColor = "0x" & Hex(PixelGetColor($aMouse_Pos[0], $aMouse_Pos[1]), 6) ;  * <--------------  color converted to hexadecimal
    GUICtrlSetData($ColorLabel, $mColor)
    GUICtrlSetBkColor($ColorRec, $mColor)

    ; Keep Mag GUI on screen
    If $aMouse_Pos[0] < (@DesktopWidth - 120) Then
        $iX = $aMouse_Pos[0] + 20
    Else
        $iX = $aMouse_Pos[0] - 120
    EndIf
    If $aMouse_Pos[1] < (@DesktopHeight - 150) Then
        $iY = $aMouse_Pos[1] + 20
    Else
        $iY = $aMouse_Pos[1] - 120
    EndIf
    WinMove($hMag_GUI, "", $iX, $iY, 100, 100)
    WinMove($hColor_Win, "", $iX, $iY + 100)

EndFunc   ;==>Loupe

 

Some guy's script + some other guy's script = my script!

Link to comment
Share on other sites

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

×
×
  • Create New...