1 (изменено: Krot66, 2014-12-29 11:13:08)

Тема: AHK: Скрипт для снятия скриншотов с автосортировкой

Скрипт извлекает различную информацию из активного окна и на основании нее определяет путь сохранения скриншота. Никаких запросов на сохранение - на несколько секунд выводится превью полученного скриншота с указанием папки сохранения и размеров изображения. Если в этот момент нажать Enter - файл откроется в выбранном редакторе, пробел - станет возможно преименование файла, Ctrl - откроется окно эксплорера для сохранения файла в другом месте.

Для всех видов скриншотов используется одна функция

St(type,path)

Здесь type - тип скриншота:

f - скриншот полного экрана
w - активного окна
s - выделенной области (выводится масштабируемое полупрозрачное окно; правый шелчок по нему - подтверждение выбора, Escape или правый щелчок вне его - отмена)

Возможные расширения скриншотов - bmp, jpg, png. Помимо постоянных значений, в пути возможно использование следующих переменных (примеры смотри в начале скрипта):

$date - подстрока вида 2014.12.22
$time - подстрока вида 18.54.30. Если ею не пользоваться, при совпадении имен производится автопереименование
$proc - имя процесса активного окна без расширения
$site - корневой адрес открытого в браузере сайта
$title - полный заголовок окна
$file - название или имя файла без расширения, взятое из заголовка окна (обрабатываются стандартные заголовки и полный путь файла, если он там есть)
$cmd - - имя файла без расширения, извлеченное из командной строки открытой вместе с файлом программы
$cmt - совмещающает возможности двух предыдущих: сначала ищется имя файла в командной строке, а если он отсутствует, используется заголовок окна
$z - использование в любом месте выводит краткий тултип подтверждения вместо превью

Для работы скрипта требуется присутствие в каталоге скрипта или в %PATH% nircmd.exe, который можно скачать здесь: http://www.nirsoft.net/utils/nircmd.html

Получить тонкий, эстетичный бордюр окна выделения на Windows 8+ можно с помощью Tiny Windows Borders: http://winaero.com/comment.php?comment.news.96

---------------------------
UPD: Смотри ниже улучшенный вариант на основе GDI+, не требующий nircmd.exe
UPD: Смотри ниже вариант со встроенным распознаванием текста на базе Tesseract-OCR

#NoEnv 
SendMode Input 
SetWorkingDir %A_ScriptDir%
#SingleInstance, force
Menu Tray, Icon, shell32.dll, 35
SetTitleMatchMode 2
SetTitleMatchMode Slow
CoordMode Mouse, Screen

; --------- Настройки ---------
color:="FFDC00" ; цвет окна выделения
transp:=150 ; его прозрачность (0-255)
sel:=80 ; его начальный размер
pr_time:=3 ; время показа превью, сек
tab:=3 ; число цифр c ведущими нулями при автопереименовании
ed_path:="D:\Soft\Chasys Draw IES\Artist.exe"  ; путь к редактору
;------------------------------

<+PrintScreen::St("f","#Screenshots\$proc\$date-$time_$title.png") ; LShift+PrintScreen - скриншот всего экрана в папку процесса активного окна

#PrintScreen::St("w","#Screenshots\$proc\$date-$time_$title.png") ; Win+PrintScreen - скриншот активного окна в папку процесса активного окна

<^PrintScreen::St("s","#Screenshots\$proc\$date-$time_$title.png") ;LCtrl+PrintScreen - скриншот выделенной области в папку процесса активного окна

>^PrintScreen::St("s","#Files\$file\img.png") ;RCtrl+PrintScreen - скриншот выделенной области в папку открытого файла (для цитат электронных книг и пр.)

<^<+PrintScreen::St("s","#Sites\$site\$file.png") ;LCtrl+LShift+PrintScreen - скриншот выделенной области в папку открытого сайта с именем из заголовка страницы

>+PrintScreen::St("s","#Платежи\$site\$date\img.png") ;RShift+PrintScreen - скриншоты электронных платежей с сортировкой по сайтам и датам

>^>+PrintScreen::St("s","#Формы\[$site]-$file.png") ;RCtrl+RShift+PrintScreen - скриншоты регистрационных форм

; -----------------------------
<!PrintScreen::Run %s_path% ; LAlt+PrintScreen - открытие последнего скриншота

>!PrintScreen::Run %s_folder% ; RAlt+PrintScreen - открытие папки последнего скриншота

;------------------------------
St(type,f_path)
{
    global
    KeyWait Ctrl, T1
    KeyWait Shift, T1
    KeyWait Alt, T1
    KeyWait PrintScreen, T1
    tp:=type, fp:=f_path, z:=""
    If (type="s") && select
        goto End    
    FormatTime date, , yyyy.MM.dd
    FormatTime time, , HH.mm.ss
    WinGetActiveTitle t
    WinGet proc, ProcessName, % t
    SplitPath proc, , , , proc
    StringUpper proc, proc, T
    title:=ValidName(t)
    file:=ValidName(CleanTitle(t))
    cmd:=GetPath(t)
    SplitPath cmd, , , ,cmd
    If cmd
        cmt:=cmd
    else
    { 
        cmt:=file
        If f_path contains $cmd 
        {
                MsgBox, 262160, Ошибка, Имя открытого файла недоступно!, 1.5
                return
        }
    }
    If f_path contains $site
    {
        Clipboard:=""
        Send ^{vk4C}
        Sleep 500
        Send ^{vk43}
        ClipWait 1
        RegExMatch(Clipboard,"(?<=//).+?(?=/)",site)
        If ! site
        {
            MsgBox, 262160, Ошибка, Адрес недоступен!, 1.5
            return
        }
    }
    If (type="s") && (select="")
    {
        MouseGetPos mx, my
        Gui Destroy
        Gui Color, % color
        Gui +Lastfound +Resize AlwaysOnTop -Caption +ToolWindow -DPIScale
        WinSet Transparent, % transp
        Gui Show, x%mx% y%my% w%sel% h%sel%, selectwindow
        select:=1
        return
    }
    End:
    StringReplace tag, tag, $site, % stag
    StringReplace s_path, f_path, $date, % date
    StringReplace s_path, s_path, $time, % time
    StringReplace s_path, s_path, $proc, % proc
    StringReplace s_path, s_path, $site, % site
    StringReplace s_path, s_path, $title, % title
    StringReplace s_path, s_path, $file, % file
    StringReplace s_path, s_path, $cmd, % cmd
    StringReplace s_path, s_path, $cmt, % cmt
    StringReplace s_path, s_path, $z
    If ! Errorlevel
        z:=1        
    s_path:=RenIfExist(s_path,tab)
    SplitPath s_path, , s_folder, s_ext, s_file
    FileCreateDir % s_folder
    If (type="f")
    {
        SysGet, M, Monitor
        sw:=MRight
        sh:=MBottom
        RunWait % "nircmd.exe savescreenshot new." s_ext
    }        
    If (type="w")
    {
        WinGetPos, , , sw, sh,% t
        RunWait % "nircmd.exe savescreenshotwin new." s_ext
    }
    If (type="s")
        RunWait % "nircmd.exe savescreenshot new." s_ext " " sx " " sy " " sw " " sh
    FileMove % "new." s_ext,% s_path
    FileGetSize sz,% s_path, K
    If z
    {
        ToolTip Сохранено
        Sleep 600
        ToolTip
        return
    }
    SplashImage % s_path, B1 ZW800 ZH-1 ZX20 ZY20 Fm14 Fs12 CW808080 CTFFFFFF C00,{Enter} - редактирование`n{Ctrl} - сохранить как`n{Space} - переименование файла"  ,% "Папка:  "  s_folder "`nИмя:  " s_file "." s_ext "`n" sw "x" sh "   " sz " KB", preview
    WinActivate preview
    Sleep % pr_time*1000
    SplashImage Off
    select:=""
    return
}

#IfWinActive selectwindow ahk_class AutoHotkeyGUI
RButton::
KeyWait RButton, T1
WinGetPos sx, sy, sw, sh, selectwindow
MouseGetPos mx, my
If (mx>sx && mx<sx+sw && my>sy && my<sy+sh)
{
    Gui Destroy
    St(tp,fp)
    return
}
GuiEscape:
Gui Destroy
select:=""
Sleep 200
return

