SmartNote


 SmartNote is a screen snip tool to take fast note with OCR ability
 from Tesseract 100+ languages

 

I did some upgrades

·         can work on multiple monitors

·         I changed the hotkey so it can grab menus and context menus

·         I changed the environment to OnEvent Mode for smoother operation

·         Add entry to send picture to ShareX image editor

 

I tried it in Windows 10 with the version  tesseract-ocr-w32-setup-v5.3.0.20221214.exe

 

Snipe new note

While Right Windows Key IsPressed, tap 2 times the Right Shift key to start NewCapture,
is useful when Capture menu or context.

While start NewCapture point click anywhere to escape. (Does not catch smaller than 9*9 px)

While start NewCapture escape with ESC

 

Tesseract info

Of course, you will have to install it first. tesseract-installer-for-windows

Languages supported  https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html

More info Command-Line-Usage

 
; https://www.autoitscript.com/forum/topic/208600-smartnote/
;----------------------------------------------------------------------------------------
; Title...........: SmartNote.au3
; Description.....: SmartNote is a screen snip tool to take Screenshot with OCR ability from Tesseract (100+ languages)
; AutoIt Version..: 3.3.16.1   Author: ioa747
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#AutoIt3Wrapper_Res_Fileversion=0.0.3.20230924
#AutoIt3Wrapper_UseX64=n ; *<- DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", "int", -4) ; -4=PerMonitorAwareV2

#include <MsgBoxConstants.au3>
#include <ScreenCapture.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <StaticConstants.au3>
#include <TrayConstants.au3>
#include <Misc.au3>
#include <Array.au3>
#include <GDIPlus.au3>
#include <Clipboard.au3>
#include <String.au3>

; Initialization
DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", "int", -4) ; -4=PerMonitorAwareV2

Opt("MouseCoordMode", 1)  ; 1=absolute, 0=relative, 2=client
Opt("TrayMenuMode", 3)    ; 0=append, 1=no default menu, 2=no automatic check, 4=menuitemID  not return
Opt("TrayOnEventMode", 1) ; Enable TrayOnEventMode.
Opt("GUIOnEventMode", 1)  ; 0=disabled, 1=OnEvent mode enabled

; tray entry to exit script
Global $TRAY_ExitScript = TrayCreateItem("Exit")
TrayItemSetOnEvent(-1, "TRAY_EVENT")
; separator
TrayCreateItem("")
; tray entry to capture
Global $TRAY_NewCapture = TrayCreateItem("Capture")
TrayItemSetOnEvent(-1, "TRAY_EVENT")

TraySetOnEvent($TRAY_EVENT_PRIMARYDOUBLE, "TRAY_EVENT")
TraySetIcon("mmcndmgr.dll", -106)
TraySetState($TRAY_ICONSTATE_SHOW)
TraySetToolTip("SmartNote" & @CRLF & "Double Click to take new note")

Global $mPos, $aRecPos[4], $hGUICapture, $block_gui
Global $hDLL = DllOpen("user32.dll")
; array to hold the Contextmenu data
Global $NoteGui[1][12]

$NoteGui[0][0] = 0 ; cnt, Note_Handle
$NoteGui[0][1] = "jpgPath"
$NoteGui[0][2] = "Gui_Size"
$NoteGui[0][3] = "ID_PicCtrl"
$NoteGui[0][4] = "ID_ContextMenu"
$NoteGui[0][5] = "ID_cMenuCopy"
$NoteGui[0][6] = "ID_cMenuShareX"
$NoteGui[0][7] = "ID_cMenuSave"
$NoteGui[0][8] = "ID_cMenuOpen"
$NoteGui[0][9] = "ID_cMenuOCR-eng"
$NoteGui[0][10] = "ID_cMenuOCR-eng+ell"
$NoteGui[0][11] = "ID_cMenuClose"

; Check for leftover files
Global $iFileExists = FileExists(@ScriptDir & "\tmp")
If $iFileExists Then
    FileDelete(@ScriptDir & "\tmp\*.*")
Else
    DirCreate(@ScriptDir & "\tmp")
EndIf

; ℹ️  While Right Windows Key IsPressed, tap 2 times the Right SHIFT key to start NewCapture,
;     is useful when Capture menu or contex.
; While start NewCapture point click anywhere to escape. (does not catch smaller than 9*9 px)
; While start NewCapture escape with ESC

Global $iShift

; loop until program exit
;************************************************
While Sleep(100)
    $iShift = 0
    While _IsPressed("5C", $hDLL) ; 5C = Right Windows key
        Sleep(100)
        If _IsPressed("A1", $hDLL) Then ; A1 = Right SHIFT key
            Sleep(100)
            $iShift += 1
        EndIf

        If $iShift = 2 Then
            NewCapture()
            ExitLoop
        EndIf
    WEnd