#IfWinActive preview ahk_class AutoHotkey2      
Space::
SplashImage Off
Sleep 500
;~ Rename:
InputBox s_file, Переименование, Введите имя файла без расширения:, , 500, 130, , , , ,% s_file
s_file:=ValidName(s_file)
s_path_new:=RenIfExist(s_folder "\" s_file "." s_ext,1)
;~ IfExist % s_path_new
    ;~ goto Rename
FileMove % s_path, % s_path_new
s_path:=s_path_new
return
Enter::
NumpadEnter::
SplashImage Off
Run % ed_path " " s_path
return
Ctrl::
SplashImage Off
FileSelectFile s_path_new, S, % s_file "." s_ext, Выберите место сохранения, Изображения (*.bmp; *.jpg; *.png)
FileMove % s_path, % s_path_new
s_path:=s_path_new
SplitPath s_path, , s_folder
return
Esc::SplashImage Off
#IfWinActive

;-----------------------------    
CleanTitle(t)
{
    RegExMatch(t,"(?<=\)\.+?(?=\.[a-zA-Z0-9]{2,4}(]| |$|\}))",title)
    If ! title
        RegExMatch(t,"(?<=\[).+\.[a-zA-Z0-9]{2,4}(?=])",title)
    If ! title
        RegExMatch(t,"^.+\.[a-zA-Z0-9]{2,4}(?=( - | \| ))",title)
    If ! title
        RegExMatch(t,"(?<= - ).+\.[a-zA-Z0-9]{2,4}$",title)
    SplitPath title, , , ,title
    If ! title
        RegExMatch(t,"^.+(?= - )",title)
    If ! title
        title:=t
    return title
}

GetPath(title)
{
    WinGet pr, ProcessName, % title 
    Process, Exist, % pr 
    pid := ErrorLevel
    for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
    If (process.ProcessId = pid)
    cmdline := process.CommandLine
    If cmdline contains Explorer.exe
        cmdline:=""
    fp:=RegExMatch(cmdline,"[A-Z]:\\.*\.[a-zA-Z0-9]{2,4}",f_path,6)
    return f_path
}

RenIfExist(f_path,tab)
{
    If ! FileExist(f_path)
        return f_path
    SplitPath f_path, , dir, ext, file
    Loop % dir "\" file "*." ext
    {
        n:=0
        RegExMatch(A_LoopFileName,"(?<=_)\d+?(?=\.[a-zA-Z0-9]{2,4}$)",n)
        If ! n
            n_max:=0
        If (n>n_max)
            n_max:=n
    }
    SetFormat float, % "0" tab
    return dir "\" file "_" n_max+1.0 "." ext
}

ValidName(n,r="")
{
    n:=RegExReplace(n,"(:|;|,|\*|\?|\\|/|<|>|"")"," ")
    n:=RegExReplace(n,"\s+"," ")
    StringReplace n, n, |, -, All
    If r
        StringReplace n, n, % " ", % r
    return Trim(n)
}



2

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Krot66 пишет:

Для работы скрипта требуется присутствие в каталоге скрипта или в %PATH% nircmd.exe

А зачем? Снять скриншот можно и без nircmd.exe, на чистом AHK.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Можно, но надо ковыряться с GDIplus. nircmd позволяет написать простой, компактный скрипт не уходя в эти дебри, а недостатков у нее - только фиксированные разрешение и сжатие jpg

4

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Ну, если идти по пути, чтобы меньше ковыряться, то вообще не имеет смысла что-то программировать, достаточно хорошо погуглить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Я бы и не програмировал, но тут такая нищета: из десятков программ - ни одной подходящей. Так что собрав свой утлый скарб и вооружившись принципом наименьшего действия...

6

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Krot66 пишет:

вооружившись принципом наименьшего действия...

Ну в таком случае имейте в виду, что в Коллекции в комплекте скрипта для снятия скриншотов уже есть функция CaptureScreen(), принимающая координаты экрана, нужное расширение результирующего файла и разрешение для случая, если выбран jpg, и выдающая скриншот на выходе. Если скажете, чем nircmd.exe удобнее, готов рассмотреть этот вариант.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

но тут такая нищета: из десятков программ - ни одной подходящей.

Когда мне надо было, я почему то нашёл, и адаптировал не лезя в дебри, просто следуя примеру.
Думаю очевидно, что файл исходника всегда лучше стороннего экзешника, тем более на фоне:

а недостатков у нее - только фиксированные разрешение и сжатие jpg

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

8

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Да, всё уже расковыряно до нас. Но я думаю, что разные варианты решения задачи имеют право на существование. По крайней мере отец-основатель script-coding, The gray Cardinal, придерживался этой идеологии.

9

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Смущает в основном количество глюков и проблем с 64-битными системами. Nircmd проста и надежна как револьвер. Потом некоторые люди вообще сторонятся истинных и правильных вещей, которых не разумеют.
Фиксированное сжатие jpg имеет мало значения, поскольку есть несжатый png. Если надо вставить в сканнер, есть море пакетных обработчиков, которые поднимут разрешение до 300

10

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

YMP пишет:

разные варианты решения задачи имеют право на существование

Так кто ж им запрещает! Вопрос, каким вариантом в итоге пользоваться, более, или менее рациональным.

Krot66 пишет:

Смущает в основном количество глюков и проблем с 64-битными системами.

У меня 64-битная, не сталкивался.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Хорошо, попробуем

12

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

teadrinker пишет:
YMP пишет:

разные варианты решения задачи имеют право на существование

Так кто ж им запрещает! Вопрос, каким вариантом в итоге пользоваться, более, или менее рациональным.

А как ты измеришь рациональность?

13

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Да просто, чем меньше лишних действий требуется, тем рациональнее. Ну и надёжность тоже сюда входит.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

А возможно авто вырезание картинки с помощью которой AHK само определяет ее размер для вырезания?

15

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Как это — «само»?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Сомнительно это - как браузер передаст координаты изображения? Проще слепить скрипт для быстрого сохранения браузерных картинок, можно с подписью из выделенного текста. Для Оперы такой себе делал

17

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Krot66 пишет:

Сомнительно это - как браузер передаст координаты изображения?

Обычно открывается картинка в новой вкладке и фон вокруг нее белый, на таком же принципе можно сделать универсальный обрезчик картинок который умеет различать цвет фона. Перед вырезанием картинки указываешь скрипту на цвет фона и он игнорирует его и воспринимает как за рамку внутри которого картинка, потом приводишь курсор на один из углов картинки и скрипт движет уже дальше сам  и определяет что фон, а что картинка.

18

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Наверное, можно, но особого смысла не вижу. Выделить необходимую область на экране вручную не составляет никакого труда. Либо меню «сохранить изображение» использовать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

teadrinker пишет:

Наверное, можно, но особого смысла не вижу.

Просто упрощение работы для ленивых.

20

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Ну, алгоритм могу подсказать: с помощью PixelGetColor по каждой из координат определить, где заканчивается и где снова начинается последовательность пикселей указанного цвета.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Картинки будут извлекаться не в их оригинальном качестве. Это подходит для распознавания штрихкодов, но не собирания картинок как таковых

22

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

А когда вы скриншот делаете, картинки в оригинальном качестве извлекаются? И пожалуйста, найдите отсутствующие точки в конце предложений.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

23

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Krot66 пишет:

Потом некоторые люди вообще сторонятся истинных и правильных вещей, которых не разумеют.

Krot66 пишет:

Хорошо, попробуем

Попробуйте.

И можно ещё Вас попросить, ссылку на энциклопедию истинных и правильных вещей? А то мы тут без разумения истины, в основном ерундой занимаемся.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

24

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

teadrinker пишет:

Ну, алгоритм могу подсказать: с помощью PixelGetColor по каждой из координат определить, где заканчивается и где снова начинается последовательность пикселей указанного цвета.

Можно сделать отдельную тему и там обсуждать и действия и что скрипт должен выполнять. Как предложение можно сделать собственную программу (с использованием других программ) для вырезания картинок, а если точнее то программу исполнитель для программы которая вырезает.

25

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

В принципе можно сделать так: узнаем, какой Id у картинки под мышкой, вычисляем его местоположение на странице и сохраняем. Только зачем такие сложности, когда можно сделать save as.

26

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Malcev пишет:

В принципе можно сделать так: узнаем, какой Id у картинки под мышкой, вычисляем его местоположение на странице и сохраняем. Только зачем такие сложности, когда можно сделать save as.

Такой вариант подходит для стандартного сохранения картинки, но если в плане рабочем и когда стоят ограничения на загрузку картинки такие как: размер до 1000х1000 и не более чем 300kb. То нужен другой подход вырезания картинки.

27 (изменено: Krot66, 2014-12-24 14:58:10)

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Вариант на основе GDI+, не требующий наличия nircmd.exe
Поддерживаемые форматы теперь bmp, gif, jpg, png и tif
Появилась настройка качества jpg

#NoEnv 
SendMode Input 
SetWorkingDir %A_ScriptDir%
#SingleInstance, force
Menu Tray, Icon, shell32.dll, 35
SetTitleMatchMode 2
SetTitleMatchMode Slow
CoordMode Mouse, Screen

; --------- Настройки ---------
color:="FFDC00" ; цвет окна выделения
transp:=150 ; его прозрачность (0-255)
sel:=80 ; его начальный размер
nQuality:=90 ; качество JPEG
pr_time:=3 ; время показа превью, сек
tab:=3 ; число цифр c ведущими нулями при автопереименовании
ed_path:="D:\Soft\Chasys Draw IES\Artist.exe"  ; путь к редактору
;------------------------------

<+PrintScreen::St("f","#Screenshots\$proc\$date-$time_$title.png") ; LShift+PrintScreen - скриншот всего экрана в папку процесса активного окна

#PrintScreen::St("w","#Screenshots\$proc\$date-$time_$title.png") ; Win+PrintScreen - скриншот активного окна в папку процесса активного окна

<^PrintScreen::St("s","#Screenshots\$proc\$date-$time_$title.png") ;LCtrl+PrintScreen - скриншот выделенной области в папку процесса активного окна

>^PrintScreen::St("s","#Files\$file\img.png") ;RCtrl+PrintScreen - скриншот выделенной области в папку открытого файла (для цитат электронных книг и пр.)

<^<+PrintScreen::St("s","#Sites\$site\$file.png") ;LCtrl+LShift+PrintScreen - скриншот выделенной области в папку открытого сайта с именем из заголовка страницы

>+PrintScreen::St("s","#Платежи\$site\$date\img.png") ;RShift+PrintScreen - скриншоты электронных платежей с сортировкой по сайтам и датам

>^>+PrintScreen::St("s","#Формы\[$site]-$file.png") ;RCtrl+RShift+PrintScreen - скриншоты регистрационных форм

; -----------------------------
<!PrintScreen::Run %s_path% ; LAlt+PrintScreen - открытие последнего скриншота

>!PrintScreen::Run %s_folder% ; RAlt+PrintScreen - открытие папки последнего скриншота

;------------------------------
St(type,f_path)
{
    global
    KeyWait Ctrl, T1
    KeyWait Shift, T1
    KeyWait Alt, T1
    KeyWait PrintScreen, T1
    tp:=type, fp:=f_path, z:=""
    If (type="s") && select
        goto End    
    FormatTime date, , yyyy.MM.dd
    FormatTime time, , HH.mm.ss
    WinGetActiveTitle t
    WinGet proc, ProcessName, % t
    SplitPath proc, , , , proc
    StringUpper proc, proc, T
    title:=ValidName(t)
    file:=ValidName(CleanTitle(t))
    cmd:=GetPath(t)
    SplitPath cmd, , , ,cmd
    If cmd
        cmt:=cmd
    else
    { 
        cmt:=file
        If f_path contains $cmd 
        {
                MsgBox, 262160, Ошибка, Имя открытого файла недоступно!, 1.5
                return
        }
    }
    If f_path contains $site
    {
        Clipboard:=""
        Send ^{vk4C}
        Sleep 500
        Send ^{vk43}
        ClipWait 1
        RegExMatch(Clipboard,"(?<=//).+?(?=/)",site)
        If ! site
        {
            MsgBox, 262160, Ошибка, Адрес недоступен!, 1.5
            return
        }
    }
    If (type="s") && (select="")
    {
        MouseGetPos mx, my
        Gui Destroy
        Gui Color, % color
        Gui +Lastfound +Resize AlwaysOnTop -Caption +ToolWindow -DPIScale
        WinSet Transparent, % transp
        Gui Show, x%mx% y%my% w%sel% h%sel%, selectwindow
        select:=1
        return
    }
    End:
    StringReplace tag, tag, $site, % stag
    StringReplace s_path, f_path, $date, % date
    StringReplace s_path, s_path, $time, % time
    StringReplace s_path, s_path, $proc, % proc
    StringReplace s_path, s_path, $site, % site
    StringReplace s_path, s_path, $title, % title
    StringReplace s_path, s_path, $file, % file
    StringReplace s_path, s_path, $cmd, % cmd
    StringReplace s_path, s_path, $cmt, % cmt
    StringReplace s_path, s_path, $z
    If ! Errorlevel
        z:=1        
    s_path:=RenIfExist(s_path,tab)
    SplitPath s_path, , s_folder, s_ext, s_file
    FileCreateDir % s_folder
    SysGet, M, Monitor
    If (type="f")        
        sx:=0, sy:=0, sw:=MRight, sh:=MBottom    
    If (type="w")
        WinGetPos, , , sw, sh,% t
    aRect:= sx "|" sy "|" sw "|" sh
    pToken := GdipStart()
    pBitmap := BitmapFromScreen(aRect, 0, 0x40000000 | 0x00CC0020)
    SaveBitmapToFile(pBitmap, s_path, nQuality)
    DllCall("gdiplus\GdipDisposeImage", UInt, pBitmap)
    GdipShutdown(pToken)
    FileGetSize sz,% s_path, K
    If z
    {
        ToolTip Сохранено
        Sleep 600
        ToolTip
        return
    }
    SplashImage % s_path, B1 ZW800 ZH-1 ZX20 ZY20 Fm14 Fs12 CW808080 CTFFFFFF C00,{Enter} - редактирование`n{Ctrl} - сохранить как`n{Space} - переименование файла"  ,% "Папка:  "  s_folder "`nИмя:  " s_file "." s_ext "`n" sw "x" sh "   " sz " KB", preview
    WinActivate preview
    Sleep % pr_time*1000
    SplashImage Off
    select:=""
    return
}

#IfWinActive selectwindow ahk_class AutoHotkeyGUI
RButton::
KeyWait RButton, T1
WinGetPos sx, sy, sw, sh, selectwindow
MouseGetPos mx, my
If (mx>sx && mx<sx+sw && my>sy && my<sy+sh)
{
    Gui Destroy
    St(tp,fp)
    return
}
GuiEscape:
Gui Destroy
select:=""
Sleep 200
return

#IfWinActive preview ahk_class AutoHotkey2      
Space::
SplashImage Off
Sleep 500
InputBox s_file, Переименование, Введите имя файла без расширения:, , 500, 130, , , , ,% s_file
s_file:=ValidName(s_file)
s_path_new:=RenIfExist(s_folder "\" s_file "." s_ext,1)
FileMove % s_path, % s_path_new
s_path:=s_path_new
return
Enter::
NumpadEnter::
SplashImage Off
Run % ed_path " " s_path
return
Ctrl::
SplashImage Off
FileSelectFile s_path_new, S, % s_file "." s_ext, Выберите место сохранения, Изображения (*.bmp; *.jpg; *.png)
FileMove % s_path, % s_path_new
s_path:=s_path_new
SplitPath s_path, , s_folder
return
Esc::SplashImage Off
#IfWinActive

;-----------------------------    
CleanTitle(t)
{
    RegExMatch(t,"(?<=\)\.+?(?=\.[a-zA-Z0-9]{2,4}(]| |$|\}))",title)
    If ! title
        RegExMatch(t,"(?<=\[).+\.[a-zA-Z0-9]{2,4}(?=])",title)
    If ! title
        RegExMatch(t,"^.+\.[a-zA-Z0-9]{2,4}(?=( - | \| ))",title)
    If ! title
        RegExMatch(t,"(?<= - ).+\.[a-zA-Z0-9]{2,4}$",title)
    SplitPath title, , , ,title
    If ! title
        RegExMatch(t,"^.+(?= - )",title)
    If ! title
        title:=t
    return title
}

GetPath(title)
{
    WinGet pr, ProcessName, % title 
    Process, Exist, % pr 
    pid := ErrorLevel
    for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
    If (process.ProcessId = pid)
    cmdline := process.CommandLine
    If cmdline contains Explorer.exe
        cmdline:=""
    fp:=RegExMatch(cmdline,"[A-Z]:\\.*\.[a-zA-Z0-9]{2,4}",f_path,6)
    return f_path
}

RenIfExist(f_path,tab)
{
    If ! FileExist(f_path)
        return f_path
    SplitPath f_path, , dir, ext, file
    Loop % dir "\" file "*." ext
    {
        n:=0
        RegExMatch(A_LoopFileName,"(?<=_)\d+?(?=\.[a-zA-Z0-9]{2,4}$)",n)
        If ! n
            n_max:=0
        If (n>n_max)
            n_max:=n
    }
    SetFormat float, % "0" tab
    return dir "\" file "_" n_max+1.0 "." ext
}

ValidName(n,r="")
{
    n:=RegExReplace(n,"(:|;|,|\*|\?|\\|/|<|>|"")"," ")
    n:=RegExReplace(n,"\s+"," ")
    StringReplace n, n, |, -, All
    If r
        StringReplace n, n, % " ", % r
    return Trim(n)
}

;--------- GDI+ ----------
BitmapFromScreen(Screen, Cursor, Raster="")
{
    if (Screen = 0)
    {
        Sysget, x, 76
        Sysget, y, 77
        Sysget, w, 78
        Sysget, h, 79
    }
    else
    {
        StringSplit, S, Screen, |
        x := S1, y := S2, w := S3, h := S4
    }
    chdc := DllCall("CreateCompatibleDC", UInt, 0)
    VarSetCapacity(bi, 40, 0)
    NumPut(w, bi, 4), NumPut(h, bi, 8), NumPut(40, bi, 0), NumPut(1, bi, 12, "ushort")
    NumPut(0, bi, 16), NumPut(32, bi, 14, "ushort")
    hbm := DllCall("CreateDIBSection"
        , UInt , chdc, UInt , &bi, UInt , 0, "uint*", 0, UInt , 0, UInt , 0)
    obm := DllCall("SelectObject", UInt, chdc, UInt, hbm)
    hhdc := DllCall("GetDC", UInt, 0)
    DllCall("gdi32\BitBlt", UInt, chdc, Int, 0, Int, 0, Int, w, Int, h
        , UInt, hhdc, Int, x, Int, y, UInt, Raster)
    DllCall("ReleaseDC", UInt, 0, UInt, hhdc)
    ;~ if Cursor
        ;~ CaptureCursor(chdc, x, y)
    DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", UInt, hbm, UInt, 0, "uint*", pBitmap)
    DllCall("SelectObject", UInt, chdc, UInt, obm)
    DllCall("DeleteObject", UInt, hbm)
    DllCall("DeleteDC", UInt, hhdc)
    DllCall("DeleteDC", UInt, chdc)
    return pBitmap
}

SaveBitmapToFile(pBitmap, sOutput, Quality=75)
{
    SplitPath, sOutput,,, Extension
    if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
        return -1
    Extension := "." Extension

    DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
    VarSetCapacity(ci, nSize)
    DllCall("gdiplus\GdipGetImageEncoders", UInt, nCount, UInt, nSize, UInt, &ci)
    if !(nCount && nSize)
        return -2

    Loop, %nCount%
    {
        Location := NumGet(ci, 76*(A_Index-1)+44)
        if !A_IsUnicode
        {
            nSize := DllCall("WideCharToMultiByte", UInt, 0, UInt, 0
                , UInt, Location, Int, -1, UInt, 0, Int,  0, UInt, 0, UInt, 0)
            VarSetCapacity(sString, nSize)
            DllCall("WideCharToMultiByte", UInt, 0, UInt, 0, UInt, Location
                , Int, -1, Str, sString, Int, nSize, UInt, 0, UInt, 0)
            if !InStr(sString, "*" Extension)
                continue
        }
        else
        {
            nSize := DllCall("WideCharToMultiByte", UInt, 0, UInt, 0
                , UInt, Location, Int, -1, UInt, 0, Int,  0, UInt, 0, UInt, 0)
            sString := ""
            Loop, %nSize%
                sString .= Chr(NumGet(Location+0, 2*(A_Index-1), "char"))
            if !InStr(sString, "*" Extension)
                continue
        }
        pCodec := &ci+76*(A_Index-1)
        break
    }
    if !pCodec
        return -3

    if (Quality != 75)
    {
        Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
        if Extension in .JPG,.JPEG,.JPE,.JFIF
        {
            DllCall("gdiplus\GdipGetEncoderParameterListSize"
                , UInt, pBitmap, UInt, pCodec, "uint*", nSize)
            VarSetCapacity(EncoderParameters, nSize, 0)
            DllCall("gdiplus\GdipGetEncoderParameterList", UInt, pBitmap
                , UInt, pCodec, UInt, nSize, UInt, &EncoderParameters)
            Loop, % NumGet(EncoderParameters)      ;%
            {
                if (NumGet(EncoderParameters, (28*(A_Index-1))+20) = 1)
                    && (NumGet(EncoderParameters, (28*(A_Index-1))+24) = 6)
                {
                   p := (28*(A_Index-1))+&EncoderParameters
                   NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20)))
                   break
                }
            }
       }
    }

    if !A_IsUnicode
    {
        nSize := DllCall("MultiByteToWideChar"
            , UInt, 0, UInt, 0, UInt, &sOutput, Int, -1, UInt, 0, Int, 0)
        VarSetCapacity(wOutput, nSize*2)
        DllCall("MultiByteToWideChar"
            , UInt, 0, UInt, 0, UInt, &sOutput, Int, -1, UInt, &wOutput, Int, nSize)
        VarSetCapacity(wOutput, -1)
        if !VarSetCapacity(wOutput)
            return -4
        E := DllCall("gdiplus\GdipSaveImageToFile"
            , UInt, pBitmap, UInt, &wOutput, UInt, pCodec, UInt, p ? p : 0)
    }
    else
        E := DllCall("gdiplus\GdipSaveImageToFile"
            , UInt, pBitmap, UInt, &sOutput, UInt, pCodec, UInt, p ? p : 0)
    return E ? -5 : 0
}