WEnd
;************************************************

;----------------------------------------------------------------------------------------
Func NewCapture()                       ; NewCapture <<- HotKey WIN /

    Local $aRecPos[4], $aMPos[2], $tPos ;, $aTipPos[4], $iX, $iY
    Local $iDeskWidth, $iDeskHeight, $iDeskLeft, $iDeskTop
    Local $sDevice, $hMonitor, $sCurDevice, $aData, $Status = 0

    ; make Capture gui
    $hGUICapture = GUICreate("Capture_gui", 1, 1, 1, 1, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
    GUISetBkColor("0xFFFF00", $hGUICapture) ; $COLOR_YELLOW
    WinSetTrans($hGUICapture, "", 50)

    ; make mouse block gui
    $block_gui = GUICreate("block_gui", 1, 1, 1, 1, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
    WinSetTrans($block_gui, "", 1)
    GUISetState(@SW_SHOW, $block_gui)
    GUISetCursor($MCID_CROSS, 1, $block_gui)

    Sleep(200)

    Local $iMaxLoop = 1200, $iCntLoop = 0

    While Sleep(10)
        $iCntLoop += 1
        If $iCntLoop = $iMaxLoop Then ExitLoop

        ; get mouse coordinates
        $tPos = _WinAPI_GetMousePos()
        $aMPos[0] = DllStructGetData($tPos, 1)
        $aMPos[1] = DllStructGetData($tPos, 2)

        ; get $hMonitor from previously defined Mouse coordinates
        $hMonitor = _WinAPI_MonitorFromPoint($tPos)

        ; get monitor $aData appropriate for previously defined coordinates
        $aData = _WinAPI_GetMonitorInfo($hMonitor)
        If Not @error Then
            $sDevice = $aData[3]
            $iDeskLeft = DllStructGetData($aData[0], 1)
            $iDeskTop = DllStructGetData($aData[0], 2)
            $iDeskWidth = DllStructGetData($aData[0], 3)
            $iDeskHeight = DllStructGetData($aData[0], 4)
        EndIf

        ;move the $block_gui to active monitor
        If $sCurDevice <> $sDevice Then
            $sCurDevice = $sDevice
            ;ConsoleWrite("- $sCurDevice=" & $sCurDevice & @CRLF)
            WinMove($block_gui, "", $iDeskLeft, $iDeskTop, $iDeskWidth, $iDeskHeight)
        EndIf

        ; whait  Left_mouse_button _IsPressed
        If _IsPressed("01", $hDLL) Then
            $Status = 1
            $aMPos = MouseGetPos()
            $aRecPos[0] = $aMPos[0]
            $aRecPos[1] = $aMPos[1]

            ; Wait until key is released.
            While _IsPressed("01", $hDLL)
                Sleep(50)
                $aMPos = MouseGetPos()
                $aRecPos[2] = $aMPos[0]
                $aRecPos[3] = $aMPos[1]

                ; show Capture gui
                GUISetState(@SW_SHOW, $hGUICapture)
                WinMove($hGUICapture, "", $aRecPos[0], $aRecPos[1], $aRecPos[2] - $aRecPos[0], $aRecPos[3] - $aRecPos[1])
            WEnd
        ElseIf _IsPressed("1B", $hDLL) Then ;1B=ESC key - emergency exit
            GUIDelete($hGUICapture)
            GUIDelete($block_gui)
            Return SetError(1, 1, 0)
        EndIf

        If $Status = 1 Then ExitLoop
    WEnd

    GUIDelete($hGUICapture)
    GUIDelete($block_gui)

    ;ConsoleWrite($aRecPos[0] & ";" & $aRecPos[1] & ";" & $aRecPos[2] - $aRecPos[0] & ";" & $aRecPos[3] - $aRecPos[1] & @CRLF)

    ; if bigger from 9*9 px then create note
    If ($aRecPos[2] - $aRecPos[0]) > 9 And ($aRecPos[3] - $aRecPos[1]) > 9 Then CreateNew_NoteGui($aRecPos)  ; create new note

    ;Return $FilePath

EndFunc   ;==>NewCapture
;----------------------------------------------------------------------------------------
Func CreateNew_NoteGui($aRecPos)        ; create new note gui

    Local $n, $aSize[2]

    ReDim $NoteGui[UBound($NoteGui) + 1][12]
    $NoteGui[0][0] += 1

    $n = $NoteGui[0][0]

    $aSize[0] = $aRecPos[2] - $aRecPos[0] ; width
    $aSize[1] = $aRecPos[3] - $aRecPos[1] ; height

    ; create note GUI
    $NoteGui[$n][0] = GUICreate($NoteGui[$n][1], $aSize[0], $aSize[1], $aRecPos[0], $aRecPos[1], $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_TOPMOST))
    GUISetOnEvent($GUI_EVENT_RESIZED, "GUI_EVENT", $NoteGui[$n][0])

    ; jpg Path for _ScreenCapture_Capture
    $NoteGui[$n][1] = @ScriptDir & "\tmp\image_" & $NoteGui[$n][0] & ".jpg"
    _ScreenCapture_Capture($NoteGui[$n][1], $aRecPos[0], $aRecPos[1], $aRecPos[2], $aRecPos[3])

    ; save the Gui_Size
    $NoteGui[$n][2] = $aSize

    ; set jpg Path as GUI title
    WinSetTitle($NoteGui[$n][0], "", $NoteGui[$n][1])

    ; Creates a Picture control
    $NoteGui[$n][3] = GUICtrlCreatePic($NoteGui[$n][1], 0, 0, 0, 0, -1, $GUI_WS_EX_PARENTDRAG)

    ; Creates a Label control just for $SS_GRAYFRAME
    GUICtrlCreateLabel("", 0, 0, $aSize[0], $aSize[1], $SS_GRAYFRAME)

    ; Creates a context menu
    $NoteGui[$n][4] = GUICtrlCreateContextMenu($NoteGui[$n][3])

    ; MenuItem for the context menu "Copy to Clipboard"
    $NoteGui[$n][5] = GUICtrlCreateMenuItem("Copy to Clipboard", $NoteGui[$n][4])
    GUICtrlSetOnEvent(-1, "cm_CopyToClipboard")

    ; MenuItem for the context menu "ID_cMenuShareX"
    $NoteGui[$n][6] = GUICtrlCreateMenuItem("Send to ShareX", $NoteGui[$n][4])
    GUICtrlSetOnEvent(-1, "cm_ShareX")

    ; MenuItem for the context menu "Save as..."
    $NoteGui[$n][7] = GUICtrlCreateMenuItem("Save as...", $NoteGui[$n][4])
    GUICtrlSetOnEvent(-1, "cm_SaveAs")

    ; MenuItem for the context menu "Open"
    $NoteGui[$n][8] = GUICtrlCreateMenuItem("Open", $NoteGui[$n][4])
    GUICtrlSetOnEvent(-1, "cm_Open")

    ; separator
    GUICtrlCreateMenuItem("", $NoteGui[$n][4])

    ; MenuItem for the context menu "OCR - eng"
    $NoteGui[$n][9] = GUICtrlCreateMenuItem("OCR - eng", $NoteGui[$n][4])
    GUICtrlSetOnEvent(-1, "cm_OCR_Eng")

    ; MenuItem for the context menu "OCR - eng+ell"
    $NoteGui[$n][10] = GUICtrlCreateMenuItem("OCR - eng+ell", $NoteGui[$n][4])
    GUICtrlSetOnEvent(-1, "cm_OCR_EngEll")

    ; separator
    GUICtrlCreateMenuItem("", $NoteGui[$n][4])

    ; MenuItem for the context menu "Close"
    $NoteGui[$n][11] = GUICtrlCreateMenuItem("Close", $NoteGui[$n][4])
    GUICtrlSetOnEvent(-1, "cm_Close")

    ; Display the GUI.
    GUISetState(@SW_SHOW, $NoteGui[$n][0])

    Return $NoteGui[$n][0]

EndFunc   ;==>CreateNew_NoteGui
;----------------------------------------------------------------------------------------
Func SaveFileDlg($Active_title)         ; Save file Dialog
    ; Create a constant variable in Local scope of the message to display in FileSaveDialog.
    Local Const $sMessage = "Choose a filename."

    ; Display a save dialog to select a file.
    Local $sFileSaveDialog = FileSaveDialog($sMessage, @ScriptDir & "\SET\", "image (*.jpg)", $FD_PATHMUSTEXIST)
    If @error Then
        ; Display the error message.
        MsgBox($MB_SYSTEMMODAL, "", "No file was saved.")
    Else
        ; Retrieve the filename from the filepath e.g. Example.jpg
        Local $sFileName = StringTrimLeft($sFileSaveDialog, StringInStr($sFileSaveDialog, "\", $STR_NOCASESENSEBASIC, -1))

        ; Check if the extension .jpg is appended to the end of the filename.
        Local $iExtension = StringInStr($sFileName, ".", $STR_NOCASESENSEBASIC)

        ; If a period (dot) is found then check whether or not the extension is equal to .jpg
        If $iExtension Then
            ; If the extension isn't equal to .jpg then append to the end of the filepath.
            If Not (StringTrimLeft($sFileName, $iExtension - 1) = ".jpg") Then $sFileSaveDialog &= ".jpg"
        Else
            ; If no period (dot) was found then append to the end of the file.
            $sFileSaveDialog &= ".jpg"
        EndIf

        ; Display the saved file.
        ;ConsoleWrite("You saved the following file:" & @CRLF & $sFileSaveDialog & @CRLF)

        FileCopy($Active_title, $sFileSaveDialog, $FC_OVERWRITE + $FC_CREATEPATH)

    EndIf
EndFunc   ;==>SaveFileDlg
;----------------------------------------------------------------------------------------
Func NoteGui_Delete($hWnd)              ; NoteGui_Delete
    For $i = 1 To $NoteGui[0][0]
        If $NoteGui[$i][0] = $hWnd Then
            _ArrayDelete($NoteGui, $i)
            $NoteGui[0][0] -= 1
            ExitLoop
        EndIf
    Next
EndFunc   ;==>NoteGui_Delete
;----------------------------------------------------------------------------------------
Func PicToClip($Path)                   ; put image to clipboard (Thanks to @Nine)
    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile($Path)
    Local $hBitmap1 = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    _GDIPlus_ImageDispose($hImage)

    Local $hBitmap2 = _WinAPI_CopyImage($hBitmap1, $IMAGE_BITMAP, 0, 0, $LR_COPYDELETEORG + $LR_COPYRETURNORG)
    _WinAPI_DeleteObject($hBitmap1)
    _GDIPlus_Shutdown()

    _ClipBoard_Open(0)
    _ClipBoard_Empty()
    _ClipBoard_SetDataEx($hBitmap2, $CF_BITMAP)
    _ClipBoard_Close()
    _WinAPI_DeleteObject($hBitmap2)

EndFunc   ;==>PicToClip
;----------------------------------------------------------------------------------------
Func TesseracOCR($ImagePath, $lang)     ; perform ocr (Thanks to JohnOne)

;~ ; $lang = more LangCode  ->  https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html
;~ ; more info at  ->  https://tesseract-ocr.github.io/tessdoc/Command-Line-Usage.html#simplest-invocation-to-ocr-an-image
;~ ; Of course you will have to install it first. -> https://github.com/UB-Mannheim/tesseract/wiki
;~ ; I tried it in Windows 10 with the version ->  https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-w32-setup-v5.3.0.20221214.exe

    Local $ResultTextPath, $OutPutPath, $Result

    ;C:\Program Files (x86)\Tesseract-OCR\tesseract.exe
    Local Const $TesseractExePath = @ProgramFilesDir & "\Tesseract-OCR\tesseract.exe" ; ℹ️ Give your path * <-

    $ResultTextPath = @ScriptDir & "\tmp\Result"
    $OutPutPath = $ResultTextPath & ".txt"

    ShellExecuteWait($TesseractExePath, '"' & $ImagePath & '" "' & $ResultTextPath & '" -l ' & $lang & ' --psm 6', "", "", @SW_HIDE)
    ;ConsoleWrite($TesseractExePath & ' "' & $ImagePath & '" "' & $ResultTextPath & '" -l ' & $lang & ' --psm 6' & @CRLF)

    If @error Then
        Exit MsgBox($MB_OK + $MB_TOPMOST + $MB_ICONERROR, "Error", @error)
    EndIf

    $Result = FileRead($OutPutPath)

    Local $Msg = @CRLF & @CRLF & _StringRepeat(@TAB, 4) & "Copy to ClipBoard ?"
    Local $iMsgBoxAnswer = MsgBox(4, "OCR Result", $Result & $Msg)
    If $iMsgBoxAnswer = 6 Then ;Yes
        ClipPut($Result)
        ToolTip("The text was copied to the clipboard")
        Sleep(1000)
        ToolTip("")
    EndIf
    FileDelete($OutPutPath)
EndFunc   ;==>TesseracOCR
;----------------------------------------------------------------------------------------
Func TRAY_EVENT()         ; TRAY_Event
    Switch @TRAY_ID ; Check the last tray item identifier.
        Case $TRAY_EVENT_PRIMARYDOUBLE
            NewCapture()

        Case $TRAY_NewCapture
            NewCapture()

        Case $TRAY_ExitScript
            DllClose($hDLL)
            Exit

    EndSwitch
EndFunc   ;==>TRAY_EVENT
;----------------------------------------------------------------------------------------
Func GUI_EVENT()          ; GUI_EVENT
    Select
        Case @GUI_CtrlId = $GUI_EVENT_RESIZED
            Local $aSize
            For $i = 1 To $NoteGui[0][0]
                If $NoteGui[$i][0] = @GUI_WinHandle Then
                    $aSize = $NoteGui[$i][2]
                    WinMove(@GUI_WinHandle, "", Default, Default, $aSize[0], $aSize[1])
                    ControlMove(@GUI_WinHandle, "", "Static1", 0, 0, $aSize[0], $aSize[1])
                    ControlMove(@GUI_WinHandle, "", "Static2", 0, 0, $aSize[0], $aSize[1])
                    ExitLoop
                EndIf
            Next
    EndSelect
EndFunc   ;==>GUI_EVENT
;----------------------------------------------------------------------------------------
Func cm_CopyToClipboard() ; ContextMenu  "Copy to Clipboard"
    Local $Active_title = WinGetTitle(@GUI_WinHandle)
    PicToClip($Active_title)
EndFunc   ;==>cm_CopyToClipboard
;----------------------------------------------------------------------------------------
Func cm_ShareX()          ; ContextMenu  "Send to ShareX""
    Local $Active_title = WinGetTitle(@GUI_WinHandle)
    PicToClip($Active_title)
    Sleep(100)
    Local $strLen = StringLen(@ScriptDir & "\tmp\image_")
    If StringLeft($Active_title, $strLen) = @ScriptDir & "\tmp\image_" Then
        GUIDelete(@GUI_WinHandle)
        FileDelete($Active_title)
        NoteGui_Delete(@GUI_WinHandle)
    EndIf

    ShellExecute("C:\Program Files\ShareX\ShareX.exe", "-imageeditor ") ; ℹ️ Give your path * <-
    Local $hShareXImageEd = WinWait("[TITLE:ShareX - Image editor; REGEXPCLASS:WindowsForms10\.Window\..\.app\.0\..+_r\d+_ad1]", "", 2)
    While WinExists($hShareXImageEd)
        ControlClick($hShareXImageEd, "", "[NAME:btnLoadImageFromClipboard]")
        Sleep(300)
    WEnd
    $hShareXImageEd = WinWait("[TITLE:ShareX - Image editor; REGEXPCLASS:WindowsForms10\.Window\..\.app\.0\..+_r\d+_ad1]", "", 2)
    WinActivate($hShareXImageEd)
    WinSetState($hShareXImageEd, "", @SW_MAXIMIZE)

EndFunc   ;==>cm_ShareX
;----------------------------------------------------------------------------------------
Func cm_SaveAs()          ; ContextMenu  "Save as..."
    Local $Active_title = WinGetTitle(@GUI_WinHandle)
    SaveFileDlg($Active_title)
EndFunc   ;==>cm_SaveAs
;----------------------------------------------------------------------------------------
Func cm_Open()            ; ContextMenu  "Open"
    Local $Active_title = WinGetTitle(@GUI_WinHandle)
    ShellExecute($Active_title)
EndFunc   ;==>cm_Open
;----------------------------------------------------------------------------------------
Func cm_OCR_Eng()         ; ContextMenu  "OCR - eng"
    Local $Active_title = WinGetTitle(@GUI_WinHandle)
    TesseracOCR($Active_title, "eng")
EndFunc   ;==>cm_OCR_Eng
;----------------------------------------------------------------------------------------
Func cm_OCR_EngEll()      ; ContextMenu  "OCR - eng+ell"
    Local $Active_title = WinGetTitle(@GUI_WinHandle)
    TesseracOCR($Active_title, "eng+ell")
EndFunc   ;==>cm_OCR_EngEll
;----------------------------------------------------------------------------------------
Func cm_Close()           ; ContextMenu  "Close"
    Local $Active_title = WinGetTitle(@GUI_WinHandle)
    Local $strLen = StringLen(@ScriptDir & "\tmp\image_")
    If StringLeft($Active_title, $strLen) = @ScriptDir & "\tmp\image_" Then
        GUIDelete(@GUI_WinHandle)
        FileDelete($Active_title)
        NoteGui_Delete(@GUI_WinHandle)
        ;ConsoleWrite("- WinClose " & @GUI_WinHandle & " & FileDelete " & $Active_title & @CRLF)
    EndIf
EndFunc   ;==>cm_Close
;----------------------------------------------------------------------------------------

 



Comments

Popular posts from this blog

ControlGetHandle ($hWnd, "", "[REGEXPCLASS:<>; INSTANCE:<>]")

Simple Calculator