GdipStart()
{
    if !DllCall("GetModuleHandle", Str, "gdiplus")
        DllCall("LoadLibrary", Str, "gdiplus")
    VarSetCapacity(si, 16, 0), si := Chr(1)
    DllCall("gdiplus\GdiplusStartup", "uint*", pToken, UInt, &si, UInt, 0)
    return pToken
}

GdipShutdown(pToken)
{
    DllCall("gdiplus\GdiplusShutdown", UInt, pToken)
    if hModule := DllCall("GetModuleHandle", Str, "gdiplus")
        DllCall("FreeLibrary", UInt, hModule)
    return 0
}



28

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Пользуетесь устаревшей библиотекой Gdip.ahk, написанной для AHK-basic.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

29

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Функции взяты из вашего ScreenCatcher,a. Следует взять из Gdip_all?
Они позволяют такую замену?

30

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Да, конечно. Только в скрипте названия функций изменены (чаще всего знак подчёркивания убран), чтобы не пересекались с теми, что есть в файле Gdip.ahk. Мой скрипт написан в 2010, и хоть там и сказано, что работает под AHK_L, на самом деле сработает только под 32-bit.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

31

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Совсем доработанная версия на основе Gdip_All.ahk с поддержкой 64-битных систем

#NoEnv 
SendMode Input 
SetWorkingDir %A_ScriptDir%
#SingleInstance, force
Menu Tray, Icon, shell32.dll, 35
SetTitleMatchMode 2
SetTitleMatchMode Slow
CoordMode Mouse, Screen

; --------- Настройки ---------
color:="FFDC00" ; цвет окна выделения
transp:=150 ; его прозрачность (0-255)
sel:=80 ; его начальный размер
nQuality:=90 ; качество JPEG
pr_time:=3 ; время показа превью, сек
tab:=3 ; число цифр c ведущими нулями при автопереименовании
ed_path:="D:\Soft\Chasys Draw IES\Artist.exe"  ; путь к редактору
;------------------------------

<+PrintScreen::St("f","#Screenshots\$proc\$date-$time_$title.png") ; LShift+PrintScreen - скриншот всего экрана в папку процесса активного окна

#PrintScreen::St("w","#Screenshots\$proc\$date-$time_$title.png") ; Win+PrintScreen - скриншот активного окна в папку процесса активного окна

<^PrintScreen::St("s","#Screenshots\$proc\$date-$time_$title.png") ;LCtrl+PrintScreen - скриншот выделенной области в папку процесса активного окна

>^PrintScreen::St("s","#Files\$file\img.png") ;RCtrl+PrintScreen - скриншот выделенной области в папку открытого файла (для цитат электронных книг и пр.)

<^<+PrintScreen::St("s","#Sites\$site\$file.png") ;LCtrl+LShift+PrintScreen - скриншот выделенной области в папку открытого сайта с именем из заголовка страницы

>+PrintScreen::St("s","#Платежи\$site\$date\img.png") ;RShift+PrintScreen - скриншоты электронных платежей с сортировкой по сайтам и датам

>^>+PrintScreen::St("s","#Формы\[$site]-$file.png") ;RCtrl+RShift+PrintScreen - скриншоты регистрационных форм

; -----------------------------
<!PrintScreen::Run %s_path% ; LAlt+PrintScreen - открытие последнего скриншота

>!PrintScreen::Run %s_folder% ; RAlt+PrintScreen - открытие папки последнего скриншота

;------------------------------
St(type,f_path)
{
    global
    KeyWait Ctrl, T1
    KeyWait Shift, T1
    KeyWait Alt, T1
    KeyWait PrintScreen, T1
    tp:=type, fp:=f_path, z:=""
    If (type="s") && select
        goto End    
    FormatTime date, , yyyy.MM.dd
    FormatTime time, , HH.mm.ss
    WinGetActiveTitle t
    WinGet proc, ProcessName, % t
    SplitPath proc, , , , proc
    StringUpper proc, proc, T
    title:=ValidName(t)
    file:=ValidName(CleanTitle(t))
    cmd:=GetPath(t)
    SplitPath cmd, , , ,cmd
    If cmd
        cmt:=cmd
    else
    { 
        cmt:=file
        If f_path contains $cmd 
        {
                MsgBox, 262160, Ошибка, Имя открытого файла недоступно!, 1.5
                return
        }
    }
    If f_path contains $site
    {
        Clipboard:=""
        Send ^{vk4C}
        Sleep 500
        Send ^{vk43}
        ClipWait 1
        RegExMatch(Clipboard,"(?<=//).+?(?=/)",site)
        If ! site
        {
            MsgBox, 262160, Ошибка, Адрес недоступен!, 1.5
            return
        }
    }
    If (type="s") && (select="")
    {
        MouseGetPos mx, my
        Gui Destroy
        Gui Color, % color
        Gui +Lastfound +Resize AlwaysOnTop -Caption +ToolWindow -DPIScale
        WinSet Transparent, % transp
        Gui Show, x%mx% y%my% w%sel% h%sel%, selectwindow
        select:=1
        return
    }
    End:
    StringReplace tag, tag, $site, % stag
    StringReplace s_path, f_path, $date, % date
    StringReplace s_path, s_path, $time, % time
    StringReplace s_path, s_path, $proc, % proc
    StringReplace s_path, s_path, $site, % site
    StringReplace s_path, s_path, $title, % title
    StringReplace s_path, s_path, $file, % file
    StringReplace s_path, s_path, $cmd, % cmd
    StringReplace s_path, s_path, $cmt, % cmt
    StringReplace s_path, s_path, $z
    If ! Errorlevel
        z:=1        
    s_path:=RenIfExist(s_path,tab)
    SplitPath s_path, , s_folder, s_ext, s_file
    FileCreateDir % s_folder
    SysGet, M, Monitor
    If (type="f")        
        sx:=0, sy:=0, sw:=MRight, sh:=MBottom    
    If (type="w")
        WinGetPos, , , sw, sh,% t
    aRect:= sx "|" sy "|" sw "|" sh
    pToken := Startup()
    pBitmap := BitmapFromScreen(aRect,0x40000000 | 0x00CC0020)
    SaveBitmapToFile(pBitmap, s_path, nQuality)
    DllCall("gdiplus\GdipDisposeImage", UInt, pBitmap)
    Shutdown(pToken)
    FileGetSize sz,% s_path, K
    If z
    {
        ToolTip Сохранено
        Sleep 600
        ToolTip
        return
    }
    SplashImage % s_path, B1 ZW800 ZH-1 ZX20 ZY20 Fm14 Fs12 CW808080 CTFFFFFF C00,{Enter} - редактирование`n{Ctrl} - сохранить как`n{Space} - переименование файла"  ,% "Папка:  "  s_folder "`nИмя:  " s_file "." s_ext "`n" sw "x" sh "   " sz " KB", preview
    WinActivate preview
    Sleep % pr_time*1000
    SplashImage Off
    select:=""
    return
}

#IfWinActive selectwindow ahk_class AutoHotkeyGUI
RButton::
KeyWait RButton, T1
WinGetPos sx, sy, sw, sh, selectwindow
MouseGetPos mx, my
If (mx>sx && mx<sx+sw && my>sy && my<sy+sh)
{
    Gui Destroy
    St(tp,fp)
    return
}
GuiEscape:
Gui Destroy
select:=""
Sleep 200
return

#IfWinActive preview ahk_class AutoHotkey2      
Space::
SplashImage Off
Sleep 500
InputBox s_file, Переименование, Введите имя файла без расширения:, , 500, 130, , , , ,% s_file
s_file:=ValidName(s_file)
s_path_new:=RenIfExist(s_folder "\" s_file "." s_ext,1)
FileMove % s_path, % s_path_new
s_path:=s_path_new
return
Enter::
NumpadEnter::
SplashImage Off
Run % ed_path " " s_path
return
Ctrl::
SplashImage Off
FileSelectFile s_path_new, S, % s_file "." s_ext, Выберите место сохранения, Изображения (*.bmp; *.jpg; *.png)
FileMove % s_path, % s_path_new
s_path:=s_path_new
SplitPath s_path, , s_folder
return
Esc::SplashImage Off
#IfWinActive

;-----------------------------    
CleanTitle(t)
{
    RegExMatch(t,"(?<=\)\.+?(?=\.[a-zA-Z0-9]{2,4}(]| |$|\}))",title)
    If ! title
        RegExMatch(t,"(?<=\[).+\.[a-zA-Z0-9]{2,4}(?=])",title)
    If ! title
        RegExMatch(t,"^.+\.[a-zA-Z0-9]{2,4}(?=( - | \| ))",title)
    If ! title
        RegExMatch(t,"(?<= - ).+\.[a-zA-Z0-9]{2,4}$",title)
    SplitPath title, , , ,title
    If ! title
        RegExMatch(t,"^.+(?= - )",title)
    If ! title
        title:=t
    return title
}

GetPath(title)
{
    WinGet pr, ProcessName, % title 
    Process, Exist, % pr 
    pid := ErrorLevel
    for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
    If (process.ProcessId = pid)
    cmdline := process.CommandLine
    If cmdline contains Explorer.exe
        cmdline:=""
    fp:=RegExMatch(cmdline,"[A-Z]:\\.*\.[a-zA-Z0-9]{2,4}",f_path,6)
    return f_path
}

RenIfExist(f_path,tab)
{
    If ! FileExist(f_path)
        return f_path
    SplitPath f_path, , dir, ext, file
    Loop % dir "\" file "*." ext
    {
        n:=0
        RegExMatch(A_LoopFileName,"(?<=_)\d+?(?=\.[a-zA-Z0-9]{2,4}$)",n)
        If ! n
            n_max:=0
        If (n>n_max)
            n_max:=n
    }
    SetFormat float, % "0" tab
    return dir "\" file "_" n_max+1.0 "." ext
}

ValidName(n,r="")
{
    n:=RegExReplace(n,"(:|;|,|\*|\?|\\|/|<|>|"")"," ")
    n:=RegExReplace(n,"\s+"," ")
    StringReplace n, n, |, -, All
    If r
        StringReplace n, n, % " ", % r
    return Trim(n)
}

;--------- GDI+ ----------
BitmapFromScreen(Screen=0, Raster="")
{
    if (Screen = 0)
    {
        Sysget, x, 76
        Sysget, y, 77    
        Sysget, w, 78
        Sysget, h, 79
    }
    else if (SubStr(Screen, 1, 5) = "hwnd:")
    {
        Screen := SubStr(Screen, 6)
        if !WinExist( "ahk_id " Screen)
            return -2
        WinGetPos,,, w, h, ahk_id %Screen%
        x := y := 0
        hhdc := GetDCEx(Screen, 3)
    }
    else if (Screen&1 != "")
    {
        Sysget, M, Monitor, %Screen%
        x := MLeft, y := MTop, w := MRight-MLeft, h := MBottom-MTop
    }
    else
    {
        StringSplit, S, Screen, |
        x := S1, y := S2, w := S3, h := S4
    }

    if (x = "") || (y = "") || (w = "") || (h = "")
        return -1

    chdc := CreateCompatibleDC(), hbm := CreateDIBSection(w, h, chdc), obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
    BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
    ReleaseDC(hhdc)
    
    pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
    SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
    return pBitmap
}

Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
    return pBitmap
}

SaveBitmapToFile(pBitmap, sOutput, Quality=75)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    SplitPath, sOutput,,, Extension
    if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
        return -1
    Extension := "." Extension

    DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
    VarSetCapacity(ci, nSize)
    DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
    if !(nCount && nSize)
        return -2
    
    If (A_IsUnicode){
        StrGet_Name := "StrGet"
        Loop, %nCount%
        {
            sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
            if !InStr(sString, "*" Extension)
                continue
            
            pCodec := &ci+idx
            break
        }
    } else {
        Loop, %nCount%
        {
            Location := NumGet(ci, 76*(A_Index-1)+44)
            nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
            VarSetCapacity(sString, nSize)
            DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
            if !InStr(sString, "*" Extension)
                continue
            
            pCodec := &ci+76*(A_Index-1)
            break
        }
    }
    
    if !pCodec
        return -3

    if (Quality != 75)
    {
        Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
        if Extension in .JPG,.JPEG,.JPE,.JFIF
        {
            DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
            VarSetCapacity(EncoderParameters, nSize, 0)
            DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
            Loop, % NumGet(EncoderParameters, "UInt")      ;%
            {
                elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
                if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
                {
                    p := elem+&EncoderParameters-pad-4
                    NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
                    break
                }
            }      
        }
    }

    if (!A_IsUnicode)
    {
        nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
        VarSetCapacity(wOutput, nSize*2)
        DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
        VarSetCapacity(wOutput, -1)
        if !VarSetCapacity(wOutput)
            return -4
        E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
    }
    else
        E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
    return E ? -5 : 0
}

BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("gdi32\BitBlt"
                    , Ptr, dDC
                    , "int", dx
                    , "int", dy
                    , "int", dw
                    , "int", dh
                    , Ptr, sDC
                    , "int", sx
                    , "int", sy
                    , "uint", Raster ? Raster : 0x00CC0020)
}

CreateCompatibleDC(hdc=0)
{
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    hdc2 := hdc ? hdc : GetDC()
    VarSetCapacity(bi, 40, 0)
    
    NumPut(w, bi, 4, "uint")
    , NumPut(h, bi, 8, "uint")
    , NumPut(40, bi, 0, "uint")
    , NumPut(1, bi, 12, "ushort")
    , NumPut(0, bi, 16, "uInt")
    , NumPut(bpp, bi, 14, "ushort")
    
    hbm := DllCall("CreateDIBSection"
                    , Ptr, hdc2
                    , Ptr, &bi
                    , "uint", 0
                    , A_PtrSize ? "UPtr*" : "uint*", ppvBits
                    , Ptr, 0
                    , "uint", 0, Ptr)

    if !hdc
        ReleaseDC(hdc2)
    return hbm
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}

DeleteObject(hObject)
{
   return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}

GetDC(hwnd=0)
{
    return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}

GetDCEx(hwnd, flags=0, hrgnClip=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
}

ReleaseDC(hdc, hwnd=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

SelectObject(hdc, hgdiobj)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}

Startup()
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
        DllCall("LoadLibrary", "str", "gdiplus")
    VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
    DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
    return pToken
}

Shutdown(pToken)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
    if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
        DllCall("FreeLibrary", Ptr, hModule)
    return 0
}

32

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Попробовал сделать встроенное распознавание текста на основе Tesseract-OCR, так, чтобы вместо превью картинки выводилось окно редактирования распознанного текста с последующим сохранением его по заданным правилам.
Результат оказался на удивление достойным: при работе с pdf и djvu среднего качества с простым текстом ошибки распознавания почти отсутствуют, и даже на старых серых, переснятых камерой книгах с волнистыми строками будет что приводить в порядок. Прилично работает с двуязычными текстами, читает компьютерные сообщения и интерфейсы, если шрифт ClearType и не слишком мелок. Можно даже сканировать вшитые субтитры в плеере и засовывать их в переводчик, если есть такая нужда.

Файл tesseract-ocr-3.02-win32-portable.zip и нужные языковые пакеты берем здесь (английский включен в дистрибутив): https://code.google.com/p/tesseract-ocr/downloads/list
Папка Tesseract-OCR должна находиться в каталоге скрипта, языковые пакеты в папке tessdata без подкаталогов.
Собранный набор скрипт + Tesseract-OCR с русским и английским языковыми пакетами можно взять здесь: https://yadi.sk/d/ZEe594j4dgU5X

Функция сканирования теперь имеет вид:
St(type,f_path,lng="",save_img="")
Здесь
lng - код языка, фигурирующий в названиях архивов языковых пакетов и их файлах. Возможны сочетания вида "rus+eng", но едва ли стоит использовать более двух языков за раз.
save_img - переменная, отвечающая за сохранение распознанных файлов.
Результирующий текстовый файл имеет тот же полный путь, что и изображение с заменой расширения на txt. Разница в том, что изображения автопереименовываются при совпадении имен, а распознанный текст дописывается в один файл.

Так что
St("s","_Books_OCR\$file.png","rus+eng")
будет лепить книжные цитаты в текстовый файл, одноименный с первоисточником, не оставляя обработанных изображений.

При этом если нажатие кнопки Save или Ctrl+S в окне редактирования добавляет текст с заголовком из даты, времени и заголовка активного окна, то нажатие Add продолжает прежнюю запись. Это позволяет соединять цитаты на разрывах страниц, где распознавание регулярно глючит. Cancel отменяет сохранение текста и удаляет исходное изображение.

Исправлен баг со снятием скриншота активного окна

#NoEnv 
SendMode Input 
SetWorkingDir %A_ScriptDir%
#SingleInstance, force
Menu Tray, Icon, shell32.dll, 35
SetTitleMatchMode 2
SetTitleMatchMode Slow
CoordMode Mouse, Screen

; --------- Настройки ---------
color:="FFDC00" ; цвет окна выделения
transp:=150 ; его прозрачность (0-255)
sel:=80 ; его начальный размер
nQuality:=90 ; качество JPEG
pr_time:=3 ; время показа превью изображений, сек
tab:=3 ; число цифр c ведущими нулями при автопереименовании
ed_path:="D:\Soft\Chasys Draw IES\Artist.exe"  ; путь к графическому редактору 
ft:=22 ; размер шрифта окна редактирования распознанного текста
;------------------------------

<+PrintScreen::St("f","#Screenshots\$proc\$date-$time_$title.png") ; LShift+PrintScreen - скриншот всего экрана в папку процесса активного окна

#PrintScreen::St("w","#Screenshots\$proc\$date-$time_$title.png") ; Win+PrintScreen - скриншот активного окна в папку процесса активного окна

<^PrintScreen::St("s","#Screenshots\$proc\$date-$time_$title.png") ;LCtrl+PrintScreen - скриншот выделенной области в папку процесса активного окна

$^!PrintScreen::St("s","#Screenshots\$proc\$date-$time_$title.png","rus+eng",1) ;Ctrl+Alt+PrintScreen - распознанный текст выделенной области в папку процесса активного окна с сохранением изображения

>^PrintScreen::St("s","_Books_OCR\$file.png","rus+eng") ; RCtrl+PrintScreen - распознанные цитаты электронных книг в файл, одноменный с названием источника 

<^<+PrintScreen::St("s","#Sites\$site\$file.png") ;LCtrl+LShift+PrintScreen - скриншот выделенной области в папку открытого сайта с именем из заголовка страницы

>+PrintScreen::St("s","#Платежи\$site\$date\img.png") ;RShift+PrintScreen - скриншоты электронных платежей с сортировкой по сайтам и датам

>^>+PrintScreen::St("s","#Формы\[$site]-$file.png") ;RCtrl+RShift+PrintScreen - скриншоты регистрационных форм


; -----------------------------
$<!PrintScreen:: ; LAlt+PrintScreen - открытие последнего скриншота или текстового файла
Run %s_path%
SplitPath s_path, s_file, , s_ext
If (s_ext="txt")
{
    WinWaitActive % s_file, , 3
    If ! Errorlevel
    {
        Sleep 500
        Send ^{End}
    }
}
return

$>!PrintScreen::Run %s_folder% ; RAlt+PrintScreen - открытие папки последнего скриншота или текстового файла

;------------------------------
St(type,f_path,lng="",save_img="")
{
    global
    KeyWait Ctrl, T1
    KeyWait Shift, T1
    KeyWait Alt, T1
    KeyWait PrintScreen, T1
    type2:=type, f_path2:=f_path, lng2:=lng, save_img2:=save_img, z:=""
    If (type="s") && select
        goto End    
    FormatTime date, , yyyy.MM.dd
    FormatTime time, , HH.mm.ss
    WinGetActiveTitle t
    WinGet proc, ProcessName, % t
    SplitPath proc, , , , proc
    StringUpper proc, proc, T
    title:=ValidName(t)
    file:=ValidName(CleanTitle(t))
    cmd:=GetPath(t)
    SplitPath cmd, , , ,cmd
    If cmd
        cmt:=cmd
    else
    { 
        cmt:=file
        If f_path contains $cmd 
        {
                MsgBox, 262160, Ошибка, Имя открытого файла недоступно!, 1.5
                return
        }
    }
    If f_path contains $site
    {
        Clipboard:=""
        Send ^{vk4C}
        Sleep 500
        Send ^{vk43}
        ClipWait 1
        RegExMatch(Clipboard,"(?<=//).+?(?=/)",site)
        If ! site
        {
            MsgBox, 262160, Ошибка, Адрес недоступен!, 1.5
            return
        }
    }
    If (type="s") && (select="")
    {
        MouseGetPos mx, my
        Gui Destroy
        Gui Color, % color
        Gui +Lastfound +Resize AlwaysOnTop -Caption +ToolWindow -DPIScale
        WinSet Transparent, % transp
        Gui Show, x%mx% y%my% w%sel% h%sel%, selectwindow
        select:=1
        return
    }
    End:
    StringReplace tag, tag, $site, % stag
    StringReplace s_path, f_path, $date, % date
    StringReplace s_path, s_path, $time, % time
    StringReplace s_path, s_path, $proc, % proc
    StringReplace s_path, s_path, $site, % site
    StringReplace s_path, s_path, $title, % title
    StringReplace s_path, s_path, $file, % file
    StringReplace s_path, s_path, $cmd, % cmd
    StringReplace s_path, s_path, $cmt, % cmt
    StringReplace s_path, s_path, $z
    If ! Errorlevel
        z:=1
    start_path:=s_path
    s_path:=RenIfExist(s_path,tab)
    SplitPath s_path, , s_folder, s_ext, s_file
    FileCreateDir % s_folder
    SysGet, M, Monitor
    If (type="f")        
        sx:=0, sy:=0, sw:=MRight, sh:=MBottom    
    If (type="w")
        WinGetPos sx, sy, sw, sh, A
    aRect:= sx "|" sy "|" sw "|" sh
    pToken := Startup()
    pBitmap := BitmapFromScreen(aRect,0x40000000 | 0x00CC0020)
    SaveBitmapToFile(pBitmap, s_path, nQuality)
    DllCall("gdiplus\GdipDisposeImage", UInt, pBitmap)
    Shutdown(pToken)
    FileGetSize sz,% s_path, K
    If lng
    {
        spt="%s_path%"
        RunWait % "Tesseract-OCR\tesseract.exe " spt " Tesseract-OCR\out -l " lng
        Sleep 200
        FileEncoding UTF-8-RAW
        FileRead text, Tesseract-OCR\out.txt        
        If ! save_img2
            FileDelete % s_path
        text:=RegExReplace(text,"^\s+","")
        text:=RegExReplace(text,"\s+$","")
        text:=RegExReplace(text,"^\s+$",""), r:="`r`n`r`n"
        text:=RegExReplace(text,"\R{2,}",r)
        SplitPath start_path, ,t_folder, , t_file
        t_path:=t_folder "\" t_file ".txt"
        s_path_del:=s_path, s_path:=t_path
        ed_w:=MRight*0.7, ed_h:=MBottom*0.7, b_w:=ed_w/4    
        Gui 2:Destroy
        Gui 2:-DPIScale
        Gui 2:Color, D7D7D7
        Gui 2:Margin , 24, 8
        Gui 2:font, s%ft%
        Gui 2:Add, Edit, vtext w%ed_w% h%ed_h%,% text
        Gui 2:font, s13
        Gui 2:Add, Button, w%b_w% y+8 h45, Canc&el
        Gui 2:Add, Button, wp x+0 hp, &Copy
        Gui 2:Add, Button, x+0 hp wp, &Add
        Gui 2:Add, Button, wp x+0 hp, &Save    
        Gui 2:Show, Center, % t_path
        Send ^{Home}
        return
    }
    If z
    {
        ToolTip Сохранено
        Sleep 600
        ToolTip
        return
    }
    SplashImage % s_path, B1 ZW800 ZH-1 ZX20 ZY20 Fm14 Fs12 CW808080 CTFFFFFF C00,{Enter} - редактирование`n{Ctrl} - сохранить как`n{Space} - переименование файла"  ,% "Папка:  "  s_folder "`nИмя:  " s_file "." s_ext "`n" sw "x" sh "   " sz " KB", preview
    WinActivate preview
    Sleep % pr_time*1000
    SplashImage Off
    select:=""
    return
}

#If WinActive("ahk_pid " DllCall("GetCurrentProcessId"))
^vk53::goto 2ButtonSave ; Ctrl+S
#If WinActive
2ButtonAdd:
caption:=""
goto Add
2ButtonSave:
caption:="`n`n### " A_DD "." A_MM "." A_YYYY "  " A_Hour ":" A_Min " ###`n### " title " ###`n`n"
Add:
Gui 2:Submit
If text
{    
    FileAppend % caption . text "`n",% t_path, utf-8
    If Errorlevel
        MsgBox, 262160, , Ошибка сохранения!, 1
    else
        MsgBox 262208, ,% "Сохранено!", 1
    select:="", text:=""    
}
return

2ButtonCopy:
Gui 2:Submit, NoHide
Clipboard:=text
ToolTip Тект в буфере!
Sleep 600
ToolTip
return

2ButtonCancel:
2GuiEscape:
2GuiClose:
Gui 2:Destroy
FileDelete % s_path_del
select:="", text:=""
return
    

#IfWinActive selectwindow ahk_class AutoHotkeyGUI
RButton::
KeyWait RButton, T1
WinGetPos sx, sy, sw, sh, selectwindow
MouseGetPos mx, my
If (mx>sx && mx<sx+sw && my>sy && my<sy+sh)
{
    Gui Destroy
    St(type2,f_path2,lng2,save_img2)
    return
}
GuiEscape:
Gui Destroy
select:=""
Sleep 200
return

#IfWinActive preview ahk_class AutoHotkey2      
Space::
SplashImage Off
Sleep 500
InputBox s_file, Переименование, Введите имя файла без расширения:, , 500, 130, , , , ,% s_file
s_file:=ValidName(s_file)
s_path_new:=RenIfExist(s_folder "\" s_file "." s_ext,1)
FileMove % s_path, % s_path_new
s_path:=s_path_new
return

Enter::
NumpadEnter::
SplashImage Off
Run % ed_path " " s_path
return

Ctrl::
SplashImage Off
FileSelectFile s_path_new, S, % s_file "." s_ext, Выберите место сохранения, Изображения (*.bmp; *.jpg; *.png)
FileMove % s_path, % s_path_new
s_path:=s_path_new
SplitPath s_path, , s_folder
return

Esc::SplashImage Off
#IfWinActive

;-----------------------------    
CleanTitle(t)
{
    RegExMatch(t,"(?<=\)\.+?(?=\.[a-zA-Z0-9]{2,4}(]| |$|\}))",title)
    If ! title
        RegExMatch(t,"(?<=\[).+\.[a-zA-Z0-9]{2,4}(?=])",title)
    If ! title
        RegExMatch(t,"^.+\.[a-zA-Z0-9]{2,4}(?=( - | \| ))",title)
    If ! title
        RegExMatch(t,"(?<= - ).+\.[a-zA-Z0-9]{2,4}$",title)
    SplitPath title, , , ,title
    If ! title
        RegExMatch(t,"^.+(?= - )",title)
    If ! title
        title:=t
    return title
}

GetPath(title)
{
    WinGet pr, ProcessName, % title 
    Process, Exist, % pr 
    pid := ErrorLevel
    for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
    If (process.ProcessId = pid)
    cmdline := process.CommandLine
    If cmdline contains Explorer.exe
        cmdline:=""
    fp:=RegExMatch(cmdline,"[A-Z]:\\.*\.[a-zA-Z0-9]{2,4}",f_path,6)
    return f_path
}

RenIfExist(f_path,tab)
{
    If ! FileExist(f_path)
        return f_path
    SplitPath f_path, , dir, ext, file
    Loop % dir "\" file "*." ext
    {
        n:=0
        RegExMatch(A_LoopFileName,"(?<=_)\d+?(?=\.[a-zA-Z0-9]{2,4}$)",n)
        If ! n
            n_max:=0
        If (n>n_max)
            n_max:=n
    }
    SetFormat float, % "0" tab
    return dir "\" file "_" n_max+1.0 "." ext
}

ValidName(n,r="")
{
    n:=RegExReplace(n,"(:|;|,|\*|\?|\\|/|<|>|"")"," ")
    n:=RegExReplace(n,"\s+"," ")
    StringReplace n, n, |, -, All
    If r
        StringReplace n, n, % " ", % r, All
    return Trim(n)
}

;--------- GDI+ ----------
BitmapFromScreen(Screen=0, Raster="")
{
    if (Screen = 0)
    {
        Sysget, x, 76
        Sysget, y, 77    
        Sysget, w, 78
        Sysget, h, 79
    }
    else if (SubStr(Screen, 1, 5) = "hwnd:")
    {
        Screen := SubStr(Screen, 6)
        if !WinExist( "ahk_id " Screen)
            return -2
        WinGetPos,,, w, h, ahk_id %Screen%
        x := y := 0
        hhdc := GetDCEx(Screen, 3)
    }
    else if (Screen&1 != "")
    {
        Sysget, M, Monitor, %Screen%
        x := MLeft, y := MTop, w := MRight-MLeft, h := MBottom-MTop
    }
    else
    {
        StringSplit, S, Screen, |
        x := S1, y := S2, w := S3, h := S4
    }

    if (x = "") || (y = "") || (w = "") || (h = "")
        return -1

    chdc := CreateCompatibleDC(), hbm := CreateDIBSection(w, h, chdc), obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
    BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
    ReleaseDC(hhdc)
    
    pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
    SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
    return pBitmap
}

Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
    return pBitmap
}

SaveBitmapToFile(pBitmap, sOutput, Quality=75)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    SplitPath, sOutput,,, Extension
    if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
        return -1
    Extension := "." Extension

    DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
    VarSetCapacity(ci, nSize)
    DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
    if !(nCount && nSize)
        return -2
    
    If (A_IsUnicode){
        StrGet_Name := "StrGet"
        Loop, %nCount%
        {
            sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
            if !InStr(sString, "*" Extension)
                continue
            
            pCodec := &ci+idx
            break
        }
    } else {
        Loop, %nCount%
        {
            Location := NumGet(ci, 76*(A_Index-1)+44)
            nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
            VarSetCapacity(sString, nSize)
            DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
            if !InStr(sString, "*" Extension)
                continue
            
            pCodec := &ci+76*(A_Index-1)
            break
        }
    }
    
    if !pCodec
        return -3

    if (Quality != 75)
    {
        Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
        if Extension in .JPG,.JPEG,.JPE,.JFIF
        {
            DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
            VarSetCapacity(EncoderParameters, nSize, 0)
            DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
            Loop, % NumGet(EncoderParameters, "UInt")      ;%
            {
                elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
                if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
                {
                    p := elem+&EncoderParameters-pad-4
                    NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
                    break
                }
            }      
        }
    }

    if (!A_IsUnicode)
    {
        nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
        VarSetCapacity(wOutput, nSize*2)
        DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
        VarSetCapacity(wOutput, -1)
        if !VarSetCapacity(wOutput)
            return -4
        E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
    }
    else
        E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
    return E ? -5 : 0
}

BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("gdi32\BitBlt"
                    , Ptr, dDC
                    , "int", dx
                    , "int", dy
                    , "int", dw
                    , "int", dh
                    , Ptr, sDC
                    , "int", sx
                    , "int", sy
                    , "uint", Raster ? Raster : 0x00CC0020)
}

CreateCompatibleDC(hdc=0)
{
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    hdc2 := hdc ? hdc : GetDC()
    VarSetCapacity(bi, 40, 0)
    
    NumPut(w, bi, 4, "uint")
    , NumPut(h, bi, 8, "uint")
    , NumPut(40, bi, 0, "uint")
    , NumPut(1, bi, 12, "ushort")
    , NumPut(0, bi, 16, "uInt")
    , NumPut(bpp, bi, 14, "ushort")
    
    hbm := DllCall("CreateDIBSection"
                    , Ptr, hdc2
                    , Ptr, &bi
                    , "uint", 0
                    , A_PtrSize ? "UPtr*" : "uint*", ppvBits
                    , Ptr, 0
                    , "uint", 0, Ptr)

    if !hdc
        ReleaseDC(hdc2)
    return hbm
}

DeleteDC(hdc)
{
   return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}

DeleteObject(hObject)
{
   return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}

GetDC(hwnd=0)
{
    return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}

GetDCEx(hwnd, flags=0, hrgnClip=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
}

ReleaseDC(hdc, hwnd=0)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}

SelectObject(hdc, hgdiobj)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}

Startup()
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
        DllCall("LoadLibrary", "str", "gdiplus")
    VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
    DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
    return pToken
}

Shutdown(pToken)
{
    Ptr := A_PtrSize ? "UPtr" : "UInt"
    
    DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
    if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
        DllCall("FreeLibrary", Ptr, hModule)
    return 0
}

33

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Как настроить последний скрипт на распознавание изображения по определенному пути, в текстовый файл с тем же именем?

34

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Нужно повесить на любую клавишу функцию вида
St("s","Папка\image.png","rus+eng",1)
где "rus+eng" - сочетание языков распознавания или один язык. Усложнить можно с помощью переменных (процесс, заголовок окна и пр.) из описания.
Еще нужна папка Tesseract-OCR из архивов на этой странице.

35 (изменено: DD, 2019-08-19 20:41:47)

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Имелось в виду: распознать изображение, которое не открыто для скрипта на экране, а лежит где-то на диске. С другими хотекеями срабатывает, но в таком формате не пошло:

2::St("s","D:\Screenshot_OCR\_Books_OCR\1_file.jpg","rus+eng",1)
2::St("s","_Books_OCR\1_file.jpg","rus+eng",1)

Выводится желтая область, и после клика правой кнопкой создается пустой файл в папке "Tesseract-OCR". Дано ли настроить скрипт на автоматизацию распознавания множества файлов изображений, в текстовые файлы с их названиями?

36

Re: AHK: Скрипт для снятия скриншотов с автосортировкой

Все что нужно, это цикл, обходящий папку и команда из скрипта (пути исправить)

RunWait % "Tesseract-OCR\tesseract.exe " spt " Tesseract-OCR\out -l " lng

здесь spt - переменная пути к изображению, а lng - языковой код. Данный скрипт для этого не предназначен.

+ DD