1

Тема: AHK: Сохранить маленький произвольный кусок экрана

http://forum.script-coding.com/viewtopic.php?id=479

Вот тут вроде написано как сохранить маленький произвольный кусок экрана в файлик. Но толком примера нет... а все мои попытки сводятся к нолю.

Задача
Какую-нибудь иконку выделять мышкой. С этой иконки делается принт-скрин. И в итоге получается файлик с картинкой, которую можно дальше использовать в скрипте для управления этой программкой.
Вобщем всё стандартно.

Вот только в той теме решение как бы есть... но оно для Гуру(

Если не сложно, то выложите хотя бы простенький код который позволяет сделать картинку с выбранной части экрана. А то ГУЕ я вообще пока еще не понимаю(

2

Re: AHK: Сохранить маленький произвольный кусок экрана

Слио пишет:

Какую-нибудь иконку выделять мышкой

Где выделяют, на рабочем столе?

Рисунок иконки никак не связан с приложением. Иконка у ярлыка может быть вообще от другого файла/ресурса.

3

Re: AHK: Сохранить маленький произвольный кусок экрана

Я думал, требуется произвольный участок экрана сохранить в файл точечного рисунка.

4

Re: AHK: Сохранить маленький произвольный кусок экрана

ypppu пишет:

Я думал, требуется произвольный участок экрана сохранить в файл точечного рисунка.

Ну, это-то делалось. Жаль вот, что «Гуру» этого не умеют [курсив в цитате мой - alexii]:

…в итоге получается файлик с картинкой, которую можно дальше использовать в скрипте для управления этой программкой. Вобщем всё стандартно.

Ещё бы понять, что на самом деле подразумевалось под «управлением этой программкой».

5

Re: AHK: Сохранить маленький произвольный кусок экрана

То есть без LangMF и Winset, region, нельзя сделать скриншот кусочка экрана (и сохранить в файл)?

6 (изменено: teadrinker, 2009-06-24 21:52:47)

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

Жаль вот, что «Гуру» этого не умеют.

Ну, я далеко не «Гуру», но на основе функций, взятых с оф. форума, такой скрипт написать могу.
Следующий код нужно сохранить в файл. После запуска появится полупрозрачное жёлтое окно, которое можно перемещать левой кнопкой мыши и менять его размеры. После нажатия Print Screen в директории скрипта появится bmp-файл со снимком экрана под окном.

    WM_LBUTTONDOWN = 0x201
    WM_NCLBUTTONDOWN = 0xA1

    INVALID_HANDLE_VALUE = -1
    INVALID_FILE_SIZE = 0xFFFFFFFF

    DetectHiddenWindows, On
    Gui, +LastFound +Resize -Caption +AlwaysOnTop +Owner
    ID := WinExist()
    WinSet, Transparent, 130
    Gui, Color, Yellow
    Gui, Show, h100 w100
    OnMessage(WM_LBUTTONDOWN, "GuiMove")
    Return

Esc::
GuiClose:
    ExitApp

PrintScreen::
    WinGetPos, X, Y, W, H, ahk_id %ID%
    Gui, Hide
    Gui, 2:-Caption +LastFound
    Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
    WinActivate
    Send, !{PrintScreen}
    Gui, 2:Destroy
    Gui, Show
    ScreenShot(A_Hour "." A_Min "." A_Sec ".bmp")
    Return

GuiMove()
{
    global
    PostMessage, WM_NCLBUTTONDOWN, 2
}

; Capturing Procedure
ScreenShot(filename)
{
    ; Copy clipboard data to a variable
    ClipData := ClipboardAll

    ; Get Image Dimensions
    ; Width Bytes
    VarSetCapacity(BinWidth, 4, 0)
    DllCall("RtlMoveMemory", UInt, &BinWidth, UInt, &(ClipData) + 20, Int, 4)

    ; Calculate Decimal Width
    x1 := *(&(BinWidth)+1)
    x2 := *(&(BinWidth))
    Width := (x1 * 256) + x2

    ; Height Bytes
    VarSetCapacity(BinHeight, 4, 0)
    DllCall("RtlMoveMemory", UInt, &BinHeight, UInt, &(ClipData) + 24, Int, 4)

    ; Calculate Decimal Height
    y1 := *(&(BinHeight)+1)
    y2 := *(&(BinHeight))
    Height := (y1 * 256) + y2

    ; Variable initialization
    VarSetCapacity(ImageFile, (Width * Height * 4) + 54, 0)
    VarSetCapacity(BmpHeader, 54, 0)

    ; BMP Header Construction
    ; Find a bmp file to copy the header
    Loop, % A_WinDir "*.bmp", 0, 1
    {
        FileRead, BmpHeader, % A_LoopFileLongPath
        break
    }

    ; Copy the correct image size to valid BMP Header
    DllCall("RtlMoveMemory", UInt, &(BmpHeader) + 18, UInt, &BinWidth, Int, 4)
    DllCall("RtlMoveMemory", UInt, &(BmpHeader) + 22, UInt, &BinHeight, Int, 4)

    ; Copy the correct bit depth to valid BMP Header
    DllCall("RtlMoveMemory", UInt, &(BmpHeader) + 28, UInt, &(ClipData) + 30, Int, 2)

    ; Copy the BMP Header to new ImageFile variable
    DllCall( "RtlMoveMemory", UInt, &ImageFile, UInt, &BmpHeader, Int, 54)
    ; Copy the Image data to new ImageFile variable
    DllCall( "RtlMoveMemory", UInt, &(ImageFile) + 54, UInt, &(ClipData) + 68, Int, Width * Height * 4)

    ; Write data to file
    fh := OpenFileForWrite(filename)
    WriteInFile(fh, ImageFile, (Width * Height * 4) + 54)
    CloseFile(fh)
}

/*
// Open the file for writing.
// Return the file handle to provide in further write operations and in the final close operation,
// or INVALID_HANDLE_VALUE if an error was found.
*/
OpenFileForWrite(_filename)
{
    local handle

    handle := DllCall("CreateFile"
            , "Str", _filename        ; lpFileName
            , "UInt", 0x40000000    ; dwDesiredAccess (GENERIC_WRITE)
            , "UInt", 3        ; dwShareMode (FILE_SHARE_READ|FILE_SHARE_WRITE)
            , "UInt", 0        ; lpSecurityAttributes
            , "UInt", 4        ; dwCreationDisposition (OPEN_ALWAYS: create if not exists)
            , "UInt", 0        ; dwFlagsAndAttributes
            , "UInt", 0)    ; hTemplateFile
    If (handle = INVALID_HANDLE_VALUE or handle = 0)
    {
        ErrorLevel = -1
    }
    If (ErrorLevel != 0)
        Return INVALID_HANDLE_VALUE    ; Couldn't open the file
    Return handle
}

/*
// Close the file.
*/
CloseFile(_handle)
{
    local result

    result := DllCall("CloseHandle", "UInt", _handle)
    If (result = 0)
    {
        ErrorLevel = -1
    }
}

/*
// Move the file pointer in the file to the given offset relative to moveMethod.
//
// moveMethod can be FILE_BEGIN, FILE_CURRENT or FILE_END.
// If moveMethod is -1, nothing is done (default, for operations at current position).
// To get the current position, call this function with just FILE_CURRENT (null offset).
// offset can be positive (toward end of the file) or negative (toward start of the file).
//
// Return -1 if there was an error, the new file pointer position if OK.
// Note: Currently it doesn't work for files larger than 2GB...
*/

MoveInFile(_handle, _moveMethod=-1, _offset=0)
{
    local result

    result = %INVALID_FILE_SIZE%
    if (_moveMethod != -1)
    {
        result := DllCall("SetFilePointer"
                , "UInt", _handle        ; hFile
                , "Int", _offset        ; lDistanceToMove
                , "UInt", 0            ; lpDistanceToMoveHigh
                , "UInt", _moveMethod)    ; dwMoveMethod
        if (result = -1)    ; INVALID_SET_FILE_POINTER
        {
            ErrorLevel = -1
        }
        If (ErrorLevel != 0)
            Return -1    ; Couldn't make the move
    }
    Return result
}

/*
// Write in a file opened for writing.
//
// Move to position given by moveMethod and offset
// (by default stand at current position) and
// write byteNb bytes from data (all data if byteNb = 0;
// data contains binary bytes that can be a string or
// raw bytes generated from hexa data with the Hex2Bin routine).
//
// moveMethod, defaulting to -1 (no move, write at current position),
// can also be FILE_BEGIN, FILE_CURRENT or FILE_END.
// offset can be positive (toward end of file) or negative (toward beginning of file).
//
// Return the number of bytes written (-1 if there was an error).
*/
WriteInFile(_handle, ByRef @data, _byteNb=0, _moveMethod=-1, _offset=0)
{
    local dataSize, result, written

    _offset := MoveInFile(_handle, _moveMethod, _offset)
    If (ErrorLevel != 0)
        Return -1    ; Couldn't make the move

    dataSize := VarSetCapacity(@data)        ; Get the capacity (>= used length!)
    If (_byteNb < 1 or _byteNb > dataSize)
    {
        _byteNb := dataSize
    }
    result := DllCall("WriteFile"
            , "UInt", _handle    ; hFile
            , "UInt", &@data    ; lpBuffer
            , "UInt", _byteNb    ; nNumberOfBytesToWrite
            , "UInt *", written    ; lpNumberOfBytesWritten
            , "UInt", 0)        ; lpOverlapped
    if (result = 0 or written < _byteNb)
    {
        ErrorLevel = -2
    }
    If (ErrorLevel != 0)
        Return -1    ; Couldn't write in the file
    Return written
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: Сохранить маленький произвольный кусок экрана

OFF: teadrinker, если Вы не поняли, то моя ирония относилась к тому, что, в понимании коллеги Слио, можно управлять приложением, просто получив bitmap иконки ярлыка приложения. Само получение-то как раз возможно.

P.S. У меня что-то скрипт из предыдущего поста даёт нечитабельные bmp.

8

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

P.S. У меня что-то скрипт из предыдущего поста даёт нечитабельные bmp.

Ага, если отрыть в текстовом редакторе, похоже на .tga.

9

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

P.S. У меня что-то скрипт из предыдущего поста даёт нечитабельные bmp.

Странно, у меня всё работает, bmp читаются...

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

10 (изменено: teadrinker, 2009-06-24 21:54:10)

Re: AHK: Сохранить маленький произвольный кусок экрана

Отредактировал, добавил пропущенные константы. Так работает?

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

11

Re: AHK: Сохранить маленький произвольный кусок экрана

Не работает.

12

Re: AHK: Сохранить маленький произвольный кусок экрана

Аналогично . Причём в Clipboard'е-то лежит правильный bitmap. Может, в файл что-то не то пишется?

13

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

Причём в Clipboard'е-то лежит правильный bitmap.

Ещё бы, ведь он делается с помощью

Send, !{PrintScreen}

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

14

Re: AHK: Сохранить маленький произвольный кусок экрана

Подумал, как это работает, но точно не уверен. Вроде бы в нужных координатах создаётся окно GUI, потом оно делается прозрачным, затем с него делается скриншот. Или тут какой-то другой принцип задействован?

15 (изменено: teadrinker, 2009-06-24 23:17:26)

Re: AHK: Сохранить маленький произвольный кусок экрана

ypppu пишет:

Вроде бы в нужных координатах создаётся окно GUI, потом оно делается прозрачным, затем с него делается скриншот.

Нет, как раз таким образом у меня получался скриншот окна, как если бы оно было не прозрачным. Здесь создаётся вспомогательное окно в координатах основного, но оно изначально скрытое. Затем основное прячется, вспомогательное активируется и уже с него снимается скриншот.
В конце концов, на оф. форуме есть и другие способы сохранения bitmap в файл, если этот почему-то не работает.

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

16

Re: AHK: Сохранить маленький произвольный кусок экрана

2teadrinker: мне сама идея со скрытием окна понравилась. Это-то как раз работает.

17 (изменено: teadrinker, 2009-06-25 00:47:47)

Re: AHK: Сохранить маленький произвольный кусок экрана

А так работает? Требует gdiplus.dll

    WM_LBUTTONDOWN = 0x201
    WM_NCLBUTTONDOWN = 0xA1

    DetectHiddenWindows, On
    Gui, +LastFound +Resize -Caption +AlwaysOnTop +Owner
    ID := WinExist()
    WinSet, Transparent, 130
    Gui, Color, Yellow
    Gui, Show, h100 w100
    OnMessage(WM_LBUTTONDOWN, "GuiMove")
    Return

Esc::
GuiClose:
    ExitApp

PrintScreen::
    WinGetPos, X, Y, W, H, ahk_id %ID%
    Gui, Hide
    Gui, 2:-Caption +LastFound
    Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
    WinActivate
    Send, !{PrintScreen}
    Gui, 2:Destroy
    Gui, Show
    Convert("", A_Hour "." A_Min "." A_Sec ".bmp")
    Convert("", A_Hour "." A_Min "." A_Sec ".jpg")
    Return

GuiMove()
{
    global
    PostMessage, WM_NCLBUTTONDOWN, 2
}

Convert(sFileFr = "", sFileTo = "")
{
   If   sFileTo  =
      sFileTo := A_ScriptDir . "\screen.bmp"
   SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

   If Not   hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
      Return   sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo . "\" . sNameTo . ".bmp") : ""
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

   If   !sFileFr
   {
      DllCall("OpenClipboard", "Uint", 0)
      If    DllCall("IsClipboardFormatAvailable", "Uint", 2) && (hBM:=DllCall("GetClipboardData", "Uint", 2)) {
         DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0, "UintP", pImage)
      }
      DllCall("CloseClipboard")
   }
   Else If   (sFileFr Is Integer) {
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0, "UintP", pImage)
   }
   Else {
      DllCall("gdiplus\GdipLoadImageFromFile", "Uint", Unicode4Ansi(wFileFr,sFileFr), "UintP", pImage)
   }

   DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
   VarSetCapacity(ci, nSize)
   DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
   Loop,   %nCount%
   {
      If   !InStr(Ansi4Unicode(NumGet(ci, 76 * (A_Index - 1) + 44)), "." . sExtTo)
         Continue
      pCodec := &ci + 76 * (A_Index - 1)
         Break
   }

   If   pImage
      pCodec   ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage, "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec, "Uint", 0) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pImage, "UintP", hBitmap, "Uint", 0) . SetClipboardData(hBitmap), DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

   DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
   DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hFile:=   DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0, "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16, "Uint", 6, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint", 8, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
   DllCall("CloseHandle", "Uint", hFile)
}

Unicode4Ansi(ByRef wString, sString)
{
   nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2)
   DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize)
   Return   &wString
}

Ansi4Unicode(pString)
{
   nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
   Return   sString
}

SetClipboardData(hBitmap)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hDIB :=   DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
   pDIB :=   DllCall("GlobalLock", "Uint", hDIB)
   DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
   DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
   DllCall("GlobalUnlock", "Uint", hDIB)
   DllCall("DeleteObject", "Uint", hBitmap)
   DllCall("OpenClipboard", "Uint", 0)
   DllCall("EmptyClipboard")
   DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
   DllCall("CloseClipboard")
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AHK: Сохранить маленький произвольный кусок экрана

Да.

Ощущение такое, что у меня в более ранних вариантах попросту отсутствовал заголовок в результирующем bmp. Впрочем, это субъективно/hex-визуально .

19

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

Жаль вот, что «Гуру» этого не умеют [курсив в цитате мой - alexii]:

…в итоге получается файлик с картинкой, которую можно дальше использовать в скрипте для управления этой программкой. Вобщем всё стандартно.

Ещё бы понять, что на самом деле подразумевалось под «управлением этой программкой».

Видимо, имелось ввиду, что картинка будет добавлена в окно GUI, и у неё будет метка перехода, запускающая соответствующую программу.

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

20

Re: AHK: Сохранить маленький произвольный кусок экрана

Такое мне на ум, увы, не пришло .

21 (изменено: migomigo, 2009-06-25 17:58:16)

Re: AHK: Сохранить маленький произвольный кусок экрана

К сожалению, у меня этот скрипт несрабатывает. Сохраняет синий квадратик. Наверно потому что у меня виста..:rolleyes:

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

22

Re: AHK: Сохранить маленький произвольный кусок экрана

А у тебя gdiplus.dll есть?

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

23

Re: AHK: Сохранить маленький произвольный кусок экрана

Признаюсь, так как глаза сразу скользнули по скрипту - я изначально не заметил его необходимость. Но увы, после скачивания gdiplus.dll - скрипт все равно сохраняет синий прямоугольник..

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

24

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker, пример вполне для Коллекции. Может быть и этот, если разобраться, почему у меня с ypppu он до конца не сработал .

25

Re: AHK: Сохранить маленький произвольный кусок экрана

Немного доведу до ума, и размещу.

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

26

Re: AHK: Сохранить маленький произвольный кусок экрана

Коль Вы не против — тогда прикрепляю тему.

27

Re: AHK: Сохранить маленький произвольный кусок экрана

На основе второго примера написал полноценный скрипт, сохраняющий скриншоты и снапшоты в файлы с расширением по выбору. Управление через контекстное меню окна.
Грячие клавиши:
Pause — скрыть/показать окно.
ScrollLock — вернуть окно в центр экрана.
PrintScreen — если окно видимо, снапшот части экрана, расположенной непосредственно под ним; если скрыто — скриншот.
Alt + PrintScreen — если окно скрипта скрыто, снапшот активного окна.
Escape — выход.
Если открыто окно установок Color – Transparent:
Щелчок ЛКМ по названию слайдера — установка в позицию "0", ПКМ — "255".
Escape — закрытие окна установок.

    #NoEnv
    #UseHook
    OnExit, Exit
    SetWinDelay, 0
    SetBatchLines, -1
    CoordMode, Mouse

    Menu, Tray, Icon, Shell32.dll, 95

    Ini_ReadSect("Color", "Red", Red_, "FF", "Green", Green_, "C7", "Blue", Blue_, "00")
    Ini_ReadSect("Transparent", "Trans", Trans, 130)
    Ini_ReadSect("Extension", "ext", ext, "bmp")
    Ini_ReadSect("Out Directory", "OutDirectory", OutDirectory, A_ScriptDir)

    Menu, Extensions, Add, JPG, Extensions
    Menu, Extensions, Add, BMP, Extensions
    Menu, Extensions, Add, TIF, Extensions
    Menu, Extensions, Add, GIF, Extensions
    Menu, Extensions, Add, PNG, Extensions
    Menu, Extensions, Check, %ext%

    Menu, MainMenu, Add, Color – Transparent, Settings
    Menu, MainMenu, Add, Out Directory, OutDirectory
    Menu, MainMenu, Add, Extension, :Extensions
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Exit, GuiClose

    Gui, +LastFound -Caption +AlwaysOnTop +Owner
    WinGet, ID
    WinSet, Transparent, 0
    Gui, Color, % Red_ Green_ Blue_
    Loop 8
        Gui, Add, Text, w10 h10 +0x4 Hidden
    Loop 4
        SetCursor("HAND", "Static" a_index)
    Gui, Show, h200 w200

    OnMessage(0x201, "WM_LBUTTONDOWN")
    OnMessage(0x204, "WM_RBUTTONDOWN")

    Hotkey, LButton, WinResize, Off
    Melt(ID, Trans, 1)
    SetTimer, MouseMove, 100

MouseMove:
    MouseGetPos, X_M, Y_M, ID_Win
    if !Move && (ID_Win = ID3)
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    if (X_M <= X + W + 20) && (X_M >= X + W - 20)
                            && (Y_M <= Y + H + 20) && (Y_M >= Y + H - 20)
        Var = 1
    else if (X_M <= X + 20) && (X_M >= X - 20)
                            && (Y_M <= Y + H + 20) && (Y_M >= Y + H - 20)
        Var = 2
    else if (X_M <= X + 20) && (X_M >= X - 20)
                            && (Y_M <= Y + 20) && (Y_M >= Y - 20)
        Var = 3
    else if (X_M <= X + W + 20) && (X_M >= X + W - 20)
                            && (Y_M <= Y + 20) && (Y_M >= Y - 20)
        Var = 4
    else if (X_M <= X + W + 20) && (X_M >= X + W - 20)
                            && (Y_M <= Y + H - 20) && (Y_M >= Y + 20)
        Var = 5
    else if (X_M <= X + W - 20) && (X_M >= X + 20)
                            && (Y_M <= Y + H + 20) && (Y_M >= Y + H - 20)
        Var = 6
    else if (X_M <= X + 20) && (X_M >= X - 20)
                            && (Y_M <= Y + H - 20) && (Y_M >= Y + 20)
        Var = 7
    else if (X_M <= X + W - 20) && (X_M >= X + 20)
                            && (Y_M <= Y + 20) && (Y_M >= Y - 20)
        Var = 8
    else
        Var =
    if Var
    {
        Hotkey, LButton, On
        GuiControl, Show, Static%Var%
        Loop 8
        {
            if (a_index = Var)
                Continue
            GuiControl, Hide, Static%a_index%
        }
    }
    else if !Move
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
    }
    Return

WinResize:
    SetTimer, MouseMove, Off
    X_M_Old := X_M, Y_M_Old := Y_M, Move = 1
    While GetKeyState("LButton", "P")
    {
        MouseGetPos, X_M, Y_M
        {
            if Var = 1
                WinMove, ahk_id %ID%,,,, W + X_M - X_M_Old, H + Y_M - Y_M_Old
            else if Var = 2
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old,, W - X_M + X_M_Old, H + Y_M - Y_M_Old
            else if Var = 3
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old, Y + Y_M - Y_M_Old, W - X_M + X_M_Old
                                                                                                , H - Y_M + Y_M_Old
            else if Var = 4
                WinMove, ahk_id %ID%,,, Y + Y_M - Y_M_Old, W + X_M - X_M_Old, H - Y_M + Y_M_Old
            else if Var = 5
                WinMove, ahk_id %ID%,,,, W + X_M - X_M_Old
            else if Var = 6
                WinMove, ahk_id %ID%,,,,, H + Y_M - Y_M_Old
            else if Var = 7
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old,, W - X_M + X_M_Old
            else if Var = 8
                WinMove, ahk_id %ID%,,, Y + Y_M - Y_M_Old,, H - Y_M + Y_M_Old
        }
        Sleep, 10
    }
    Move =
    SetTimer, MouseMove, On
    Return

GuiSize:
    GuiControl, Move, Static1, % "x" A_GuiWidth - 10 "y" A_GuiHeight - 10
    GuiControl, Move, Static2, % "x0 y" A_GuiHeight - 10
    GuiControl, Move, Static3, % "x0 y0"
    GuiControl, Move, Static4, % "x" A_GuiWidth - 10 "y0"
    GuiControl, Move, Static5, % "x" A_GuiWidth - 10 "y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static6, % "x" (A_GuiWidth - 10)/2 "y" A_GuiHeight - 10
    GuiControl, Move, Static7, % "x0 y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static8, % "x" (A_GuiWidth - 10)/2 "y0"
    Return

GuiContextMenu:
    Menu, MainMenu, Show
    Return

Extensions:
    Menu, Extensions, UnCheck, %ext%
    StringLower, ext, A_ThisMenuItem
    Menu, Extensions, Check, %ext%
    Return

OutDirectory:
    Gosub, Pause
    FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
    OutDirectory := OutDir ? OutDir : OutDirectory
    Gosub, Pause
    Return

Settings:
   IfWinExist, ahk_id %ID3%
        Goto, 3GuiClose
   Gui, 3:+owner1 +LastFound
    WinGet, ID3
    WinSet, Transparent, 0
    Gui, 3:Color, CCC8C0

    Gui, 3:Font, s9, Arial
   Gui, 3:Add, Text, x11 y17 w29 cRed, Red
   Gui, 3:Add, Text, x10 y47 w30 cGreen, Green
   Gui, 3:Add, Text, x11 y77 w29 cBlue, Blue
    Gui, 3:Add, Text, x10 y107 w30 cWhite, Trans

   Gui, 3:Add, Slider
        , vRed gColorSet x43 y15 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Red_%
   Gui, 3:Add, Slider
        , vGreen gColorSet x43 y45 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Green_%
   Gui, 3:Add, Slider
        , vBlue gColorSet x43 y75 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Blue_%
   Gui, 3:Add, Slider
        , vTrans gTransSet x43 y105 w197 h20 Range0-255 ToolTip AltSubmit, % Trans

    Gui, 3:Add, Button, g3GuiClose x80 y140 w90 h23, OK

    WinGetPos, X, Y, W, H, ahk_id %ID%
    3Gui_Y := (Y + H + 15 + 180 <= A_ScreenHeight) ? Y + H + 15 : Y - 180 - 35
    3Gui_Y := (3Gui_Y < 0) ? 0 : 3Gui_Y
    3Gui_X := (X+(W-250)/2+250 > A_ScreenWidth) ? A_ScreenWidth - 250 : X + (W-256)/2
    3Gui_X := (3Gui_X < 0) ? 0 : 3Gui_X

    GuiControl, 3:Focus, Static1
    Gui, 3:Show, x%3Gui_X% y%3Gui_Y% w250 h180, Color – Transparent
    Melt(ID3, 255, 1)
    Return

ColorSet:
    %A_GuiControl%_ := StrLen(Tr := Trans(%A_GuiControl%, 10, 16)) = 1 ? "0" Tr : Tr
    Gui, 1:Color, % Red_ Green_ Blue_
    Return

TransSet:
    WinSet, Transparent, % Trans, ahk_id %ID%
    Return

3GuiClose:
    Melt(ID3, 255, 0)
    Gui, 3:Destroy
    Return

Exit:
    IfWinExist, ahk_id %ID3%
        Gosub, 3GuiClose
    if !mod
        Melt(ID, Trans, 0)
    Ini_WriteSect("Color", "Red", Red_, "Green", Green_, "Blue", Blue_)
    Ini_WriteSect("Transparent", "Trans", Trans)
    Ini_WriteSect("Extension", "ext", ext)
    Ini_WriteSect("Out Directory", "OutDirectory", OutDirectory)
    ExitApp

PrintScreen::
    IfWinExist, ahk_id %ID%
    {
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0)
        Gui, 2:-Caption +LastFound
        Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
        WinActivate
        Send, !{PrintScreen}
        Gui, 2:Destroy
        Melt(ID, Trans, 1)
    }
    Else
        Send, {PrintScreen}
    Convert("", OutDirectory "\" A_Hour "." A_Min "." A_Sec "." ext)
    Return

~!PrintScreen:: Convert("", OutDirectory "\" A_Hour "." A_Min "." A_Sec "." ext)

Pause::
    Melt(ID, Trans, mod)
    mod := !mod
    Return

ScrollLock::
    if !mod
        Melt(ID, Trans, 0)
    Gui, Show, % "x" A_ScreenWidth/2 - 103 "y" A_ScreenHeight/2 - 118 "w200 h200"
    Melt(ID, 130, 1), Trans := 130, mod := ""
    GuiControl, 3:, Trans, 130
    Return

Esc::
GuiClose:
    ExitApp

#IfWinExist Color – Transparent ahk_class AutoHotkeyGUI
Esc:: Goto, 3GuiClose
#IfWinExist

Melt(hWnd, Trans, Appear, N = 20)
{
    WinShow, ahk_id %hWnd%
    While A_Index * N < Trans
    {
        WinSet, Transparent, % Appear ? A_Index * N : Trans - A_Index * N, ahk_id %hWnd%
        Sleep, 10
    }
    if Appear
        WinSet, Transparent, % Trans, ahk_id %hWnd%
    Else
        WinHide, ahk_id %hWnd%
}

WM_LBUTTONDOWN(wp, lp, msg, hWnd)
{
    global ID, Var
    if (hWnd = ID) && (!Var || GetKeyState("Alt"))
        PostMessage, WM_NCLBUTTONDOWN := 0xA1, 2,,, ahk_id %ID%
    SetValue(hWnd, 0)
}

WM_RBUTTONDOWN(wp, lp, msg, hWnd)
{
    SetValue(hWnd, 255)
}

SetValue(hWnd, Pos)
{
    local Control, Text
    if (hWnd != ID3)
        Return
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 3:, % "msctls_trackbar32" SubStr(Control, 7), % Pos
    Gui, 3:Submit, NoHide
    GuiControlGet, Text, 3:, % Control
    %Text%_ := StrLen(Tr := Trans(%Text%, 10, 16)) = 1 ? "0" Tr : Tr
    Gui, 1:Color, % Red_ Green_ Blue_
    Gosub, TransSet
}


; Пишет секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_WriteSect(Section, Key1, Value1, Key2 = "", Value2 = ""
   , Key3 = "", Value3 = "", Key4 = "", Value4 = "", Key5 = "", Value5 = ""
   , Key6 = "", Value6 = "", Key7 = "", Value7 = "", Key8 = "", Value8 = ""
   , Key9 = "", Value9 = "", Key10 = "", Value10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniWrite, % Value%a_index%, % FileName, % Section, % Key%a_index%
}

; Читает секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_ReadSect(Section, Key1, ByRef var1, Default1 = "", Key2 = "", ByRef var2 = "", Default2 = ""
   , Key3 = "", ByRef var3 = "", Default3 = "", Key4 = "", ByRef var4 = "", Default4 = ""
   , Key5 = "", ByRef var5 = "", Default5 = "", Key6 = "", ByRef var6 = "", Default6 = ""
   , Key7 = "", ByRef var7 = "", Default7 = "", Key8 = "", ByRef var8 = "", Default8 = ""
   , Key9 = "", ByRef var9 = "", Default9 = "", Key10 = "", ByRef var10 = "", Default10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniRead, var%a_index%, % FileName, % Section, % Key%a_index%, % Default%a_index%
}


; Переводит число Number из системы счисления N в систему счисления K. Number должно
; быть написано без префикса, и, если содержит буквенные символы, в кавычках.
; Возвращает значение без префикса.

Trans(Number, N, K)
{
    if N = 10
        Return Trans_Dec(Number, K)
    if K = 10
        Return Trans_ToDec(Number, N)
    Else
        Return Trans_Dec(Trans_ToDec(Number, N), K)
}

Trans_Dec(Number, K)
{
    if K = 16
    {
        SetFormat, integer, hex
        TransNumber := SubStr(Number + 0, 3)
        SetFormat, integer, dec
        Return TransNumber
    }
    if (Number < K)
        Return Number < 10 ? Number : Chr(Asc("A") + Number - 10)
    Mod := Mod(Number,K) < 10 ? Mod(Number,K) : Chr(Asc("A") + Mod(Number,K) - 10)
    Return Trans_Dec(Floor(Number/K),K) . Mod
}

Trans_ToDec(Number, N)
{
    if N = 16
    {
        SetFormat, integer, d
        Number := "0x" . Number
        Return Number + 0
    }
    StringCaseSense on
    if StrLen(Number) = 1
    {
        if Number between a and z
            Number := Asc(Number) - Asc("a") + 10
        if Number between A and Z
            Number := Asc(Number) - Asc("A") + 10
        Return Number
    }
    SubString := SubStr(Number,1,1)
    if SubString between a and z
        SubString := Asc(SubString) - Asc("a") + 10
    if SubString between A and Z
        SubString := Asc(SubString) - Asc("A") + 10
    Return SubString*N**(StrLen(Number)-1) + Trans_ToDec(SubStr(Number,2),N)
}

Convert(sFileFr = "", sFileTo = "")
{
   If sFileTo  =
      sFileTo := A_ScriptDir . "\screen.bmp"
   SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

   If !hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
      Return sFileFr+0 ? SaveHBITMAPToFile(sFileFr
                                                    , sDirTo . "\" . sNameTo . ".bmp") : ""
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

   If !sFileFr
   {
      DllCall("OpenClipboard", "Uint", 0)
      If DllCall("IsClipboardFormatAvailable", "Uint", 2)
                && (hBM:=DllCall("GetClipboardData", "Uint", 2))
        {
         DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0
                , "UintP", pImage)
      }
      DllCall("CloseClipboard")
   }
   Else If (sFileFr Is Integer)
    {
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0
            , "UintP", pImage)
   }
   Else
    {
      DllCall("gdiplus\GdipLoadImageFromFile", "Uint", Unicode4Ansi(wFileFr,sFileFr)
            , "UintP", pImage)
   }

   DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
   VarSetCapacity(ci, nSize)
   DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
   Loop, %nCount%
   {
      If !InStr(Ansi4Unicode(NumGet(ci, 76 * (A_Index - 1) + 44)), "." . sExtTo)
         Continue
      pCodec := &ci + 76 * (A_Index - 1)
         Break
   }

   If pImage
      pCodec ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage
            , "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec
            , "Uint", 0) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pImage
            , "UintP", hBitmap, "Uint", 0) . SetClipboardData(hBitmap)
            , DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

   DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
   DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hFile := DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0
                                                        , "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16
                                                        , "Uint", 6, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint",8, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20)
                                                        , "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
   DllCall("CloseHandle", "Uint", hFile)
}

Unicode4Ansi(ByRef wString, sString)
{
   nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                                        , "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2)
   DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                            , "int", -1, "Uint", &wString, "int", nSize)
   Return   &wString
}

Ansi4Unicode(pString)
{
   nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                            , "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                , "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
   Return   sString
}

SetClipboardData(hBitmap)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hDIB :=   DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
   pDIB :=   DllCall("GlobalLock", "Uint", hDIB)
   DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
   DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
   DllCall("GlobalUnlock", "Uint", hDIB)
   DllCall("DeleteObject", "Uint", hBitmap)
   DllCall("OpenClipboard", "Uint", 0)
   DllCall("EmptyClipboard")
   DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
   DllCall("CloseClipboard")
}

SetCursor(pShape, pCtrl="")
{
   Return SetCursor_(pShape, pCtrl, 0)
}

SetCursor_(wparam, lparam, msg)
{
    global ID
   static WM_SETCURSOR := 0x20, WM_MOUSEMOVE := 0x200
   static HAND := 32649
   static hover, curOld=32512, cursor, ctrls="`n", init

   if !init
      init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"),  OnMessage(WM_MOUSEMOVE, "SetCursor_")

   if A_Gui =
   {
      cursor := DllCall("LoadCursor", "Uint", 0, "Int", %WPARAM%, "Uint")
      ctrls .= lparam "=" cursor "`n"
   }

   If (msg = WM_SETCURSOR)
      ifEqual, hover, 1, Return 1

   if (msg = WM_MOUSEMOVE)
   {
      MouseGetPos,,,ID_Win,c
        if (ID_Win = ID)
            Return
        If j := InStr(ctrls, "`n" c "=")
        {
            hover := true
            j += 2+StrLen(c)
            j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j)-j+1)
            DllCall("SetCursor", "uint",j)
        }
        else DllCall("SetCursor", "uint", curOld), hover := ""
   }
}

Функции Convert() и SetCursor() взяты с оф. форума и приспособлены к данному скрипту.
Функции Ini_ReadSect(), Ini_WriteSect(), Trans() написаны для общего случая и предназначены для использования через библиотеку.

Протестируйте, работает? Имеет ли смысл размещать в таком виде в коллекции?

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

28

Re: AHK: Сохранить маленький произвольный кусок экрана

Работает. Только я бы предпочёл такую схему формирования имён файлов: YYYYMMDD-HHMMSSNN (NN — доли секунд или порядковый номер внутри одной секунды), что-то так.

Также меня смущает термин снапшот, который в этом значении не применяется нигде — ни на русском, ни в английском варианте. Я бы всё ж применял вариант «скриншот части экрана/активного окна». То есть, примерно так:

PrintScreen — если окно видимо, снапшот скриншот части экрана, расположенной непосредственно под ним; если скрыто — скриншот всего экрана.

Далее, здесь:

Alt + PrintScreen — если окно скрипта скрыто, снапшот активного окна.

А если не скрыто — у меня получается то же самое — скриншот активного окна?! Надо бы сие как-то отразить в пояснении, а то начало фразы «если окно скрипта скрыто» заставляет строить неверные предположения.

Кстати, скриншот самого окна выделения (делаем окно выделения активным, нажимаем Pause — окно скрывается, активным становится другое окно; ещё раз Pause, окно выделения появляется и становится активным, Alt-PrintScrn) тоже интересно смотрится . Сие можно отследить/изменить поведение?

Прежнее изменение размеров окна выделения было нагляднее . В последнем варианте можно сделать появляющиеся маркеры изменения размеров инверсными по отношению к фону окна выделения? А то их практически не видно.

29

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

Далее, здесь:

Alt + PrintScreen — если окно скрипта скрыто, снапшот активного окна.

А если не скрыто — у меня получается то же самое — скриншот активного окна?! Надо бы сие как-то отразить в пояснении, а то начало фразы «если окно скрипта скрыто» заставляет строить неверные предположения.

Согласен.

alexii пишет:

Кстати, скриншот самого окна выделения (делаем окно выделения активным, нажимаем Pause — окно скрывается, активным становится другое окно; ещё раз Pause, окно выделения появляется и становится активным, Alt-PrintScrn) тоже интересно смотрится . Сие можно отследить/изменить поведение?

Здесь не совсем Вас понял, как (на какое) изменить?

alexii пишет:

В последнем варианте можно сделать появляющиеся маркеры изменения размеров инверсными по отношению к фону окна выделения? А то их практически не видно.

Можно попробовать. Сейчас, кстати, они чёрные, серыми кажутся из-за полупрозрачности окна. Тем не менее, на моём мониторе их видно прекрасно.
Поясню, почему я отказался от прошлого варианта. Окно было со стилем WS_SIZEBOX (+Resize), что давало рамочку по краю, которая, имхо, мешала точно определить границу выделения. Но при этом курсоры, показывающие возможность изменения размера, загружались автоматически. Сейчас разбираюсь с функцией SetSystemCursor, разберусь — можно будет отказаться от маркеров. В общем, ещё нужно какое-то время.

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

30 (изменено: teadrinker, 2009-06-29 22:52:09)

Re: AHK: Сохранить маленький произвольный кусок экрана

Вот вариант с инверсивными маркерами:

    #NoEnv
    #UseHook
    OnExit, Exit
    SetWinDelay, 0
    SetBatchLines, -1
    CoordMode, Mouse

    Menu, Tray, Icon, Shell32.dll, 95

    Ini_ReadSect("Color", "Red", Red_, "FF", "Green", Green_, "C7", "Blue", Blue_, "00")
    Ini_ReadSect("Transparent", "Trans", Trans, 130)
    Ini_ReadSect("Extension", "ext", ext, "bmp")
    Ini_ReadSect("Out Directory", "OutDirectory", OutDirectory, A_ScriptDir)

    Menu, Extensions, Add, JPG, Extensions
    Menu, Extensions, Add, BMP, Extensions
    Menu, Extensions, Add, TIF, Extensions
    Menu, Extensions, Add, GIF, Extensions
    Menu, Extensions, Add, PNG, Extensions
    Menu, Extensions, Check, %ext%

    Menu, MainMenu, Add, Color – Transparent, Settings
    Menu, MainMenu, Add, Out Directory, OutDirectory
    Menu, MainMenu, Add, Extension, :Extensions
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Exit, GuiClose

    Gui, +LastFound -Caption +AlwaysOnTop +Owner
    WinGet, ID
    WinSet, Transparent, 0
    Gui, Color, % Red_ Green_ Blue_

    Gui, Add, Text, w10 h10 x190 y190 Hidden hwndText1ID
    Gui, Add, Text, w10 h10 x0 y190 Hidden hwndText2ID
    Gui, Add, Text, w10 h10 x0 y0 Hidden hwndText3ID
    Gui, Add, Text, w10 h10 x190 y0 Hidden hwndText4ID
    Gui, Add, Text, w10 h10 x190 y95 Hidden hwndText5ID
    Gui, Add, Text, w10 h10 x95 y190 Hidden hwndText6ID
    Gui, Add, Text, w10 h10 x0 y95 Hidden hwndText7ID
    Gui, Add, Text, w10 h10 x95 y0 Hidden hwndText8ID

    MarkerColor := InvertColor(Red_, Green_, Blue_)
    Loop 8
        Control_Colors(Text%a_index%ID, "Set", MarkerColor)

    Loop 4
        SetCursor("HAND", "Static" a_index)

    Control_Colors(ID, "RCB", 0, 0)
    Gui, Show, h200 w200

    OnMessage(0x201, "WM_LBUTTONDOWN")
    OnMessage(0x204, "WM_RBUTTONDOWN")

    Hotkey, LButton, WinResize, Off
    Melt(ID, Trans, 1)
    SetTimer, MouseMove, 100

MouseMove:
    MouseGetPos, X_M, Y_M, ID_Win
    if !Move && (ID_Win = ID3)
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    if (X_M <= X + W + 20) && (X_M >= X + W - 10)
                            && (Y_M <= Y + H + 20) && (Y_M >= Y + H - 10)
        Var = 1
    else if (X_M <= X + 10) && (X_M >= X - 20)
                            && (Y_M <= Y + H + 20) && (Y_M >= Y + H - 10)
        Var = 2
    else if (X_M <= X + 10) && (X_M >= X - 20)
                            && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 3
    else if (X_M <= X + W + 20) && (X_M >= X + W - 10)
                            && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 4
    else if (X_M <= X + W + 20) && (X_M >= X + W - 10)
                            && (Y_M < Y + H - 10) && (Y_M > Y + 10)
        Var = 5
    else if (X_M < X + W - 10) && (X_M > X + 10)
                            && (Y_M <= Y + H + 20) && (Y_M >= Y + H - 10)
        Var = 6
    else if (X_M <= X + 10) && (X_M >= X - 20)
                            && (Y_M < Y + H - 10) && (Y_M > Y + 10)
        Var = 7
    else if (X_M < X + W - 10) && (X_M > X + 10)
                            && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 8
    else
        Var =
    if Var
    {
        Hotkey, LButton, On
        GuiControl, Show, Static%Var%
        Loop 8
        {
            if (a_index = Var)
                Continue
            GuiControl, Hide, Static%a_index%
        }
    }
    else if !Move
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
    }
    Return

WinResize:
    SetTimer, MouseMove, Off
    X_M_Old := X_M, Y_M_Old := Y_M, Move = 1
    While GetKeyState("LButton", "P")
    {
        MouseGetPos, X_M, Y_M
        {
            if Var = 1
                WinMove, ahk_id %ID%,,,, W + X_M - X_M_Old, H + Y_M - Y_M_Old
            else if Var = 2
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old,, W - X_M + X_M_Old, H + Y_M - Y_M_Old
            else if Var = 3
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old, Y + Y_M - Y_M_Old, W - X_M + X_M_Old
                                                                                                , H - Y_M + Y_M_Old
            else if Var = 4
                WinMove, ahk_id %ID%,,, Y + Y_M - Y_M_Old, W + X_M - X_M_Old, H - Y_M + Y_M_Old
            else if Var = 5
                WinMove, ahk_id %ID%,,,, W + X_M - X_M_Old
            else if Var = 6
                WinMove, ahk_id %ID%,,,,, H + Y_M - Y_M_Old
            else if Var = 7
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old,, W - X_M + X_M_Old
            else if Var = 8
                WinMove, ahk_id %ID%,,, Y + Y_M - Y_M_Old,, H - Y_M + Y_M_Old
        }
        Sleep, 10
    }
    Move =
    SetTimer, MouseMove, On
    Return

GuiSize:
    GuiControl, Move, Static1, % "x" A_GuiWidth - 10 "y" A_GuiHeight - 10
    GuiControl, Move, Static2, % "x0 y" A_GuiHeight - 10
    GuiControl, Move, Static3, % "x0 y0"
    GuiControl, Move, Static4, % "x" A_GuiWidth - 10 "y0"
    GuiControl, Move, Static5, % "x" A_GuiWidth - 10 "y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static6, % "x" (A_GuiWidth - 10)/2 "y" A_GuiHeight - 10
    GuiControl, Move, Static7, % "x0 y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static8, % "x" (A_GuiWidth - 10)/2 "y0"
    Return

GuiContextMenu:
    Menu, MainMenu, Show
    Return

Extensions:
    Menu, Extensions, UnCheck, %ext%
    StringLower, ext, A_ThisMenuItem
    Menu, Extensions, Check, %ext%
    Return

OutDirectory:
    Gosub, Pause
    FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
    OutDirectory := OutDir ? OutDir : OutDirectory
    Gosub, Pause
    Return

Settings:
    IfWinExist, ahk_id %ID3%
        Goto, 3GuiClose
    Gui, 3:+owner1 +LastFound
    WinGet, ID3
    WinSet, Transparent, 0
    Gui, 3:Color, CCC8C0

    Gui, 3:Font, s9, Arial
    Gui, 3:Add, Text, x11 y17 w29 cRed, Red
    Gui, 3:Add, Text, x10 y47 w30 cGreen, Green
    Gui, 3:Add, Text, x11 y77 w29 cBlue, Blue
    Gui, 3:Add, Text, x10 y107 w30 cWhite, Trans

    Gui, 3:Add, Slider
        , vRed gColorSet x43 y15 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Red_%
    Gui, 3:Add, Slider
        , vGreen gColorSet x43 y45 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Green_%
    Gui, 3:Add, Slider
        , vBlue gColorSet x43 y75 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Blue_%
    Gui, 3:Add, Slider
        , vTrans gTransSet x43 y105 w197 h20 Range0-255 ToolTip AltSubmit, % Trans

    Gui, 3:Add, Button, g3GuiClose x80 y140 w90 h23, OK

    WinGetPos, X, Y, W, H, ahk_id %ID%
    3Gui_Y := (Y + H + 15 + 180 <= A_ScreenHeight) ? Y + H + 15 : Y - 180 - 35
    3Gui_Y := (3Gui_Y < 0) ? 0 : 3Gui_Y
    3Gui_X := (X+(W-250)/2+250 > A_ScreenWidth) ? A_ScreenWidth - 250 : X + (W-256)/2
    3Gui_X := (3Gui_X < 0) ? 0 : 3Gui_X

    GuiControl, 3:Focus, Static1
    Gui, 3:Show, x%3Gui_X% y%3Gui_Y% w250 h180, Color – Transparent
    Melt(ID3, 255, 1)
    Return

ColorSet:
    %A_GuiControl%_ := StrLen(Tr := Trans(%A_GuiControl%, 10, 16)) = 1 ? "0" Tr : Tr
    Gui, 1:Color, % Red_ Green_ Blue_

    MarkerColor := InvertColor(Red_, Green_, Blue_)
    Loop 8
        Control_Colors(Text%a_index%ID, "Set", MarkerColor)
    Return

TransSet:
    WinSet, Transparent, % Trans, ahk_id %ID%
    Return

3GuiClose:
    Melt(ID3, 255, 0)
    Gui, 3:Destroy
    Return

Exit:
    IfWinExist, ahk_id %ID3%
        Gosub, 3GuiClose
    if !mod
        Melt(ID, Trans, 0)
    Ini_WriteSect("Color", "Red", Red_, "Green", Green_, "Blue", Blue_)
    Ini_WriteSect("Transparent", "Trans", Trans)
    Ini_WriteSect("Extension", "ext", ext)
    Ini_WriteSect("Out Directory", "OutDirectory", OutDirectory)
    ExitApp

PrintScreen::
    IfWinExist, ahk_id %ID%
    {
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0)
        Gui, 2:-Caption +LastFound
        Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
        WinActivate
        Send, !{PrintScreen}
        Gui, 2:Destroy
        Melt(ID, Trans, 1)
    }
    Else
        Send, {PrintScreen}
    Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)
    Return

~!PrintScreen:: Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)

Pause::
    Melt(ID, Trans, mod)
    mod := !mod
    Return

ScrollLock::
    if !mod
        Melt(ID, Trans, 0)
    Gui, Show, % "x" A_ScreenWidth/2 - 103 "y" A_ScreenHeight/2 - 118 "w200 h200"
    Melt(ID, 130, 1), Trans := 130, mod := ""
    GuiControl, 3:, Trans, 130
    Return

Esc::
GuiClose:
    ExitApp

#IfWinExist Color – Transparent ahk_class AutoHotkeyGUI
Esc:: Goto, 3GuiClose
#IfWinExist

Melt(hWnd, Trans, Appear, N = 20)
{
    WinShow, ahk_id %hWnd%
    While A_Index * N < Trans
    {
        WinSet, Transparent, % Appear ? A_Index * N : Trans - A_Index * N, ahk_id %hWnd%
        Sleep, 10
    }
    if Appear
        WinSet, Transparent, % Trans, ahk_id %hWnd%
    Else
        WinHide, ahk_id %hWnd%
}

WM_LBUTTONDOWN(wp, lp, msg, hWnd)
{
    global ID, Var
    if (hWnd = ID) && (!Var || GetKeyState("Alt"))
        PostMessage, WM_NCLBUTTONDOWN := 0xA1, 2,,, ahk_id %ID%
    SetValue(hWnd, 0)
}

WM_RBUTTONDOWN(wp, lp, msg, hWnd)
{
    SetValue(hWnd, 255)
}

SetValue(hWnd, Pos)
{
    local Control, Text
    if (hWnd != ID3)
        Return
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 3:, % "msctls_trackbar32" SubStr(Control, 7), % Pos
    Gui, 3:Submit, NoHide
    GuiControlGet, Text, 3:, % Control
    %Text%_ := StrLen(Tr := Trans(%Text%, 10, 16)) = 1 ? "0" Tr : Tr
    Gui, 1:Color, % Red_ Green_ Blue_

    MarkerColor := InvertColor(Red_, Green_, Blue_)
    Loop 8
        Control_Colors(Text%a_index%ID, "Set", MarkerColor)

    Gosub, TransSet
}

InvertColor(Red, Green, Blue)
{
    _Red := StrLen(Tr := Trans(Trans(Red, 16, 10) ^ 255, 10, 16)) = 1 ? "0" Tr : Tr
    _Green := StrLen(Tr := Trans(Trans(Green, 16, 10) ^ 255, 10, 16)) = 1 ? "0" Tr : Tr
    _Blue := StrLen(Tr := Trans(Trans(Blue, 16, 10) ^ 255, 10, 16)) = 1 ? "0" Tr : Tr
    Return "0x" _Blue _Green _Red
}


; Пишет секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_WriteSect(Section, Key1, Value1, Key2 = "", Value2 = ""
   , Key3 = "", Value3 = "", Key4 = "", Value4 = "", Key5 = "", Value5 = ""
   , Key6 = "", Value6 = "", Key7 = "", Value7 = "", Key8 = "", Value8 = ""
   , Key9 = "", Value9 = "", Key10 = "", Value10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniWrite, % Value%a_index%, % FileName, % Section, % Key%a_index%
}

; Читает секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_ReadSect(Section, Key1, ByRef var1, Default1 = "", Key2 = "", ByRef var2 = "", Default2 = ""
   , Key3 = "", ByRef var3 = "", Default3 = "", Key4 = "", ByRef var4 = "", Default4 = ""
   , Key5 = "", ByRef var5 = "", Default5 = "", Key6 = "", ByRef var6 = "", Default6 = ""
   , Key7 = "", ByRef var7 = "", Default7 = "", Key8 = "", ByRef var8 = "", Default8 = ""
   , Key9 = "", ByRef var9 = "", Default9 = "", Key10 = "", ByRef var10 = "", Default10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniRead, var%a_index%, % FileName, % Section, % Key%a_index%, % Default%a_index%
}


; Переводит число Number из системы счисления N в систему счисления K. Number должно
; быть написано без префикса, и, если содержит буквенные символы, в кавычках.
; Возвращает значение без префикса.

Trans(Number, N, K)
{
    if N = 10
        Return Trans_Dec(Number, K)
    if K = 10
        Return Trans_ToDec(Number, N)
    Else
        Return Trans_Dec(Trans_ToDec(Number, N), K)
}

Trans_Dec(Number, K)
{
    if K = 16
    {
        SetFormat, integer, hex
        TransNumber := SubStr(Number + 0, 3)
        SetFormat, integer, dec
        Return TransNumber
    }
    if (Number < K)
        Return Number < 10 ? Number : Chr(Asc("A") + Number - 10)
    Mod := Mod(Number,K) < 10 ? Mod(Number,K) : Chr(Asc("A") + Mod(Number,K) - 10)
    Return Trans_Dec(Floor(Number/K),K) . Mod
}

Trans_ToDec(Number, N)
{
    if N = 16
    {
        SetFormat, integer, d
        Number := "0x" . Number
        Return Number + 0
    }
    StringCaseSense on
    if StrLen(Number) = 1
    {
        if Number between a and z
            Number := Asc(Number) - Asc("a") + 10
        if Number between A and Z
            Number := Asc(Number) - Asc("A") + 10
        Return Number
    }
    SubString := SubStr(Number,1,1)
    if SubString between a and z
        SubString := Asc(SubString) - Asc("a") + 10
    if SubString between A and Z
        SubString := Asc(SubString) - Asc("A") + 10
    Return SubString*N**(StrLen(Number)-1) + Trans_ToDec(SubStr(Number,2),N)
}

Convert(sFileFr = "", sFileTo = "")
{
   If sFileTo  =
      sFileTo := A_ScriptDir . "\screen.bmp"
   SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

   If !hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
      Return sFileFr+0 ? SaveHBITMAPToFile(sFileFr
                                                    , sDirTo . "\" . sNameTo . ".bmp") : ""
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

   If !sFileFr
   {
      DllCall("OpenClipboard", "Uint", 0)
      If DllCall("IsClipboardFormatAvailable", "Uint", 2)
                && (hBM:=DllCall("GetClipboardData", "Uint", 2))
        {
         DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0
                , "UintP", pImage)
      }
      DllCall("CloseClipboard")
   }
   Else If (sFileFr Is Integer)
    {
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0
            , "UintP", pImage)
   }
   Else
    {
      DllCall("gdiplus\GdipLoadImageFromFile", "Uint", Unicode4Ansi(wFileFr,sFileFr)
            , "UintP", pImage)
   }

   DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
   VarSetCapacity(ci, nSize)
   DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
   Loop, %nCount%
   {
      If !InStr(Ansi4Unicode(NumGet(ci, 76 * (A_Index - 1) + 44)), "." . sExtTo)
         Continue
      pCodec := &ci + 76 * (A_Index - 1)
         Break
   }

   If pImage
      pCodec ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage
            , "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec
            , "Uint", 0) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pImage
            , "UintP", hBitmap, "Uint", 0) . SetClipboardData(hBitmap)
            , DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

   DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
   DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hFile := DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0
                                                        , "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16
                                                        , "Uint", 6, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint",8, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20)
                                                        , "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
   DllCall("CloseHandle", "Uint", hFile)
}

Unicode4Ansi(ByRef wString, sString)
{
   nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                                        , "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2)
   DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                            , "int", -1, "Uint", &wString, "int", nSize)
   Return   &wString
}

Ansi4Unicode(pString)
{
   nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                            , "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                , "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
   Return   sString
}

SetClipboardData(hBitmap)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hDIB :=   DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
   pDIB :=   DllCall("GlobalLock", "Uint", hDIB)
   DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
   DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
   DllCall("GlobalUnlock", "Uint", hDIB)
   DllCall("DeleteObject", "Uint", hBitmap)
   DllCall("OpenClipboard", "Uint", 0)
   DllCall("EmptyClipboard")
   DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
   DllCall("CloseClipboard")
}

SetCursor(pShape, pCtrl="")
{
   Return SetCursor_(pShape, pCtrl, 0)
}

SetCursor_(wparam, lparam, msg)
{
    global ID
   static WM_SETCURSOR := 0x20, WM_MOUSEMOVE := 0x200
   static HAND := 32649
   static hover, curOld=32512, cursor, ctrls="`n", init

   if !init
      init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"),  OnMessage(WM_MOUSEMOVE, "SetCursor_")

   if A_Gui =
   {
      cursor := DllCall("LoadCursor", "Uint", 0, "Int", %WPARAM%, "Uint")
      ctrls .= lparam "=" cursor "`n"
   }

   If (msg = WM_SETCURSOR)
      ifEqual, hover, 1, Return 1

   if (msg = WM_MOUSEMOVE)
   {
      MouseGetPos,,,ID_Win,c
        if (ID_Win = ID)
            Return
        If j := InStr(ctrls, "`n" c "=")
        {
            hover := true
            j += 2+StrLen(c)
            j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j)-j+1)
            DllCall("SetCursor", "uint",j)
        }
        else DllCall("SetCursor", "uint", curOld), hover := ""
   }
}

Control_Colors(Hwnd, Msg, wParam, lParam = 0)
{
    Thread, Priority, 2147483647

   If !(Hwnd+0) {
     GuiControlGet, nHwnd, Hwnd, %Hwnd%
     Hwnd := nhwnd
   }

   Static OldWinProc := ""          ; origin Windowprocedure
   Static NewWinProc := ""          ; new Windowprocedure
   Static SetValue := "Set"         ; take over Values
   Static Register := "RCB"         ; RegisterCallBack
   Static ValueList := ""           ; Values

   ; Aufruf als Fensterprozedur?
   If (A_EventInfo <> NewWinProc) {
      If (Msg = SetValue) {
         If (RegExMatch(ValueList, "m)^" . (Hwnd +0) . "\|")) {
            ValueList := RegExReplace(ValueList
                                     , "m)^" . (Hwnd + 0) . "\|.*$"
                                     , (Hwnd + 0) . "|"
                                     . (wParam + 0) . "|"
                                     . (lParam + 0))
         } Else {
            ValueList .= (Hwnd + 0) . "|"
                      .  (wParam + 0) . "|"
                      .  (lParam + 0) .  "`r`n"
         }
         Return
      }
      If (Msg = Register) {
         If (NewWinProc = "") {
            NewWinProc := RegisterCallback("Control_Colors","",4)
            OldWinProc := DllCall("SetWindowLong"
                                 , UInt, Hwnd
                                 , Int, -4
                                 , Int, NewWinProc
                                 , UInt)
         }
         Return
      }
      Return
   }
   ; 0x0133 : WM_CTLCOLOREDIT
   ; 0x0138 : WM_CTLCOLORSTATIC
   If (Msg = 0x0133 Or Msg = 0x0135 Or Msg = 0x0138) {
      If (RegExMatch(ValueList, "m)^"
                     . (lParam + 0) . "\|(?P<BG>\d+)\|(?P<TX>\d+)$"
                     , C)) {
         DllCall("SetTextColor", UInt, wParam, UInt, CTX)
         DllCall("SetBkColor", UInt, wParam, UInt, CBG)
         Return, DllCall("CreateSolidBrush", UInt, CBG)
      }
   }
   Return DllCall("CallWindowProcA"
                  , UInt, OldWinProc
                  , UInt, Hwnd
                  , UInt, Msg
                  , UInt, wParam
                  , UInt, lParam)
}

А вот с курсорами:

    #NoEnv
    #UseHook
    OnExit, Exit
    SetWinDelay, 0
    SetBatchLines, -1
    CoordMode, Mouse

    Menu, Tray, Icon, Shell32.dll, 95

    Ini_ReadSect("Color", "Red", Red_, "FF", "Green", Green_, "C7", "Blue", Blue_, "00")
    Ini_ReadSect("Transparent", "Trans", Trans, 130)
    Ini_ReadSect("Extension", "ext", ext, "tif")
    Ini_ReadSect("Out Directory", "OutDirectory", OutDirectory, A_ScriptDir)

    Menu, Extensions, Add, JPG, Extensions
    Menu, Extensions, Add, BMP, Extensions
    Menu, Extensions, Add, TIF, Extensions
    Menu, Extensions, Add, GIF, Extensions
    Menu, Extensions, Add, PNG, Extensions
    Menu, Extensions, Check, %ext%

    Menu, MainMenu, Add, Color – Transparent, Settings
    Menu, MainMenu, Add, Out Directory, OutDirectory
    Menu, MainMenu, Add, Extension, :Extensions
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Exit, GuiClose

    Gui, +LastFound -Caption +AlwaysOnTop +Owner
    WinGet, ID
    WinSet, Transparent, 0
    Gui, Color, % Red_ Green_ Blue_
    Loop 4
        SetCursor("HAND", "Static" a_index)
    Gui, Show, h200 w200

    OnMessage(0x201, "WM_LBUTTONDOWN")
    OnMessage(0x204, "WM_RBUTTONDOWN")

    Hotkey, LButton, WinResize, Off
    Melt(ID, Trans, 1)
    SetTimer, MouseMove, 50

MouseMove:
    S = 10
    MouseGetPos, X_M, Y_M, ID_Win
    if !Move && (ID_Win = ID3)
    {
        RestoreCursors()
        Hotkey, LButton, Off
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    if ((X_M <= X + W) && (X_M > X + W - 2*S) && (Y_M <= Y + H) && (Y_M > Y + H - S))
        || ((X_M <= X + W) && (X_M > X + W - S) && (Y_M <= Y + H) && (Y_M > Y + H - 2*S))
        Var = 1

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M <= Y + H) && (Y_M > Y + H - S))
        || ((X_M < X + S) && (X_M >= X) && (Y_M <= Y + H) && (Y_M > Y + H - 2*S))
        Var = 2

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M < Y + S) && (Y_M >= Y))
        || ((X_M < X + S) && (X_M >= X) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 3

    else if ((X_M <= X + W ) && (X_M > X + W - 2*S) && (Y_M < Y + S) && (Y_M >= Y))
        || ((X_M <= X + W ) && (X_M > X + W - S) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 4

    else if (X_M <= X + W) && (X_M > X + W - S) && (Y_M <= Y + H - S) && (Y_M >= Y + S)
        Var = 5
    else if (X_M <= X + W - S) && (X_M >= X + S) && (Y_M <= Y + H) && (Y_M > Y + H - S)
        Var = 6
    else if (X_M < X + S) && (X_M >= X) && (Y_M <= Y + H - S) && (Y_M >= Y + S)
        Var = 7
    else if (X_M <= X + W - S) && (X_M >= X + S) && (Y_M < Y + S) && (Y_M >= Y)
        Var = 8
    else
        Var =

    if Var
    {
        Hotkey, LButton, On
        if ((Var = 1) || (Var = 3)) && (Cursor != "IDC_SIZENWSE")
            RestoreCursors(), SetSystemCursor("IDC_SIZENWSE"), Cursor := "IDC_SIZENWSE"

        if ((Var = 2) || (Var = 4)) && (Cursor != "IDC_SIZENESW")
            RestoreCursors(), SetSystemCursor("IDC_SIZENESW"), Cursor := "IDC_SIZENESW"

        if ((Var = 5) || (Var = 7)) && (Cursor != "IDC_SIZEWE")
            RestoreCursors(), SetSystemCursor("IDC_SIZEWE"), Cursor := "IDC_SIZEWE"

        if ((Var = 6) || (Var = 8)) && (Cursor != "IDC_SIZENS")
            RestoreCursors(), SetSystemCursor("IDC_SIZENS"), Cursor := "IDC_SIZENS"
    }
    else if !Move
    {
        Hotkey, LButton, Off
        RestoreCursors()
        Cursor =
    }
    Return

WinResize:
    SetTimer, MouseMove, Off
    X_M_Old := X_M, Y_M_Old := Y_M, Move = 1
    While GetKeyState("LButton", "P")
    {
        MouseGetPos, X_M, Y_M
        {
            if Var = 1
                WinMove, ahk_id %ID%,,,, W + X_M - X_M_Old, H + Y_M - Y_M_Old
            if Var = 2
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old,, W - X_M + X_M_Old, H + Y_M - Y_M_Old
            if Var = 3
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old, Y + Y_M - Y_M_Old, W - X_M + X_M_Old
                                                                                                , H - Y_M + Y_M_Old
            if Var = 4
                WinMove, ahk_id %ID%,,, Y + Y_M - Y_M_Old, W + X_M - X_M_Old, H - Y_M + Y_M_Old
            if Var = 5
                WinMove, ahk_id %ID%,,,, W + X_M - X_M_Old
            if Var = 6
                WinMove, ahk_id %ID%,,,,, H + Y_M - Y_M_Old
            if Var = 7
                WinMove, ahk_id %ID%,, X + X_M - X_M_Old,, W - X_M + X_M_Old
            if Var = 8
                WinMove, ahk_id %ID%,,, Y + Y_M - Y_M_Old,, H - Y_M + Y_M_Old
        }
        Sleep, 10
    }
    Move =
    SetTimer, MouseMove, On
    Return

GuiContextMenu:
    Menu, MainMenu, Show
    Return

Extensions:
    Menu, Extensions, UnCheck, %ext%
    StringLower, ext, A_ThisMenuItem
    Menu, Extensions, Check, %ext%
    Return

OutDirectory:
    Gosub, Pause
    FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
    OutDirectory := OutDir ? OutDir : OutDirectory
    Gosub, Pause
    Return

Settings:
    IfWinExist, ahk_id %ID3%
        Goto, 3GuiClose
    Gui, 3:+owner1 +LastFound
    WinGet, ID3
    WinSet, Transparent, 0
    Gui, 3:Color, CCC8C0

    Gui, 3:Font, s9, Arial
    Gui, 3:Add, Text, x11 y17 w29 cRed, Red
    Gui, 3:Add, Text, x10 y47 w30 cGreen, Green
    Gui, 3:Add, Text, x11 y77 w29 cBlue, Blue
    Gui, 3:Add, Text, x10 y107 w30 cWhite, Trans

    Gui, 3:Add, Slider
        , vRed gColorSet x43 y15 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Red_%
    Gui, 3:Add, Slider
        , vGreen gColorSet x43 y45 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Green_%
    Gui, 3:Add, Slider
        , vBlue gColorSet x43 y75 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Blue_%
    Gui, 3:Add, Slider
        , vTrans gTransSet x43 y105 w197 h20 Range0-255 ToolTip AltSubmit, % Trans

    Gui, 3:Add, Button, g3GuiClose x80 y140 w90 h23, OK

    WinGetPos, X, Y, W, H, ahk_id %ID%
    3Gui_Y := (Y + H + 15 + 180 <= A_ScreenHeight) ? Y + H + 15 : Y - 180 - 35
    3Gui_Y := (3Gui_Y < 0) ? 0 : 3Gui_Y
    3Gui_X := (X+(W-250)/2+250 > A_ScreenWidth) ? A_ScreenWidth - 250 : X + (W-256)/2
    3Gui_X := (3Gui_X < 0) ? 0 : 3Gui_X

    GuiControl, 3:Focus, Static1
    Gui, 3:Show, x%3Gui_X% y%3Gui_Y% w250 h180, Color – Transparent
    Melt(ID3, 255, 1)
    Return

ColorSet:
    %A_GuiControl%_ := StrLen(Tr := Trans(%A_GuiControl%, 10, 16)) = 1 ? "0" Tr : Tr
    Gui, 1:Color, % Red_ Green_ Blue_
    Return

TransSet:
    WinSet, Transparent, % Trans, ahk_id %ID%
    Return

3GuiClose:
    Melt(ID3, 255, 0)
    Gui, 3:Destroy
    Return

Exit:
    IfWinExist, ahk_id %ID3%
        Gosub, 3GuiClose
    if !mod
        Melt(ID, Trans, 0)
    Ini_WriteSect("Color", "Red", Red_, "Green", Green_, "Blue", Blue_)
    Ini_WriteSect("Transparent", "Trans", Trans)
    Ini_WriteSect("Extension", "ext", ext)
    Ini_WriteSect("Out Directory", "OutDirectory", OutDirectory)
    RestoreCursors()
    ExitApp

#IfWinExist Color – Transparent ahk_class AutoHotkeyGUI
Esc:: Goto, 3GuiClose

#IfWinExist
PrintScreen::
    IfWinExist, ahk_id %ID%
    {
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0)
        Gui, 2:-Caption +LastFound
        Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
        WinActivate
        Send, !{PrintScreen}
        Gui, 2:Destroy
        Melt(ID, Trans, 1)
    }
    Else
        Send, {PrintScreen}
    Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)
    Return

~!PrintScreen:: Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)

Pause::
    Melt(ID, Trans, mod)
    mod := !mod
    Return

ScrollLock::
    if !mod
        Melt(ID, Trans, 0)
    Gui, Show, % "x" A_ScreenWidth/2 - 103 "y" A_ScreenHeight/2 - 118 "w200 h200"
    Melt(ID, 130, 1), Trans := 130, mod := ""
    GuiControl, 3:, Trans, 130
    Return

Esc::
GuiClose:
    ExitApp

Melt(hWnd, Trans, Appear, N = 20)
{
    WinShow, ahk_id %hWnd%
    While A_Index * N < Trans
    {
        WinSet, Transparent, % Appear ? A_Index * N : Trans - A_Index * N, ahk_id %hWnd%
        Sleep, 10
    }
    if Appear
        WinSet, Transparent, % Trans, ahk_id %hWnd%
    Else
        WinHide, ahk_id %hWnd%
}

WM_LBUTTONDOWN(wp, lp, msg, hwnd)
{
    global ID, Var
    if (hwnd = ID) && (!Var || GetKeyState("Alt"))
        PostMessage, WM_NCLBUTTONDOWN := 0xA1, 2,,, ahk_id %ID%
    SetValue(hwnd, 0)
}

WM_RBUTTONDOWN(wp, lp, msg, hwnd)
{
    SetValue(hwnd, 255)
}

SetValue(hwnd, Pos)
{
    local Control, Text
    if (hwnd != ID3)
        Return
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 3:, % "msctls_trackbar32" SubStr(Control, 7), % Pos
    Gui, 3:Submit, NoHide
    GuiControlGet, Text, 3:, % Control
    %Text%_ := StrLen(Tr := Trans(%Text%, 10, 16)) = 1 ? "0" Tr : Tr
    Gui, 1:Color, % Red_ Green_ Blue_
    Gosub, TransSet
}


; Пишет секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_WriteSect(Section, Key1, Value1, Key2 = "", Value2 = ""
   , Key3 = "", Value3 = "", Key4 = "", Value4 = "", Key5 = "", Value5 = ""
   , Key6 = "", Value6 = "", Key7 = "", Value7 = "", Key8 = "", Value8 = ""
   , Key9 = "", Value9 = "", Key10 = "", Value10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniWrite, % Value%a_index%, % FileName, % Section, % Key%a_index%
}

; Читает секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_ReadSect(Section, Key1, ByRef var1, Default1 = "", Key2 = "", ByRef var2 = "", Default2 = ""
   , Key3 = "", ByRef var3 = "", Default3 = "", Key4 = "", ByRef var4 = "", Default4 = ""
   , Key5 = "", ByRef var5 = "", Default5 = "", Key6 = "", ByRef var6 = "", Default6 = ""
   , Key7 = "", ByRef var7 = "", Default7 = "", Key8 = "", ByRef var8 = "", Default8 = ""
   , Key9 = "", ByRef var9 = "", Default9 = "", Key10 = "", ByRef var10 = "", Default10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniRead, var%a_index%, % FileName, % Section, % Key%a_index%, % Default%a_index%
}


; Переводит число Number из системы счисления N в систему счисления K. Number должно
; быть написано без префикса, и, если содержит буквенные символы, в кавычках.
; Возвращает значение без префикса.

Trans(Number, N, K)
{
    if N = 10
        Return Trans_Dec(Number, K)
    if K = 10
        Return Trans_ToDec(Number, N)
    Else
        Return Trans_Dec(Trans_ToDec(Number, N), K)
}

Trans_Dec(Number, K)
{
    if K = 16
    {
        SetFormat, integer, hex
        TransNumber := SubStr(Number + 0, 3)
        SetFormat, integer, dec
        Return TransNumber
    }
    if (Number < K)
        Return Number < 10 ? Number : Chr(Asc("A") + Number - 10)
    Mod := Mod(Number,K) < 10 ? Mod(Number,K) : Chr(Asc("A") + Mod(Number,K) - 10)
    Return Trans_Dec(Floor(Number/K),K) . Mod
}

Trans_ToDec(Number, N)
{
    if N = 16
    {
        SetFormat, integer, d
        Number := "0x" . Number
        Return Number + 0
    }
    StringCaseSense on
    if StrLen(Number) = 1
    {
        if Number between a and z
            Number := Asc(Number) - Asc("a") + 10
        if Number between A and Z
            Number := Asc(Number) - Asc("A") + 10
        Return Number
    }
    SubString := SubStr(Number,1,1)
    if SubString between a and z
        SubString := Asc(SubString) - Asc("a") + 10
    if SubString between A and Z
        SubString := Asc(SubString) - Asc("A") + 10
    Return SubString*N**(StrLen(Number)-1) + Trans_ToDec(SubStr(Number,2),N)
}


Convert(sFileFr = "", sFileTo = "")
{
   If sFileTo  =
      sFileTo := A_ScriptDir . "\screen.bmp"
   SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

   If !hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
      Return sFileFr+0 ? SaveHBITMAPToFile(sFileFr
                                                    , sDirTo . "\" . sNameTo . ".bmp") : ""
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

   If !sFileFr
   {
      DllCall("OpenClipboard", "Uint", 0)
      If DllCall("IsClipboardFormatAvailable", "Uint", 2)
                && (hBM:=DllCall("GetClipboardData", "Uint", 2))
        {
         DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0
                , "UintP", pImage)
      }
      DllCall("CloseClipboard")
   }
   Else If (sFileFr Is Integer)
    {
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0
            , "UintP", pImage)
   }
   Else
    {
      DllCall("gdiplus\GdipLoadImageFromFile", "Uint", Unicode4Ansi(wFileFr,sFileFr)
            , "UintP", pImage)
   }

   DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
   VarSetCapacity(ci, nSize)
   DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
   Loop,   %nCount%
   {
      If   !InStr(Ansi4Unicode(NumGet(ci, 76 * (A_Index - 1) + 44)), "." . sExtTo)
         Continue
      pCodec := &ci + 76 * (A_Index - 1)
         Break
   }

   If   pImage
      pCodec ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage
            , "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec
            , "Uint", 0) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pImage
            , "UintP", hBitmap, "Uint", 0) . SetClipboardData(hBitmap)
            , DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

   DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
   DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hFile := DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0
                                                        , "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16
                                                        , "Uint", 6, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint",8, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20)
                                                        , "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
   DllCall("CloseHandle", "Uint", hFile)
}

Unicode4Ansi(ByRef wString, sString)
{
   nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                                        , "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2)
   DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                            , "int", -1, "Uint", &wString, "int", nSize)
   Return   &wString
}

Ansi4Unicode(pString)
{
   nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                            , "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                , "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
   Return   sString
}

SetClipboardData(hBitmap)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hDIB :=   DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
   pDIB :=   DllCall("GlobalLock", "Uint", hDIB)
   DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
   DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
   DllCall("GlobalUnlock", "Uint", hDIB)
   DllCall("DeleteObject", "Uint", hBitmap)
   DllCall("OpenClipboard", "Uint", 0)
   DllCall("EmptyClipboard")
   DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
   DllCall("CloseClipboard")
}

SetCursor(pShape, pCtrl="")
{
   return SetCursor_(pShape, pCtrl, 0)
}

SetCursor_(wparam, lparam, msg)
{
    global ID, ID3
   static WM_SETCURSOR := 0x20, WM_MOUSEMOVE := 0x200
   static HAND := 32649
   static hover, curOld=32512, cursor, ctrls="`n", init

   if !init
      init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"),  OnMessage(WM_MOUSEMOVE, "SetCursor_")

   if A_Gui =
   {
      cursor := DllCall("LoadCursor", "Uint", 0, "Int", %WPARAM%, "Uint")
      ctrls .= lparam "=" cursor "`n"
   }

   If (msg = WM_SETCURSOR)
      ifEqual, hover, 1,   return 1

   if (msg = WM_MOUSEMOVE)
   {
      MouseGetPos,,,ID_Win,c
        if (ID_Win = ID)
            Return
        If j := InStr(ctrls, "`n" c "=")
        {
            hover := true
            j += 2+StrLen(c)
            j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j)-j+1)
            DllCall("SetCursor", "uint",j)
        }
        else DllCall("SetCursor", "uint", curOld), hover := ""
   }
}

SetSystemCursor(IDC)
{
    IDC_SIZENWSE = 32642
    IDC_SIZENESW = 32643
    IDC_SIZEWE = 32644
    IDC_SIZENS = 32645
    IDC_ARROW = 32512
    CursorHandle := DllCall( "LoadCursor", Uint, 0, Int, %IDC%, Uint)
    DllCall( "SetSystemCursor", Uint, CursorHandle, Int, IDC_ARROW)
}

RestoreCursors()
{
    SPI_SETCURSORS := 0x57
    DllCall( "SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0 )
}

С курсорами привычнее, но вариант с маркерами более сенситивен. alexii, по Вашему предложению поменял название выходного файла, но без учёта долей секунды, имхо, это лишнее, ведь за одну секунду нельзя сделать несколько снимков (в данной реализации ).
Какой вариант выберем?

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

31

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker пишет:

Здесь не совсем Вас понял, как (на какое) изменить?

Вчера не мог ответить по причине отсутствия телефонной связи. Если вкратце, то мне удалось добиться (не специально, конечно) получения в файле скриншота самого окна выделения. Далее пытаясь смоделировать последовательность действий, ведущих к данному поведению, мне также случайно удалось получить файл скриншота активного окна с наложенным на него окном выделения .

По первому скрипту из предыдущего поста:

Error at line 117.

Line Text: While GetKeyState("LButton", "P")
Error: This line does not contain a recognized action.

По второму:

Error at line 106.

Line Text: While GetKeyState("LButton", "P")
Error: This line does not contain a recognized action.

Это у меня что-то не так? Не разбирался.

teadrinker пишет:

Какой вариант выберем?

Почти по Чехову: «Оба лучше».

32 (изменено: teadrinker, 2009-06-30 11:22:08)

Re: AHK: Сохранить маленький произвольный кусок экрана

Только что скопировал оба варианта и проверил — всё в порядке. Обычно на While ругается, когда версия AHK не последняя, уточните.

alexii пишет:

...мне удалось добиться (не специально, конечно) получения в файле скриншота самого окна выделения. Далее пытаясь смоделировать последовательность действий, ведущих к данному поведению, мне также случайно удалось получить файл скриншота активного окна с наложенным на него окном выделения .

Да, здесь всё так и должно быть. При нажатии Alt + PrintScreen снимается скриншот активного окна. Если было активно окно скрипта (по нему щёлкнули) — получим его скриншот.

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

33

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker пишет:

Обычно на While ругается, когда версия AHK не последняя, уточните.

Вы оказались совершенно правы: обновился до самой свежей версии — заработало .

teadrinker пишет:

Если было активно окно скрипта (по нему щёлкнули) — получим его скриншот.

Вот что я хотел написать (на тутошней машине такое поведение не наблюдается, на прежней машине возможно виноват менеджер окон, так что забьём на это, скорее всего мои местные заморочки; привожу сие только для проформы):

alexii пишет:

Вот это поведение.
а):
* делаем активным окно выделения, перетаскиваем его в нужную позицию над окном X;
* нажимаем PrintScrn, делается активным окно X под окном выделения, получаем нужный скриншот окна X.

б):
* делаем активным окно выделения, перетаскиваем его в нужную позицию над окном X;
* хотим ещё раз поглядеть на окно X — нажимаем Pause — окно выделения скрывается, активным становится окно X;
* нажимаем Pause, окно выделения появляется и делается активным (т.е. визуально всё как и в случае а));
* нажимаем PrintScrn, ожидаем получить скриншот окна X, а получаем скриншот окна выделения.

Так что, всё работает, выкладывайте, коллега, причём хорошо будет именно в варианте «оба» .

P.S. Это специально, что при первом запуске у скриптов разные форматы файлов по умолчанию (.bmp — у первого, .tif — у второго) ?
P.P.S. Памятуя про обновление, проверю-ка я и скрипт из поста #6… Увы, не заработал.

34 (изменено: teadrinker, 2009-06-30 18:36:23)

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

* нажимаем PrintScrn, ожидаем получить скриншот окна X, а получаем скриншот окна выделения.

Очень странно, нажав PrintScrn, можно получить только скриншот части экрана, которая находится непосредственно под окном выделения, ведь сначала оно скрывается, затем только снимается скриншот. Возможно, всё-таки был нажат не PrintScrn, а Alt + PrintScrn?

alexii пишет:

P.S. Это специально, что при первом запуске у скриптов разные форматы файлов по умолчанию (.bmp — у первого, .tif — у второго) ?

Нет, просто по просьбе "заказчицы" сменил на tif в одном варианте, и забыл переделать обратно.

Так понимаю, запостить нужно в эту тему? Кстати, ещё такой момент. В данной теме рассматривается пример сохранения скриншота в файл с помощью Paint, запускаемого скрытым. Я не стал использовать этот алгоритм из-за того, что при снятии скриншота части экрана размер сделанного снимка может оказаться меньше, чем размер (длина-ширина) файла по умолчанию в Paint, и мы получим картинку с белыми полями. Здесь всё правильно, или это только у меня такой глюк?

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

35

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker пишет:

Возможно, всё-таки был нажат не PrintScrn, а Alt + PrintScrn?

Возможно, но я больше грешу на свои локальные глюки, описанные выше. Во всяком случае, здесь и сейчас всё работает.

teadrinker пишет:

Нет, просто по просьбе "заказчицы"

Это святое… .

teadrinker пишет:

Так понимаю, запостить нужно в эту тему?

Думаю, да.

teadrinker пишет:

Кстати, ещё такой момент. В данной теме рассматривается пример сохранения скриншота в файл с помощью Paint, запускаемого скрытым. Я не стал использовать этот алгоритм из-за того, что при снятии скриншота части экрана размер сделанного снимка может оказаться меньше, чем размер (длина-ширина) файла по умолчанию в Paint, и мы получим картинку с белыми полями. Здесь всё правильно, или это только у меня такой глюк?

Да, так и есть. По идее бы, надо сначала \Рисунок\Атибуты\1x1, а потом уже вставка. Но я не уверен, что сие получится проделать в скрытом режиме.

36

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

По идее бы, надо сначала \Рисунок\Атибуты\1x1, а потом уже вставка. Но я не уверен, что сие получится проделать в скрытом режиме.

Я вначале долго и безуспешно пытался это сделать. Возможно, и существуют какие-то ключи у Paint, чтобы он запускался с нужными атрибутами...

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

37

Re: AHK: Сохранить маленький произвольный кусок экрана

Вроде как хранится сие здесь:

REGEDIT4

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View]
"BMPWidth"=dword:00000001
"BMPHeight"=dword:00000001

Ежели предварительно поменять, то при запуске можно попользовать.

38

Re: AHK: Сохранить маленький произвольный кусок экрана

Так может, переписать? Так, вроде, надёжнее будет? А то вот migomigo говорит, что у него (на Висте) ни один мой вариант не работает.

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

39

Re: AHK: Сохранить маленький произвольный кусок экрана

Да сколько их Vist'-то .

40

Re: AHK: Сохранить маленький произвольный кусок экрана

Ладно, я на всякий случай вариант с пайнтом уже делаю...

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

41 (изменено: teadrinker, 2009-06-30 22:03:27)

Re: AHK: Сохранить маленький произвольный кусок экрана

Придумал, как поступить, чтобы работало у всех: сделать, чтобы через меню можно было выбрать способ записи файла — основной (напрямую через WinAPI), и запасной (через Paint). Если первый не сработает, можно попробовать второй. Думаю, как их назвать (эти способы в пунктах меню).

А тогда уж можно и курсоры с маркерами объединить!

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

42 (изменено: teadrinker, 2009-07-02 16:35:48)

Re: AHK: Сохранить маленький произвольный кусок экрана

Проверьте, если работает — буду постить.

    #NoEnv
    #UseHook
    OnExit, Exit
    SetWinDelay, 0
    SetBatchLines, -1
    CoordMode, Mouse

    Menu, Tray, Icon, Shell32.dll, 95

    Ini_ReadSect("Color", "Red", Red_, "FF", "Green", Green_, "C7", "Blue", Blue_, "00")
    Ini_ReadSect("Transparent", "Trans", Trans, 130)
    Ini_ReadSect("Extension", "ext", ext, "bmp")
    Ini_ReadSect("Out Directory", "OutDirectory", OutDirectory, A_ScriptDir)
    Ini_ReadSect("Write Method", "WriteMethod", WriteMethod, "WinApi")
    Ini_ReadSect("Move Method", "MoveMethod", MoveMethod, "Cursors")

    Menu, Extensions, Add, JPG, Extensions
    Menu, Extensions, Add, BMP, Extensions
    Menu, Extensions, Add, TIF, Extensions
    Menu, Extensions, Add, GIF, Extensions
    Menu, Extensions, Add, PNG, Extensions
    Menu, Extensions, Check, %ext%

    Menu, WriteMethod, Add, Via WinApi, WriteMethod
    Menu, WriteMethod, Add, Via Paint, WriteMethod
    Menu, WriteMethod, Check, Via %WriteMethod%

    Menu, MoveMethod, Add, Cursors, MoveMethod
    Menu, MoveMethod, Add, Markers, MoveMethod
    Menu, MoveMethod, Check, %MoveMethod%

    Menu, MainMenu, Add, Color – Transparent, Settings
    Menu, MainMenu, Add, Out Directory, OutDirectory
    Menu, MainMenu, Add, Extension, :Extensions
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Move Method, :MoveMethod
    Menu, MainMenu, Add, Write Method, :WriteMethod
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Exit, GuiClose

    Gui, +LastFound -Caption +AlwaysOnTop +Owner
    WinGet, ID
    WinSet, Transparent, 0
    Gui, Color, % Red_ Green_ Blue_

    Gui, Add, Text, w10 h10 x190 y190 Hidden hwndText1ID
    Gui, Add, Text, w10 h10 x0 y190 Hidden hwndText2ID
    Gui, Add, Text, w10 h10 x0 y0 Hidden hwndText3ID
    Gui, Add, Text, w10 h10 x190 y0 Hidden hwndText4ID
    Gui, Add, Text, w10 h10 x190 y95 Hidden hwndText5ID
    Gui, Add, Text, w10 h10 x95 y190 Hidden hwndText6ID
    Gui, Add, Text, w10 h10 x0 y95 Hidden hwndText7ID
    Gui, Add, Text, w10 h10 x95 y0 Hidden hwndText8ID

    Gosub, MarkerColor
    Control_Colors(ID, "RCB", 0, 0)

    Loop 4
        SetCursor("HAND", "Static" a_index)

    Gui, Show, h200 w200

    OnMessage(0x201, "WM_LBUTTONDOWN")
    OnMessage(0x204, "WM_RBUTTONDOWN")

    Hotkey, LButton, WinResize, Off
    Melt(ID, Trans, 1)
    SetTimer, %MoveMethod%, 50
    Return

Cursors:
    S = 10
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3)
    {
        RestoreCursors()
        Hotkey, LButton, Off
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H
    if ((X_M <= XW) && (X_M > XW - 2*S) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M <= XW) && (X_M > XW - S) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 1

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 2

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 3

    else if ((X_M <= XW ) && (X_M > XW - 2*S) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M <= XW ) && (X_M > XW - S) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 4

    else if (X_M <= XW) && (X_M > XW - S) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 5
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M <= YH) && (Y_M > YH - S)
        Var = 6
    else if (X_M < X + S) && (X_M >= X) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 7
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M < Y + S) && (Y_M >= Y)
        Var = 8
    else
        Var =

    if Var
    {
        Hotkey, LButton, On
        if ((Var = 1) || (Var = 3)) && (Cursor != "IDC_SIZENWSE")
            RestoreCursors(), SetSystemCursor("IDC_SIZENWSE"), Cursor := "IDC_SIZENWSE"

        if ((Var = 2) || (Var = 4)) && (Cursor != "IDC_SIZENESW")
            RestoreCursors(), SetSystemCursor("IDC_SIZENESW"), Cursor := "IDC_SIZENESW"

        if ((Var = 5) || (Var = 7)) && (Cursor != "IDC_SIZEWE")
            RestoreCursors(), SetSystemCursor("IDC_SIZEWE"), Cursor := "IDC_SIZEWE"

        if ((Var = 6) || (Var = 8)) && (Cursor != "IDC_SIZENS")
            RestoreCursors(), SetSystemCursor("IDC_SIZENS"), Cursor := "IDC_SIZENS"
    }
    else
    {
        Hotkey, LButton, Off
        RestoreCursors(), Cursor := ""
    }
    Return

Markers:
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3)
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H

    if (X_M <= XW+ 20) && (X_M >= XW - 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 1

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 2

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 3

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 4

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 5

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 6

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 7

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 8

    else Var =

    if Var
    {
        Hotkey, LButton, On
        GuiControl, Show, Static%Var%
        Loop 8
            if (a_index != Var)
                GuiControl, Hide, Static%a_index%
    }
    else
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
    }
    Return

WinResize:
    SetTimer, %MoveMethod%, Off
    X_M_Old := X_M, Y_M_Old := Y_M
    While GetKeyState("LButton", "P")
    {
        MouseGetPos, X_M, Y_M
        dX := X_M - X_M_Old, dY := Y_M - Y_M_Old
        IfEqual, Var, 1, WinMove, ahk_id %ID%,,,, W + dX, H + dY
        IfEqual, Var, 2, WinMove, ahk_id %ID%,, X + dX,, W - dX, H + dY
        IfEqual, Var, 3, WinMove, ahk_id %ID%,, X + dX, Y + dY, W - dX, H - dY
        IfEqual, Var, 4, WinMove, ahk_id %ID%,,, Y + dY, W + dX, H - dY
        IfEqual, Var, 5, WinMove, ahk_id %ID%,,,, W + dX
        IfEqual, Var, 6, WinMove, ahk_id %ID%,,,,, H + dY
        IfEqual, Var, 7, WinMove, ahk_id %ID%,, X + dX,, W - dX
        IfEqual, Var, 8, WinMove, ahk_id %ID%,,, Y + dY,, H - dY
        Sleep, 10
    }
    SetTimer, %MoveMethod%, On
    Return

GuiSize:
    GuiControl, Move, Static1, % "x" A_GuiWidth - 10 "y" A_GuiHeight - 10
    GuiControl, Move, Static2, % "x0 y" A_GuiHeight - 10
    GuiControl, Move, Static3, % "x0 y0"
    GuiControl, Move, Static4, % "x" A_GuiWidth - 10 "y0"
    GuiControl, Move, Static5, % "x" A_GuiWidth - 10 "y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static6, % "x" (A_GuiWidth - 10)/2 "y" A_GuiHeight - 10
    GuiControl, Move, Static7, % "x0 y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static8, % "x" (A_GuiWidth - 10)/2 "y0"
    Return

GuiContextMenu:
    RestoreCursors()
    Menu, MainMenu, Show
    Return

Extensions:
    Menu, Extensions, UnCheck, %ext%
    StringLower, ext, A_ThisMenuItem
    Menu, Extensions, Check, %ext%
    Return

OutDirectory:
    Gosub, Pause
    FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
    OutDirectory := OutDir ? OutDir : OutDirectory
    Gosub, Pause
    Return

MoveMethod:
    Menu, MoveMethod, UnCheck, %MoveMethod%
    SetTimer, %MoveMethod%, Off
    MoveMethod := A_ThisMenuItem
    Menu, MoveMethod, Check, %MoveMethod%
    Loop 8
        GuiControl, Hide, Static%a_index%
    SetTimer, %MoveMethod%, 50
    RestoreCursors()
    Return

WriteMethod:
    Menu, WriteMethod, UnCheck, Via %WriteMethod%
    WriteMethod := SubStr(A_ThisMenuItem, 5)
    Menu, WriteMethod, Check, Via %WriteMethod%
    Return

Settings:
    IfWinExist, ahk_id %ID3%
        Goto, 3GuiClose
    Gui, 3:+owner1 +LastFound
    WinGet, ID3
    WinSet, Transparent, 0
    Gui, 3:Color, CCC8C0

    Gui, 3:Font, s9, Arial
    Gui, 3:Add, Text, x11 y17 w29 cRed, Red
    Gui, 3:Add, Text, x10 y47 w30 cGreen, Green
    Gui, 3:Add, Text, x11 y77 w29 cBlue, Blue
    Gui, 3:Add, Text, x10 y107 w30 cWhite, Trans

    Gui, 3:Add, Slider
        , vRed gColorSet x43 y15 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Red_%
    Gui, 3:Add, Slider
        , vGreen gColorSet x43 y45 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Green_%
    Gui, 3:Add, Slider
        , vBlue gColorSet x43 y75 w197 h20 Range0-255 ToolTip AltSubmit, 0x%Blue_%
    Gui, 3:Add, Slider
        , vTrans gTransSet x43 y105 w197 h20 Range0-255 ToolTip AltSubmit, % Trans

    Gui, 3:Add, Button, g3GuiClose x80 y140 w90 h23, OK

    WinGetPos, X, Y, W, H, ahk_id %ID%
    3Gui_Y := (Y + H + 15 + 180 <= A_ScreenHeight) ? Y + H + 15 : Y - 180 - 35
    3Gui_Y := (3Gui_Y < 0) ? 0 : 3Gui_Y
    3Gui_X := (X+(W-250)/2+250 > A_ScreenWidth) ? A_ScreenWidth - 250 : X + (W-256)/2
    3Gui_X := (3Gui_X < 0) ? 0 : 3Gui_X

    GuiControl, 3:Focus, Static1
    Gui, 3:Show, x%3Gui_X% y%3Gui_Y% w250 h180, Color – Transparent
    Melt(ID3, 255, 1)
    Return

ColorSet:
    %A_GuiControl%_ := SubStr("00" . Trans(%A_GuiControl%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

MarkerColor:
    MarkerColor := InvertColor(Red_, Green_, Blue_)
    Loop 8
        Control_Colors(Text%a_index%ID, "Set", MarkerColor)
    Return

TransSet:
    WinSet, Transparent, % Trans, ahk_id %ID%
    Return

3GuiClose:
    Melt(ID3, 255, 0)
    Gui, 3:Destroy
    Return

Exit:
    IfWinExist, ahk_id %ID3%
        Gosub, 3GuiClose
    if !mod
        Melt(ID, Trans, 0)
    Ini_WriteSect("Color", "Red", Red_, "Green", Green_, "Blue", Blue_)
    Ini_WriteSect("Transparent", "Trans", Trans)
    Ini_WriteSect("Extension", "ext", ext)
    Ini_WriteSect("Out Directory", "OutDirectory", OutDirectory)
    Ini_WriteSect("Write Method", "WriteMethod", WriteMethod)
    Ini_WriteSect("Move Method", "MoveMethod", MoveMethod)

    RestoreCursors()
    ExitApp

#IfWinExist Color – Transparent ahk_class AutoHotkeyGUI
Esc:: Goto, 3GuiClose

#IfWinExist
PrintScreen::
    IfWinExist, ahk_id %ID%
    {
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0, 50)
        Gui, 2:-Caption +LastFound
        Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
        WinActivate
        Send, !{PrintScreen}
        Gui, 2:Destroy
        Melt(ID, Trans, 1, 50)
    }
    Else
        Send, {PrintScreen}

WriteFile:
    IfNotExist, % OutDirectory
        OutDirectory := A_ScriptDir
    if WriteMethod = Paint
        SaveBufferToFileViaPaint(OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)
    else
        Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)
    Return

~!PrintScreen:: Goto, WriteFile

Pause:: Melt(ID, Trans, mod), mod := !mod

ScrollLock::
    if !mod
        Melt(ID, Trans, 0)
    Gui, Show, % "x" A_ScreenWidth/2 - 103 "y" A_ScreenHeight/2 - 118 "w200 h200"
    Melt(ID, 130, 1), Trans := 130, mod := ""
    GuiControl, 3:, Trans, 130
    Return

Esc::
GuiClose:
    ExitApp

Melt(hWnd, Trans, Appear, N = 20)
{
    WinShow, ahk_id %hWnd%
    While A_Index * N < Trans
    {
        WinSet, Transparent, % Appear ? A_Index * N : Trans - A_Index * N, ahk_id %hWnd%
        Sleep, 10
    }
    if Appear
        WinSet, Transparent, % Trans, ahk_id %hWnd%
    Else
        WinHide, ahk_id %hWnd%
}

WM_LBUTTONDOWN(wp, lp, msg, hwnd)
{
    global ID, Var
    if (hwnd = ID) && (!Var || GetKeyState("Alt"))
        PostMessage, WM_NCLBUTTONDOWN := 0xA1, 2,,, ahk_id %ID%
    SetValue(hwnd, 0)
}

WM_RBUTTONDOWN(wp, lp, msg, hwnd)
{
    SetValue(hwnd, 255)
}

SetValue(hwnd, Pos)
{
    local Control, Text
    if (hwnd != ID3)
        Return
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 3:, % "msctls_trackbar32" SubStr(Control, 7), % Pos
    Gui, 3:Submit, NoHide
    GuiControlGet, Text, 3:, % Control
    %Text%_ := SubStr("00" . Trans(%Text%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

    Gosub, MarkerColor
    Gosub, TransSet
}

InvertColor(Red, Green, Blue)
{
    _Red := SubStr("00" . Trans(Trans(Red, 16, 10) ^ 255, 10, 16), -1)
    _Green := SubStr("00" . Trans(Trans(Green, 16, 10) ^ 255, 10, 16), -1)
    _Blue := SubStr("00" . Trans(Trans(Blue, 16, 10) ^ 255, 10, 16), -1)
    Return "0x" _Blue _Green _Red
}


; Пишет секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_WriteSect(Section, Key1, Value1, Key2 = "", Value2 = ""
   , Key3 = "", Value3 = "", Key4 = "", Value4 = "", Key5 = "", Value5 = ""
   , Key6 = "", Value6 = "", Key7 = "", Value7 = "", Key8 = "", Value8 = ""
   , Key9 = "", Value9 = "", Key10 = "", Value10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniWrite, % Value%a_index%, % FileName, % Section, % Key%a_index%
}

; Читает секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_ReadSect(Section, Key1, ByRef var1, Default1 = "", Key2 = "", ByRef var2 = "", Default2 = ""
   , Key3 = "", ByRef var3 = "", Default3 = "", Key4 = "", ByRef var4 = "", Default4 = ""
   , Key5 = "", ByRef var5 = "", Default5 = "", Key6 = "", ByRef var6 = "", Default6 = ""
   , Key7 = "", ByRef var7 = "", Default7 = "", Key8 = "", ByRef var8 = "", Default8 = ""
   , Key9 = "", ByRef var9 = "", Default9 = "", Key10 = "", ByRef var10 = "", Default10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniRead, var%a_index%, % FileName, % Section, % Key%a_index%, % Default%a_index%
}


; Переводит число Number из системы счисления N в систему счисления K. Number должно
; быть написано без префикса, и, если содержит буквенные символы, в кавычках.
; Возвращает значение без префикса.

Trans(Number, N, K)
{
    if N = 10
        Return Trans_Dec(Number, K)
    if K = 10
        Return Trans_ToDec(Number, N)
    Else
        Return Trans_Dec(Trans_ToDec(Number, N), K)
}

Trans_Dec(Number, K)
{
    if K = 16
    {
        SetFormat, integer, hex
        TransNumber := SubStr(Number + 0, 3)
        SetFormat, integer, dec
        Return TransNumber
    }
    if (Number < K)
        Return Number < 10 ? Number : Chr(Asc("A") + Number - 10)
    Mod := Mod(Number,K) < 10 ? Mod(Number,K) : Chr(Asc("A") + Mod(Number,K) - 10)
    Return Trans_Dec(Floor(Number/K),K) . Mod
}

Trans_ToDec(Number, N)
{
    if N = 16
    {
        SetFormat, integer, d
        Number := "0x" . Number
        Return Number + 0
    }
    StringCaseSense on
    if StrLen(Number) = 1
    {
        if Number between a and z
            Number := Asc(Number) - Asc("a") + 10
        if Number between A and Z
            Number := Asc(Number) - Asc("A") + 10
        Return Number
    }
    SubString := SubStr(Number,1,1)
    if SubString between a and z
        SubString := Asc(SubString) - Asc("a") + 10
    if SubString between A and Z
        SubString := Asc(SubString) - Asc("A") + 10
    Return SubString*N**(StrLen(Number)-1) + Trans_ToDec(SubStr(Number,2),N)
}

Convert(sFileFr = "", sFileTo = "")
{
   If sFileTo  =
      sFileTo := A_ScriptDir . "\screen.bmp"
   SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

   If !hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
      Return sFileFr+0 ? SaveHBITMAPToFile(sFileFr
                                                    , sDirTo . "\" . sNameTo . ".bmp") : ""
   VarSetCapacity(si, 16, 0), si := Chr(1)
   DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

   If !sFileFr
   {
      DllCall("OpenClipboard", "Uint", 0)
      If DllCall("IsClipboardFormatAvailable", "Uint", 2)
                && (hBM:=DllCall("GetClipboardData", "Uint", 2))
        {
         DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0
                , "UintP", pImage)
      }
      DllCall("CloseClipboard")
   }
   Else If (sFileFr Is Integer)
    {
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0
            , "UintP", pImage)
   }
   Else
    {
      DllCall("gdiplus\GdipLoadImageFromFile", "Uint", Unicode4Ansi(wFileFr,sFileFr)
            , "UintP", pImage)
   }

   DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
   VarSetCapacity(ci, nSize)
   DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
   Loop,   %nCount%
   {
      If   !InStr(Ansi4Unicode(NumGet(ci, 76 * (A_Index - 1) + 44)), "." . sExtTo)
         Continue
      pCodec := &ci + 76 * (A_Index - 1)
         Break
   }

   If   pImage
      pCodec ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage
            , "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec
            , "Uint", 0) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Uint", pImage
            , "UintP", hBitmap, "Uint", 0) . SetClipboardData(hBitmap)
            , DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

   DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
   DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hFile := DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0
                                                        , "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16
                                                        , "Uint", 6, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint",8, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
   DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20)
                                                        , "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
   DllCall("CloseHandle", "Uint", hFile)
}

Unicode4Ansi(ByRef wString, sString)
{
   nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                                        , "int", -1, "Uint", 0, "int", 0)
   VarSetCapacity(wString, nSize * 2)
   DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                            , "int", -1, "Uint", &wString, "int", nSize)
   Return   &wString
}

Ansi4Unicode(pString)
{
   nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                            , "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
   VarSetCapacity(sString, nSize)
   DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                , "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
   Return   sString
}

SetClipboardData(hBitmap)
{
   DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
   hDIB :=   DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
   pDIB :=   DllCall("GlobalLock", "Uint", hDIB)
   DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
   DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
   DllCall("GlobalUnlock", "Uint", hDIB)
   DllCall("DeleteObject", "Uint", hBitmap)
   DllCall("OpenClipboard", "Uint", 0)
   DllCall("EmptyClipboard")
   DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
   DllCall("CloseClipboard")
}

SaveBufferToFileViaPaint(FilePath)
{
    Critical
    WM_COMMAND = 0x111

    RegRead, BMPHeight_Old, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPHeight
    RegRead, BMPWidth_Old, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth

    if (BMPHeight_Old = "") || (BMPWidth_Old = "")
    {
        MsgBox, 16, Error!, Ошибка чтения реестра!, 2
        Return
    }

    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPHeight, 1
    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth, 1

    DetectHiddenWindows, On
    FileAppend,, %FilePath%
    Run, mspaint "%FilePath%",, Hide
    SplitPath, FilePath, OutFileName
    WinWait, %OutFileName% - Paint

    ;команда меню "Правка" - "Вставить"
    PostMessage, WM_COMMAND, 57637

    ;команда меню "Файл" - "Сохранить"
    PostMessage, WM_COMMAND, 57603

    WinClose

    WinWaitClose,,, 1
    if ErrorLevel
        mb = 1

    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View,BMPHeight,%BMPHeight_Old%
    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth, %BMPWidth_Old%

    if mb
    {
        WinShow
        MsgBox, 48, Error!, Ошибка работы с mspaint.exe!, 2
    }
}

SetCursor(pShape, pCtrl="")
{
    return SetCursor_(pShape, pCtrl, 0)
}

SetCursor_(wparam, lparam, msg)
{
    global ID, ID3
    static WM_SETCURSOR := 0x20, WM_MOUSEMOVE := 0x200
    static HAND := 32649
    static hover, curOld=32512, cursor, ctrls="`n", init

    if !init
        init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"), OnMessage(WM_MOUSEMOVE, "SetCursor_")

    if A_Gui =
    {
        cursor := DllCall("LoadCursor", "Uint", 0, "Int", %WPARAM%, "Uint")
        ctrls .= lparam "=" cursor "`n"
    }

    If (msg = WM_SETCURSOR)
        ifEqual, hover, 1, return 1

    if (msg = WM_MOUSEMOVE)
    {
        MouseGetPos,,, ID_Win, Control
        if (ID_Win = ID)
            Return
        If j := InStr(ctrls, "`n" Control "=")
        {
            hover := true
            j += 2+StrLen(Control)
            j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j)-j+1)
            DllCall("SetCursor", "uint",j)
        }
        else DllCall("SetCursor", "uint", curOld), hover := ""
    }
}

SetSystemCursor(IDC)
{
    IDC_SIZENWSE = 32642
    IDC_SIZENESW = 32643
    IDC_SIZEWE = 32644
    IDC_SIZENS = 32645
    IDC_ARROW = 32512
    CursorHandle := DllCall( "LoadCursor", Uint, 0, Int, %IDC%, Uint)
    DllCall( "SetSystemCursor", Uint, CursorHandle, Int, IDC_ARROW)
}

RestoreCursors()
{
   SPI_SETCURSORS := 0x57
   DllCall( "SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0 )
}


Control_Colors(Hwnd, Msg, wParam, lParam = 0)
{
    Thread, Priority, 2147483647

    If !(Hwnd+0) {
        GuiControlGet, nHwnd, Hwnd, %Hwnd%
        Hwnd := nhwnd
   }

   Static OldWinProc := ""          ; origin Windowprocedure
   Static NewWinProc := ""          ; new Windowprocedure
   Static SetValue := "Set"         ; take over Values
   Static Register := "RCB"         ; RegisterCallBack
   Static ValueList := ""           ; Values

   If (A_EventInfo <> NewWinProc) {
      If (Msg = SetValue) {
         If (RegExMatch(ValueList, "m)^" . (Hwnd +0) . "\|")) {
            ValueList := RegExReplace(ValueList
                                     , "m)^" . (Hwnd + 0) . "\|.*$"
                                     , (Hwnd + 0) . "|"
                                     . (wParam + 0) . "|"
                                     . (lParam + 0))
         } Else {
            ValueList .= (Hwnd + 0) . "|"
                      .  (wParam + 0) . "|"
                      .  (lParam + 0) .  "`r`n"
         }
         Return
      }
      If (Msg = Register) {
         If (NewWinProc = "") {
            NewWinProc := RegisterCallback("Control_Colors","",4)
            OldWinProc := DllCall("SetWindowLong"
                                 , UInt, Hwnd
                                 , Int, -4
                                 , Int, NewWinProc
                                 , UInt)
         }
         Return
      }
      Return
   }
   ; 0x0133 : WM_CTLCOLOREDIT
   ; 0x0138 : WM_CTLCOLORSTATIC
   If (Msg = 0x0133 Or Msg = 0x0135 Or Msg = 0x0138) {
      If (RegExMatch(ValueList, "m)^"
                     . (lParam + 0) . "\|(?P<BG>\d+)\|(?P<TX>\d+)$"
                     , C)) {
         DllCall("SetTextColor", UInt, wParam, UInt, CTX)
         DllCall("SetBkColor", UInt, wParam, UInt, CBG)
         Return, DllCall("CreateSolidBrush", UInt, CBG)
      }
   }
   Return DllCall("CallWindowProcA"
                  , UInt, OldWinProc
                  , UInt, Hwnd
                  , UInt, Msg
                  , UInt, wParam
                  , UInt, lParam)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

43

Re: AHK: Сохранить маленький произвольный кусок экрана

Error at line 188.

Line Text: While GetKeyState("LButton", "P")
Error: This line does not contain a recognized action.

The program will exit.

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

44 (изменено: teadrinker, 2009-07-01 16:22:45)

Re: AHK: Сохранить маленький произвольный кусок экрана

#32, #33, While-loop
The gray Cardinal, от тебя-то не ожидал!

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

45

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker
Ага, старая . Сейчас обновлю (я не следил за этой темой).

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

46

Re: AHK: Сохранить маленький произвольный кусок экрана

На всякий случай, описание работы здесь.

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

47

Re: AHK: Сохранить маленький произвольный кусок экрана

Кажется, всё работает.
teadrinker, браво . SnagIt отдыхает .

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

48

Re: AHK: Сохранить маленький произвольный кусок экрана

А возможно ли сохранение через Paint в других форматах? У меня IrfanView потом заругался на JPG, что это BMP с неправильным расширением и предложил переименовать.

49 (изменено: teadrinker, 2009-07-02 16:37:12)

Re: AHK: Сохранить маленький произвольный кусок экрана

YMP пишет:

А возможно ли сохранение через Paint в других форматах? У меня IrfanView потом заругался на JPG, что это BMP с неправильным расширением и предложил переименовать.

У меня, во всяком случае, получается!
Немного подредактировал код. Для коллекции, возможно, оформлю завтра.

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

50

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker пишет:

У меня, во всяком случае, получается!

А что именно? Я имел в виду не через меню самого Paint'a, а твоим скриптом с использованием Paint'a. У меня вот что получается:

---------------------------
IrfanView
---------------------------
Внимание!
"C:\TEMP\AHK\20090703-085057.jpg" -- это BMP-файл с неправильным расширением!
Переименовать?
---------------------------
Да   Нет   
---------------------------

Внимание!
"C:\TEMP\AHK\20090703-085145.tif" -- это BMP-файл с неправильным расширением!
Переименовать?

Внимание!
"C:\TEMP\AHK\20090703-085326.gif" -- это BMP-файл с неправильным расширением!
Переименовать?

Внимание!
"C:\TEMP\AHK\20090703-085303.png" -- это BMP-файл с неправильным расширением!
Переименовать?

51

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker, у меня тоже при выборе \Write method\Via Paint получаeтся внутренний формат «.bmp» при различных расширениях. Естественно, что и файлы совершенно идентичные, различаются только расширением.

52

Re: AHK: Сохранить маленький произвольный кусок экрана

Понял, посмотрю.

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

53 (изменено: teadrinker, 2009-07-07 01:27:23)

Re: AHK: Сохранить маленький произвольный кусок экрана

Действительно, оказалось, Paint по данному алгоритму может создавать только bmp-файлы. Сделал так, что когда расширение другое, то Paint (при выборе "Via Paint") сначала создаёт bmp-файл в директории A_Temp, затем он конвертируется в файл с нужным расширением с помощью функции из первого способа и удаляется. Неизвестно, будет ли работать такой вариант у тех, у кого первый способ не работал. Надо спросить у migomigo.
Появилась возможность указывать качество (степень сжатия) JPEG.

    #NoEnv
    #UseHook
    OnExit, Exit
    SetWinDelay, 0
    SetBatchLines, -1
    CoordMode, Mouse

    Menu, Tray, Icon, Shell32.dll, 95

    Ini_ReadSect("Color", "Red", Red_, "FF", "Green", Green_, "C7", "Blue", Blue_, "00")
    Ini_ReadSect("Transparent", "Trans", Trans, 130)
    Ini_ReadSect("Extension", "ext", ext, "bmp")
    Ini_ReadSect("Out Directory", "OutDirectory", OutDirectory, A_ScriptDir)
    Ini_ReadSect("Write Method", "WriteMethod", WriteMethod, "WinApi")
    Ini_ReadSect("Resize Pointers", "ResizePointers", ResizePointers, "Cursors")
    Ini_ReadSect("Quality JPG", "Quality", Quality, 100)

    Menu, ResizePointers, Add, Cursors, ResizePointers
    Menu, ResizePointers, Add, Markers, ResizePointers
    Menu, ResizePointers, Check, %ResizePointers%

    Menu, WriteMethod, Add, Via WinApi, WriteMethod
    Menu, WriteMethod, Add, Via Paint, WriteMethod
    Menu, WriteMethod, Check, Via %WriteMethod%

    Menu, OutDirectory, Add, % OutDirectory, OutDirectory

    Menu, Quality, Add, Quality = %Quality%`%, QualityOK
    Menu, Quality, Add, Change Quality, SetQuality

    Menu, Extensions, Add, JPG, :Quality
    Menu, Extensions, Add, BMP, Extensions
    Menu, Extensions, Add, TIF, Extensions
    Menu, Extensions, Add, GIF, Extensions
    Menu, Extensions, Add, PNG, Extensions
    Menu, Extensions, Check, %ext%

    Menu, MainMenu, Add, Color – Transparent, Settings
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Resize Pointers, :ResizePointers
    Menu, MainMenu, Add, Write Method, :WriteMethod
    Menu, MainMenu, Add, Out Directory, :OutDirectory
    Menu, MainMenu, Add, Extension, :Extensions
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Exit, GuiClose

    Gui, +LastFound -Caption +AlwaysOnTop +Owner
    WinGet, ID
    WinSet, Transparent, 0
    Gui, Color, % Red_ Green_ Blue_

    Locations = x190 y190|x0 y190|x0 y0|x190 y0|190 y95|x95 y190|x0 y95|x95 y0
    StringSplit, Location, Locations,|
    Loop 8
        Gui, Add, Text, % "w10 h10 Hidden hwndText" a_index "ID " Location%a_index%

    Gosub, MarkerColor
    Control_Colors(ID, "RCB", 0, 0)

    Loop 4
        SetCursor("IDC_HAND", "Static" a_index)

    Gui, Show, h200 w200

    OnMessage(0x201, "WM_LBUTTONDOWN")
    OnMessage(0x204, "WM_RBUTTONDOWN")

    Hotkey, LButton, WinResize, Off
    Melt(ID, Trans, 1)
    SetTimer, %ResizePointers%, 50
    Return

Cursors:
    S = 10
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3) || (ID_Win = ID4)
    {
        RestoreCursors()
        Hotkey, LButton, Off
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H
    if ((X_M <= XW) && (X_M > XW - 2*S) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M <= XW) && (X_M > XW - S) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 1

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 2

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 3

    else if ((X_M <= XW ) && (X_M > XW - 2*S) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M <= XW ) && (X_M > XW - S) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 4

    else if (X_M <= XW) && (X_M > XW - S) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 5
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M <= YH) && (Y_M > YH - S)
        Var = 6
    else if (X_M < X + S) && (X_M >= X) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 7
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M < Y + S) && (Y_M >= Y)
        Var = 8
    else
        Var =

    if Var
    {
        Hotkey, LButton, On
        if ((Var = 1) || (Var = 3)) && (Cursor != "IDC_SIZENWSE")
            RestoreCursors(), SetSystemCursor("IDC_SIZENWSE"), Cursor := "IDC_SIZENWSE"

        if ((Var = 2) || (Var = 4)) && (Cursor != "IDC_SIZENESW")
            RestoreCursors(), SetSystemCursor("IDC_SIZENESW"), Cursor := "IDC_SIZENESW"

        if ((Var = 5) || (Var = 7)) && (Cursor != "IDC_SIZEWE")
            RestoreCursors(), SetSystemCursor("IDC_SIZEWE"), Cursor := "IDC_SIZEWE"

        if ((Var = 6) || (Var = 8)) && (Cursor != "IDC_SIZENS")
            RestoreCursors(), SetSystemCursor("IDC_SIZENS"), Cursor := "IDC_SIZENS"
    }
    else
    {
        Hotkey, LButton, Off
        RestoreCursors(), Cursor := ""
    }
    Return

Markers:
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3) || (ID_Win = ID4)
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H

    if (X_M <= XW+ 20) && (X_M >= XW - 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 1

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 2

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 3

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 4

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 5

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 6

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 7

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 8

    else Var =

    if Var
    {
        Hotkey, LButton, On
        GuiControl, Show, Static%Var%
        Loop 8
            if (a_index != Var)
                GuiControl, Hide, Static%a_index%
    }
    else
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
    }
    Return

WinResize:
    SetTimer, %ResizePointers%, Off
    X_M_Old := X_M, Y_M_Old := Y_M
    While GetKeyState("LButton", "P")
    {
        MouseGetPos, X_M, Y_M
        dX := X_M - X_M_Old, dY := Y_M - Y_M_Old
        IfEqual, Var, 1, WinMove, ahk_id %ID%,,,, W + dX, H + dY
        IfEqual, Var, 2, WinMove, ahk_id %ID%,, X + dX,, W - dX, H + dY
        IfEqual, Var, 3, WinMove, ahk_id %ID%,, X + dX, Y + dY, W - dX, H - dY
        IfEqual, Var, 4, WinMove, ahk_id %ID%,,, Y + dY, W + dX, H - dY
        IfEqual, Var, 5, WinMove, ahk_id %ID%,,,, W + dX
        IfEqual, Var, 6, WinMove, ahk_id %ID%,,,,, H + dY
        IfEqual, Var, 7, WinMove, ahk_id %ID%,, X + dX,, W - dX
        IfEqual, Var, 8, WinMove, ahk_id %ID%,,, Y + dY,, H - dY
        Sleep, 10
    }
    SetTimer, %ResizePointers%, On
    Return

GuiSize:
    GuiControl, Move, Static1, % "x" A_GuiWidth - 10 "y" A_GuiHeight - 10
    GuiControl, Move, Static2, % "x0 y" A_GuiHeight - 10
    GuiControl, Move, Static3, % "x0 y0"
    GuiControl, Move, Static4, % "x" A_GuiWidth - 10 "y0"
    GuiControl, Move, Static5, % "x" A_GuiWidth - 10 "y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static6, % "x" (A_GuiWidth - 10)/2 "y" A_GuiHeight - 10
    GuiControl, Move, Static7, % "x0 y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static8, % "x" (A_GuiWidth - 10)/2 "y0"
    Return

GuiContextMenu:
    RestoreCursors()
    Menu, MainMenu, Show
    Return

QualityOK:
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
    Return

SetQuality:
    Old_Quality := Quality
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
    IfWinExist, ahk_id %ID4%
        Goto, 4GuiClose
    Gui, 4:+owner1 +LastFound
    WinGet, ID4
    WinSet, Transparent, 0
    Gui, 4:Color, CCC8C0
    Gui, 4:Font, s9, Arial
    Gui, 4:Add, Text, x11 y17 w29 cBlue, Quality:
    Gui, 4:Add, Slider, vQSlider gQualitySet x58 y15 w182 h25 ToolTip AltSubmit, % Quality
    Gui, 4:Add, Button, gQOk x80 y50 w90 h23, OK
    XQ := X_M - 260 < 0 ? 0 : X_M - 260, YQ := Y_M - 105 < 0 ? 0 : Y_M - 105
    Gui, 4:Show, x%XQ% y%YQ% w250 h85, Quality of JPEG
    Melt(ID4, 255, 1)
    Return

QualitySet:
    Quality := QSlider
    Return

QOk:
    WinClose, ahk_id %ID4%
    Return

4GuiClose:
    if (Quality != Old_Quality)
        Menu, Quality, Rename, Quality = %Old_Quality%`%, Quality = %Quality%`%
    Melt(ID4, 255, 0)
    Gui, 4:Destroy
    Return

Extensions:
    Menu, Extensions, UnCheck, %ext%
    StringLower, ext, A_ThisMenuItem
    Menu, Extensions, Check, %ext%
    Return

OutDirectory:
    Old_OutDirectory := OutDirectory
    Gosub, Pause
    FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
    OutDirectory := OutDir ? OutDir : OutDirectory
    if (OutDirectory != Old_OutDirectory)
        Menu, OutDirectory, Rename, %Old_OutDirectory%, %OutDirectory%
    Gosub, Pause
    Return

ResizePointers:
    Menu, ResizePointers, UnCheck, %ResizePointers%
    SetTimer, %ResizePointers%, Off
    ResizePointers := A_ThisMenuItem
    Menu, ResizePointers, Check, %ResizePointers%
    Loop 8
        GuiControl, Hide, Static%a_index%
    SetTimer, %ResizePointers%, 50
    RestoreCursors()
    Return

WriteMethod:
    Menu, WriteMethod, UnCheck, Via %WriteMethod%
    WriteMethod := SubStr(A_ThisMenuItem, 5)
    Menu, WriteMethod, Check, Via %WriteMethod%
    Return

Settings:
    IfWinExist, ahk_id %ID3%
        Goto, 3GuiClose
    Gui, 3:+owner1 +LastFound
    WinGet, ID3
    WinSet, Transparent, 0
    Gui, 3:Color, CCC8C0

    Gui, 3:Font, s9, Arial
    Gui, 3:Add, Text, x11 y17 w29 cRed, Red
    Gui, 3:Add, Text, x10 y47 w30 cGreen, Green
    Gui, 3:Add, Text, x11 y77 w29 cBlue, Blue
    Gui, 3:Add, Text, x10 y107 w30 cWhite, Trans

    Options = gColorSet x43 w197 h20 Range0-255 ToolTip AltSubmit
    Gui, 3:Add, Slider, vRed %Options% y15, 0x%Red_%
    Gui, 3:Add, Slider, vGreen %Options% y45, 0x%Green_%
    Gui, 3:Add, Slider, vBlue %Options% y75, 0x%Blue_%
    Gui, 3:Add, Slider, vTrans %Options% gTransSet y105, % Trans

    Gui, 3:Add, Button, g3GuiClose x80 y140 w90 h23, OK

    WinGetPos, X, Y, W, H, ahk_id %ID%
    3Gui_Y := (Y + H + 15 + 180 <= A_ScreenHeight) ? Y + H + 15 : Y - 180 - 35
    3Gui_Y := (3Gui_Y < 0) ? 0 : 3Gui_Y
    3Gui_X := (X+(W-250)/2+250 > A_ScreenWidth) ? A_ScreenWidth - 250 : X + (W-256)/2
    3Gui_X := (3Gui_X < 0) ? 0 : 3Gui_X

    GuiControl, 3:Focus, Static1
    Gui, 3:Show, x%3Gui_X% y%3Gui_Y% w250 h180, Color – Transparent
    Melt(ID3, 255, 1)
    Return

ColorSet:
    %A_GuiControl%_ := SubStr("00" . Trans(%A_GuiControl%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

MarkerColor:
    MarkerColor := InvertColor(Red_, Green_, Blue_)
    Loop 8
        Control_Colors(Text%a_index%ID, "Set", MarkerColor)
    Return

TransSet:
    WinSet, Transparent, % Trans, ahk_id %ID%
    Return

3GuiClose:
    Melt(ID3, 255, 0)
    Gui, 3:Destroy
    Return

Exit:
    IfWinExist, ahk_id %ID3%
        Gosub, 3GuiClose
    if !mod
        Melt(ID, Trans, 0)
    Ini_WriteSect("Color", "Red", Red_, "Green", Green_, "Blue", Blue_)
    Ini_WriteSect("Transparent", "Trans", Trans)
    Ini_WriteSect("Extension", "ext", ext)
    Ini_WriteSect("Out Directory", "OutDirectory", OutDirectory)
    Ini_WriteSect("Write Method", "WriteMethod", WriteMethod)
    Ini_WriteSect("Resize Pointers", "ResizePointers", ResizePointers)
    Ini_WriteSect("Quality JPG", "Quality", Quality)

    RestoreCursors()
    ExitApp

#IfWinExist Color – Transparent ahk_class AutoHotkeyGUI
Esc:: Goto, 3GuiClose

#IfWinExist Quality of JPEG ahk_class AutoHotkeyGUI
Esc:: Goto, 4GuiClose

#IfWinExist
PrintScreen::
    IfWinExist, ahk_id %ID%
    {
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0, 50)
        Gui, 2:-Caption +LastFound
        Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
        WinActivate
        Send, !{PrintScreen}
        Gui, 2:Destroy
        Melt(ID, Trans, 1, 50)
    }
    Else
        Send, {PrintScreen}

WriteFile:
    IfNotExist, % OutDirectory
        OutDirectory := A_ScriptDir
    if WriteMethod = Paint
        SaveBufferToFileViaPaint(OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)
    else
        Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext, Quality)
    Return

~!PrintScreen:: Goto, WriteFile

Pause:: Melt(ID, Trans, mod), mod := !mod

ScrollLock::
    if !mod
        Melt(ID, Trans, 0)
    Gui, Show, % "x" A_ScreenWidth/2 - 103 "y" A_ScreenHeight/2 - 118 "w200 h200"
    Melt(ID, 130, 1), Trans := 130, mod := ""
    GuiControl, 3:, Trans, 130
    Return

Esc::
GuiClose:
    ExitApp

Melt(hWnd, Trans, Appear, N = 20)
{
    WinShow, ahk_id %hWnd%
    While A_Index * N < Trans
    {
        WinSet, Transparent, % Appear ? A_Index * N : Trans - A_Index * N, ahk_id %hWnd%
        Sleep, 10
    }
    if Appear
        WinSet, Transparent, % Trans, ahk_id %hWnd%
    Else
        WinHide, ahk_id %hWnd%
}

WM_LBUTTONDOWN(wp, lp, msg, hwnd)
{
    global ID, ID3, ID4, Var
    if (hwnd = ID) && (!Var || GetKeyState("Alt"))
        PostMessage, WM_NCLBUTTONDOWN := 0xA1, 2,,, ahk_id %ID%
    if (hwnd = ID3)
        SetValue1(0)
    if (hwnd = ID4)
        SetValue2(0)
}

WM_RBUTTONDOWN(wp, lp, msg, hwnd)
{
    global ID3, ID4
    if (hwnd = ID3)
        SetValue1(255)
    if (hwnd = ID4)
        SetValue2(255)
}

SetValue1(Pos)
{
    local Control, Text
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 3:, % "msctls_trackbar32" SubStr(Control, 7), % Pos
    Gui, 3:Submit, NoHide
    GuiControlGet, Text, 3:, % Control
    %Text%_ := SubStr("00" . Trans(%Text%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

    Gosub, MarkerColor
    Gosub, TransSet
}

SetValue2(Pos)
{
    local Control
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 4:, msctls_trackbar321, % Pos
    Gui, 4:Submit, NoHide
    Quality := QSlider
}

InvertColor(Red, Green, Blue)
{
    _Red := SubStr("00" . Trans(Trans(Red, 16, 10) ^ 255, 10, 16), -1)
    _Green := SubStr("00" . Trans(Trans(Green, 16, 10) ^ 255, 10, 16), -1)
    _Blue := SubStr("00" . Trans(Trans(Blue, 16, 10) ^ 255, 10, 16), -1)
    Return "0x" _Blue _Green _Red
}


; Пишет секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_WriteSect(Section, Key1, Value1, Key2 = "", Value2 = ""
   , Key3 = "", Value3 = "", Key4 = "", Value4 = "", Key5 = "", Value5 = ""
   , Key6 = "", Value6 = "", Key7 = "", Value7 = "", Key8 = "", Value8 = ""
   , Key9 = "", Value9 = "", Key10 = "", Value10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniWrite, % Value%a_index%, % FileName, % Section, % Key%a_index%
}

; Читает секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

Ini_ReadSect(Section, Key1, ByRef var1, Default1 = "", Key2 = "", ByRef var2 = "", Default2 = ""
   , Key3 = "", ByRef var3 = "", Default3 = "", Key4 = "", ByRef var4 = "", Default4 = ""
   , Key5 = "", ByRef var5 = "", Default5 = "", Key6 = "", ByRef var6 = "", Default6 = ""
   , Key7 = "", ByRef var7 = "", Default7 = "", Key8 = "", ByRef var8 = "", Default8 = ""
   , Key9 = "", ByRef var9 = "", Default9 = "", Key10 = "", ByRef var10 = "", Default10 = "")
{
   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniRead, var%a_index%, % FileName, % Section, % Key%a_index%, % Default%a_index%
}


; Переводит число Number из системы счисления N в систему счисления K. Number должно
; быть написано без префикса, и, если содержит буквенные символы, в кавычках.
; Возвращает значение без префикса.

Trans(Number, N, K)
{
    if N = 10
        Return Trans_Dec(Number, K)
    if K = 10
        Return Trans_ToDec(Number, N)
    Else
        Return Trans_Dec(Trans_ToDec(Number, N), K)
}

Trans_Dec(Number, K)
{
    if K = 16
    {
        SetFormat, integer, hex
        TransNumber := SubStr(Number + 0, 3)
        SetFormat, integer, dec
        Return TransNumber
    }
    if (Number < K)
        Return Number < 10 ? Number : Chr(Asc("A") + Number - 10)
    Mod := Mod(Number,K) < 10 ? Mod(Number,K) : Chr(Asc("A") + Mod(Number,K) - 10)
    Return Trans_Dec(Floor(Number/K),K) . Mod
}

Trans_ToDec(Number, N)
{
    if N = 16
    {
        SetFormat, integer, d
        Number := "0x" . Number
        Return Number + 0
    }
    StringCaseSense on
    if StrLen(Number) = 1
    {
        if Number between a and z
            Number := Asc(Number) - Asc("a") + 10
        if Number between A and Z
            Number := Asc(Number) - Asc("A") + 10
        Return Number
    }
    SubString := SubStr(Number,1,1)
    if SubString between a and z
        SubString := Asc(SubString) - Asc("a") + 10
    if SubString between A and Z
        SubString := Asc(SubString) - Asc("A") + 10
    Return SubString*N**(StrLen(Number)-1) + Trans_ToDec(SubStr(Number,2),N)
}

Convert(sFileFr = "", sFileTo = "", nQuality = "")
{
    If    sFileTo  =
        sFileTo := A_ScriptDir . "\screen.bmp"
    SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

    If Not    hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
        Return    sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo . "\" . sNameTo . ".bmp") : ""
    VarSetCapacity(si, 16, 0), si := Chr(1)
    DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

    If    !sFileFr
    {
        DllCall("OpenClipboard", "Uint", 0)
        If     DllCall("IsClipboardFormatAvailable", "Uint", 2)
                                                            && (hBM:=DllCall("GetClipboardData", "Uint", 2))
        DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0, "UintP", pImage)
        DllCall("CloseClipboard")
    }
    Else If    sFileFr Is Integer
        DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0, "UintP", pImage)
    Else    DllCall("gdiplus\GdipLoadImageFromFile"
                                                        , "Uint", Unicode4Ansi(wFileFr,sFileFr), "UintP", pImage)

    DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
    VarSetCapacity(ci,nSize,0)
    DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
    Loop, %    nCount
        If    InStr(Ansi4Unicode(NumGet(ci,76*(A_Index-1)+44)), "." . sExtTo)
        {
            pCodec := &ci+76*(A_Index-1)
            Break
        }
    If    InStr(".JPG.JPEG.JPE.JFIF", "." . sExtTo) && nQuality<>"" && pImage && pCodec
    {
    DllCall("gdiplus\GdipGetEncoderParameterListSize", "Uint", pImage
                                                                                        , "Uint", pCodec, "UintP", nSize)
    VarSetCapacity(pi,nSize,0)
    DllCall("gdiplus\GdipGetEncoderParameterList", "Uint", pImage, "Uint", pCodec, "Uint"
                                                                                                        , nSize, "Uint", &pi)
    Loop, %    NumGet(pi)
        If    NumGet(pi,28*(A_Index-1)+20)=1 && NumGet(pi,28*(A_Index-1)+24)=6
        {
            pParam := &pi+28*(A_Index-1)
            NumPut(nQuality,NumGet(NumPut(4,NumPut(1,pParam+0)+20)))
            Break
        }
    }

    If    pImage
        pCodec ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage
            , "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec
            , "Uint", pParam) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap"
            , "Uint", pImage, "UintP", hBitmap
            , "Uint", 0) . SetClipboardData(hBitmap)
            , DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

    DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
    DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
    DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
    hFile:=    DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0
                                                                        , "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16
                                                                                    , "Uint", 6, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint", 8, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20), "Uint"
                                                                                , NumGet(oi,44), "UintP", 0, "Uint", 0)
    DllCall("CloseHandle", "Uint", hFile)
}

SetClipboardData(hBitmap)
{
    DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
    hDIB :=    DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
    pDIB :=    DllCall("GlobalLock", "Uint", hDIB)
    DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
    DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
    DllCall("GlobalUnlock", "Uint", hDIB)
    DllCall("DeleteObject", "Uint", hBitmap)
    DllCall("OpenClipboard", "Uint", 0)
    DllCall("EmptyClipboard")
    DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
    DllCall("CloseClipboard")
}

Unicode4Ansi(ByRef wString, sString)
{
    nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                                                    , "int", -1, "Uint", 0, "int", 0)
    VarSetCapacity(wString, nSize * 2)
    DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1
                                                                                    , "Uint", &wString, "int", nSize)
    Return    &wString
}

Ansi4Unicode(pString)
{
    nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                                        , "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
    VarSetCapacity(sString, nSize)
    DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                                , "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
    Return    sString
}

SaveBufferToFileViaPaint(FilePath)
{
    global Quality
    Critical
    WM_COMMAND = 0x111

    RegRead, BMPHeight_Old, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPHeight
    RegRead, BMPWidth_Old, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth

    if (BMPHeight_Old = "") || (BMPWidth_Old = "")
    {
        MsgBox, 16, Error!, Ошибка чтения реестра!, 2
        Return
    }

    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPHeight, 1
    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth, 1

    DetectHiddenWindows, On
    SplitPath, FilePath, OutFileName, OutDir, OutExtension, OutNameNoExt
    if OutExtension != bmp
        Old_FilePath := FilePath, FilePath := A_Temp . "\" . OutNameNoExt . ".bmp"
    FileAppend,, %FilePath%
    Run, mspaint "%FilePath%",, Hide
    WinWait, %OutNameNoExt%.bmp - Paint

    ;команда меню "Правка" - "Вставить"
    PostMessage, WM_COMMAND, 57637

    ;команда меню "Файл" - "Сохранить"
    PostMessage, WM_COMMAND, 57603

    WinClose
    WinWaitClose,,, 1
    if ErrorLevel
    {
        WinShow
        MsgBox, 48, Error!, Ошибка работы с mspaint.exe!, 2
    }

    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View,BMPHeight,%BMPHeight_Old%
    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth, %BMPWidth_Old%

    if OutExtension != bmp
    {
        Convert(FilePath, Old_FilePath, Quality)
        FileDelete, % FilePath
    }
}

SetCursor(pShape, pCtrl="")
{
    return SetCursor_(pShape, pCtrl, 0)
}

SetCursor_(wparam, lparam, msg)
{
    global ID, ID3
    static WM_SETCURSOR = 0x20, WM_MOUSEMOVE = 0x200
    static IDC_HAND = 32649, IDC_ARROW = 32512
    static hover, cursor, ctrls = "`n", init

    if !init
        init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"), OnMessage(WM_MOUSEMOVE, "SetCursor_")

    if A_Gui =
    {
        cursor := DllCall("LoadCursor", UInt, 0, Int, %WPARAM%, UInt)
        ctrls .= lparam "=" cursor "`n"
    }

    If (msg = WM_SETCURSOR)
        ifEqual, hover, 1, return 1

    if (msg = WM_MOUSEMOVE)
    {
        MouseGetPos,,, ID_Win, Control
        if (ID_Win = ID)
            Return
        If j := InStr(ctrls, "`n" Control "=")
        {
            hover := true
            j += 2 + StrLen(Control)
            j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j) - j + 1)
            DllCall("SetCursor", UInt, j)
        }
        else DllCall("SetCursor", UInt, IDC_ARROW), hover := ""
    }
}

SetSystemCursor(IDC)
{
    IDC_SIZENWSE = 32642
    IDC_SIZENESW = 32643
    IDC_SIZEWE = 32644
    IDC_SIZENS = 32645
    IDC_ARROW = 32512
    CursorHandle := DllCall( "LoadCursor", Uint, 0, Int, %IDC%, Uint)
    DllCall( "SetSystemCursor", Uint, CursorHandle, Int, IDC_ARROW)
}

RestoreCursors()
{
   SPI_SETCURSORS = 0x57
   DllCall( "SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0 )
}


Control_Colors(Hwnd, Msg, wParam, lParam = 0)
{
    Thread, Priority, 2147483647

    If !(Hwnd+0) {
        GuiControlGet, nHwnd, Hwnd, %Hwnd%
        Hwnd := nhwnd
   }

   Static OldWinProc := ""          ; origin Windowprocedure
   Static NewWinProc := ""          ; new Windowprocedure
   Static SetValue := "Set"         ; take over Values
   Static Register := "RCB"         ; RegisterCallBack
   Static ValueList := ""           ; Values

   If (A_EventInfo <> NewWinProc) {
      If (Msg = SetValue) {
         If (RegExMatch(ValueList, "m)^" . (Hwnd +0) . "\|")) {
            ValueList := RegExReplace(ValueList
                                     , "m)^" . (Hwnd + 0) . "\|.*$"
                                     , (Hwnd + 0) . "|"
                                     . (wParam + 0) . "|"
                                     . (lParam + 0))
         } Else {
            ValueList .= (Hwnd + 0) . "|"
                      .  (wParam + 0) . "|"
                      .  (lParam + 0) .  "`r`n"
         }
         Return
      }
      If (Msg = Register) {
         If (NewWinProc = "") {
            NewWinProc := RegisterCallback("Control_Colors","",4)
            OldWinProc := DllCall("SetWindowLong"
                                 , UInt, Hwnd
                                 , Int, -4
                                 , Int, NewWinProc
                                 , UInt)
         }
         Return
      }
      Return
   }
   ; 0x0133 : WM_CTLCOLOREDIT
   ; 0x0138 : WM_CTLCOLORSTATIC
   If (Msg = 0x0133 Or Msg = 0x0135 Or Msg = 0x0138) {
      If (RegExMatch(ValueList, "m)^"
                     . (lParam + 0) . "\|(?P<BG>\d+)\|(?P<TX>\d+)$"
                     , C)) {
         DllCall("SetTextColor", UInt, wParam, UInt, CTX)
         DllCall("SetBkColor", UInt, wParam, UInt, CBG)
         Return, DllCall("CreateSolidBrush", UInt, CBG)
      }
   }
   Return DllCall("CallWindowProcA"
                  , UInt, OldWinProc
                  , UInt, Hwnd
                  , UInt, Msg
                  , UInt, wParam
                  , UInt, lParam)
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

54

Re: AHK: Сохранить маленький произвольный кусок экрана

У меня заработало («Via Paint»).

55

Re: AHK: Сохранить маленький произвольный кусок экрана

Теперь нужно как-то на Висте попробовать!

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

56

Re: AHK: Сохранить маленький произвольный кусок экрана

А до конца Paint никак не обуздать, ведь может же он в другие форматы сам сохранять? Вообще крутая вещь получается. Но по-моему, в меню окошка нужен пункт Help, чтобы мучительно не вспоминать клавиши. А также Save. И сохранение по двойному щелчку в окошке. Перетащил окошко мышью, раздвинул, как мне надо, и тут же даблкликом сохранил. Тащу в другое место и сохраняю другой кусок. Не нужно отрываться на клавиатуру. Честно говоря, клавиатура здесь как-то вообще сбоку. Вот когда окошко скрыто — тогда другой разговор, там клавиатура рулит.

57

Re: AHK: Сохранить маленький произвольный кусок экрана

YMP пишет:

А до конца Paint никак не обуздать, ведь может же он в другие форматы сам сохранять?

Пока не придумал. Ещё буду пробовать, но уже после выходных.
По поводу остального — в общем, согласен, но, наверное, не "Save", а что-нибудь типа "Shot" ?

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

58

Re: AHK: Сохранить маленький произвольный кусок экрана

Я бы всё-таки за Save голосовал, так понятнее. Но в общем-то это ведь скрипт и каждый может поставить что ему нравится. По большому счёту надо бы вообще по-русски. Или — определять локаль юзера и соответственно выводить либо русское, либо английское меню.

59

Re: AHK: Сохранить маленький произвольный кусок экрана

YMP пишет:

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

Логично, но несколько заморочно. Придётся ещё строк 100 по поводу меню добавить.

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

60

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker пишет:

Ещё буду пробовать, но уже после выходных.

Тогда пока открепляю тему.

61

Re: AHK: Сохранить маленький произвольный кусок экрана

"До конца" Paint обуздать не удаётся никоим образом. Если у кого-то есть идеи — готов рассмотреть!

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

62

Re: AHK: Сохранить маленький произвольный кусок экрана

А какие идеи не сработали?

63

Re: AHK: Сохранить маленький произвольный кусок экрана

Да идей-то было негусто. Вместо

    ;команда меню "Файл" - "Сохранить"
    PostMessage, WM_COMMAND, 57603

посылать

    ;команда меню "Файл" - "Сохранить как"
    PostMessage, WM_COMMAND, 57604

и скрывать диалоговое окно сразу после появления. Но оно мелькает.
Поэтому просто прошерстил Гугл в поиске каких-нибудь ключей для запуска, но ничего путного не нашёл.

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

64 (изменено: teadrinker, 2009-07-15 14:53:36)

Re: AHK: Сохранить маленький произвольный кусок экрана

Текущий вариант, добавлен Help и сохранение скриншота по двойному щелчку в области окна.

    #NoEnv
    #UseHook
    OnExit, Exit
    SetWinDelay, 0
    SetBatchLines, -1
    CoordMode, Mouse

    Menu, Tray, Icon, Shell32.dll, 95

    Ini_ReadSect("Color", "Red", Red_, "FF", "Green", Green_, "C7", "Blue", Blue_, "00")
    Ini_ReadSect("Transparent", "Trans", Trans, 130)
    Ini_ReadSect("Extension", "ext", ext, "bmp")
    Ini_ReadSect("Out Directory", "OutDirectory", OutDirectory, A_ScriptDir)
    Ini_ReadSect("Write Method", "WriteMethod", WriteMethod, "WinApi")
    Ini_ReadSect("Resize Pointers", "ResizePointers", ResizePointers, "Cursors")
    Ini_ReadSect("Quality JPEG", "Quality", Quality, 100)

    Menu, Tray, NoStandard
    Menu, Tray, Add, Hide                  Pause, Pause
    Menu, Tray, Add
    Menu, Tray, Add, Help                  F1, Help
    Menu, Tray, Add
    Menu, Tray, Add, Exit                   Esc, Exit

    Menu, ResizePointers, Add, Cursors, ResizePointers
    Menu, ResizePointers, Add, Markers, ResizePointers
    Menu, ResizePointers, Check, %ResizePointers%

    Menu, WriteMethod, Add, Via WinApi, WriteMethod
    Menu, WriteMethod, Add, Via Paint, WriteMethod
    Menu, WriteMethod, Check, Via %WriteMethod%

    Menu, OutDirectory, Add, % OutDirectory, OutDirectory

    Menu, Quality, Add, Quality = %Quality%`%, QualityOK
    Menu, Quality, Add, Change Quality, SetQuality

    Menu, Extensions, Add, JPG, :Quality
    Menu, Extensions, Add, BMP, Extensions
    Menu, Extensions, Add, TIF, Extensions
    Menu, Extensions, Add, GIF, Extensions
    Menu, Extensions, Add, PNG, Extensions
    Menu, Extensions, Check, %ext%

    Menu, MainMenu, Add, % "Color – Transparent  ", Settings
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Resize Pointers, :ResizePointers
    Menu, MainMenu, Add, Write Method, :WriteMethod
    Menu, MainMenu, Add, Out Directory, :OutDirectory
    Menu, MainMenu, Add, Extension, :Extensions
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Save                              PrintScreen, PrintScreen
    Menu, MainMenu, Add, Hide                               Pause, Pause
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Help                               F1, Help
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Exit                                Esc, GuiClose

    Gui, +LastFound -Caption +AlwaysOnTop +Owner
    WinGet, ID
    WinSet, Transparent, 0
    Gui, Color, % Red_ Green_ Blue_

    Locations = x190 y190|x0 y190|x0 y0|x190 y0|x190 y95|x95 y190|x0 y95|x95 y0
    StringSplit, Location, Locations,|
    Loop 8
        Gui, Add, Text, % "w10 h10 Hidden hwndText" a_index "ID " Location%a_index%

    Gosub, MarkerColor
    Control_Colors(ID, "RCB", 0, 0)

    Loop 7
        SetCursor("IDC_HAND", "Static" a_index)

    Gui, Show, h200 w200, ScreenСatcher

    OnMessage(0x201, "WM_LBUTTONDOWN")
    OnMessage(0x203, "WM_LBUTTONDBLCLK")
    OnMessage(0x204, "WM_RBUTTONDOWN")

    Hotkey, LButton, WinResize, Off
    Melt(ID, Trans, 1), GuiVisible := 1
    SetTimer, %ResizePointers%, 50
    Return

Cursors:
    S = 10
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3) || (ID_Win = ID4)
    {
        RestoreCursors()
        Hotkey, LButton, Off
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H
    if ((X_M <= XW) && (X_M > XW - 2*S) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M <= XW) && (X_M > XW - S) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 1

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 2

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 3

    else if ((X_M <= XW ) && (X_M > XW - 2*S) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M <= XW ) && (X_M > XW - S) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 4

    else if (X_M <= XW) && (X_M > XW - S) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 5
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M <= YH) && (Y_M > YH - S)
        Var = 6
    else if (X_M < X + S) && (X_M >= X) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 7
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M < Y + S) && (Y_M >= Y)
        Var = 8
    else
        Var =

    if Var
    {
        Hotkey, LButton, On
        if ((Var = 1) || (Var = 3)) && (Cursor != "IDC_SIZENWSE")
            RestoreCursors(), SetSystemCursor("IDC_SIZENWSE"), Cursor := "IDC_SIZENWSE"

        if ((Var = 2) || (Var = 4)) && (Cursor != "IDC_SIZENESW")
            RestoreCursors(), SetSystemCursor("IDC_SIZENESW"), Cursor := "IDC_SIZENESW"

        if ((Var = 5) || (Var = 7)) && (Cursor != "IDC_SIZEWE")
            RestoreCursors(), SetSystemCursor("IDC_SIZEWE"), Cursor := "IDC_SIZEWE"

        if ((Var = 6) || (Var = 8)) && (Cursor != "IDC_SIZENS")
            RestoreCursors(), SetSystemCursor("IDC_SIZENS"), Cursor := "IDC_SIZENS"
    }
    else
    {
        Hotkey, LButton, Off
        RestoreCursors(), Cursor := ""
    }
    Return

Markers:
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3) || (ID_Win = ID4)
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H

    if (X_M <= XW+ 20) && (X_M >= XW - 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 1

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 2

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 3

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 4

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 5

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 6

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 7

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 8

    else Var =

    if Var
    {
        Hotkey, LButton, On
        GuiControl, Show, Static%Var%
        Loop 8
            if (a_index != Var)
                GuiControl, Hide, Static%a_index%
    }
    else
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
    }
    Return

WinResize:
    SetTimer, %ResizePointers%, Off
    X_M_Old := X_M, Y_M_Old := Y_M
    While GetKeyState("LButton", "P")
    {
        MouseGetPos, X_M, Y_M
        dX := X_M - X_M_Old, dY := Y_M - Y_M_Old
        IfEqual, Var, 1, WinMove, ahk_id %ID%,,,, W + dX, H + dY
        IfEqual, Var, 2, WinMove, ahk_id %ID%,, X + dX,, W - dX, H + dY
        IfEqual, Var, 3, WinMove, ahk_id %ID%,, X + dX, Y + dY, W - dX, H - dY
        IfEqual, Var, 4, WinMove, ahk_id %ID%,,, Y + dY, W + dX, H - dY
        IfEqual, Var, 5, WinMove, ahk_id %ID%,,,, W + dX
        IfEqual, Var, 6, WinMove, ahk_id %ID%,,,,, H + dY
        IfEqual, Var, 7, WinMove, ahk_id %ID%,, X + dX,, W - dX
        IfEqual, Var, 8, WinMove, ahk_id %ID%,,, Y + dY,, H - dY
        Sleep, 10
    }
    SetTimer, %ResizePointers%, On
    Return

GuiSize:
    GuiControl, Move, Static1, % "x" A_GuiWidth - 10 "y" A_GuiHeight - 10
    GuiControl, Move, Static2, % "x0 y" A_GuiHeight - 10
    GuiControl, Move, Static3, % "x0 y0"
    GuiControl, Move, Static4, % "x" A_GuiWidth - 10 "y0"
    GuiControl, Move, Static5, % "x" A_GuiWidth - 10 "y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static6, % "x" (A_GuiWidth - 10)/2 "y" A_GuiHeight - 10
    GuiControl, Move, Static7, % "x0 y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static8, % "x" (A_GuiWidth - 10)/2 "y0"
    Return

GuiContextMenu:
    RestoreCursors()
    Menu, MainMenu, Show
    Return

QualityOK:
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
    Return

SetQuality:
    Old_Quality := Quality
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
    IfWinExist, ahk_id %ID4%
        Goto, 4GuiClose
    Gui, 4:+owner1 +LastFound
    WinGet, ID4
    WinSet, Transparent, 0
    Gui, 4:Color, CCC8C0
    Gui, 4:Font, s9, Arial
    Gui, 4:Add, Text, x11 y17 w29 cBlue, Quality:
    Gui, 4:Add, Slider, vQSlider gQualitySet x58 y15 w182 h25 ToolTip AltSubmit, % Quality
    Gui, 4:Add, Button, gQOk x80 y50 w90 h23, OK
    XQ := X_M - 260 < 0 ? 0 : X_M - 260, YQ := Y_M - 105 < 0 ? 0 : Y_M - 105
    Gui, 4:Show, x%XQ% y%YQ% w250 h85, Quality of JPEG
    Melt(ID4, 255, 1)
    Return

QualitySet:
    Quality := QSlider
    Return

QOk:
    WinClose, ahk_id %ID4%
    Return

4GuiClose:
    if (Quality != Old_Quality)
        Menu, Quality, Rename, Quality = %Old_Quality%`%, Quality = %Quality%`%
    Melt(ID4, 255, 0)
    Gui, 4:Destroy
    Return

Extensions:
    Menu, Extensions, UnCheck, %ext%
    StringLower, ext, A_ThisMenuItem
    Menu, Extensions, Check, %ext%
    Return

OutDirectory:
    Old_OutDirectory := OutDirectory
    Gosub, Pause
    FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
    OutDirectory := OutDir ? OutDir : OutDirectory
    if (OutDirectory != Old_OutDirectory)
        Menu, OutDirectory, Rename, %Old_OutDirectory%, %OutDirectory%
    if !GuiVisible
        Gosub, Pause
    Return

ResizePointers:
    Menu, ResizePointers, UnCheck, %ResizePointers%
    SetTimer, %ResizePointers%, Off
    ResizePointers := A_ThisMenuItem
    Menu, ResizePointers, Check, %ResizePointers%
    Loop 8
        GuiControl, Hide, Static%a_index%
    SetTimer, %ResizePointers%, 50
    RestoreCursors()
    Return

WriteMethod:
    Menu, WriteMethod, UnCheck, Via %WriteMethod%
    WriteMethod := SubStr(A_ThisMenuItem, 5)
    Menu, WriteMethod, Check, Via %WriteMethod%
    Return

Settings:
    IfWinExist, ahk_id %ID3%
        Goto, 3GuiClose
    Gui, 3:+owner1 +LastFound
    WinGet, ID3
    WinSet, Transparent, 0
    Gui, 3:Color, CCC8C0

    Gui, 3:Font, s9, Arial
    Gui, 3:Add, Text, x11 y17 w29 cRed, Red
    Gui, 3:Add, Text, x10 y47 w30 cGreen, Green
    Gui, 3:Add, Text, x11 y77 w29 cBlue, Blue
    Gui, 3:Add, Text, x10 y107 w30 cWhite, Trans

    Options = x43 w197 h20 Range0-255 ToolTip AltSubmit
    Gui, 3:Add, Slider, vRed gColorSet %Options% y15, 0x%Red_%
    Gui, 3:Add, Slider, vGreen gColorSet %Options% y45, 0x%Green_%
    Gui, 3:Add, Slider, vBlue gColorSet %Options% y75, 0x%Blue_%
    Gui, 3:Add, Slider, vTrans gTransSet %Options% y105, % Trans

    Gui, 3:Add, Button, g3GuiClose x80 y140 w90 h23, OK

    WinGetPos, X, Y, W, H, ahk_id %ID%
    3Gui_Y := (Y + H + 15 + 180 <= A_ScreenHeight) ? Y + H + 15 : Y - 180 - 35
    3Gui_Y := (3Gui_Y < 0) ? 0 : 3Gui_Y
    3Gui_X := (X+(W-250)/2+250 > A_ScreenWidth) ? A_ScreenWidth - 250 : X + (W-256)/2
    3Gui_X := (3Gui_X < 0) ? 0 : 3Gui_X

    GuiControl, 3:Focus, Static1
    Gui, 3:Show, x%3Gui_X% y%3Gui_Y% w250 h180, Color – Transparent
    Melt(ID3, 255, 1)
    Return

ColorSet:
    %A_GuiControl%_ := SubStr("00" . Trans(%A_GuiControl%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

MarkerColor:
    MarkerColor := InvertColor(Red_, Green_, Blue_)
    Loop 8
        Control_Colors(Text%a_index%ID, "Set", MarkerColor)
    Return

TransSet:
    WinSet, Transparent, % Trans, ahk_id %ID%
    Return

3GuiClose:
    Melt(ID3, 255, 0)
    Gui, 3:Destroy
    Return

Help:
    IfWinExist, ahk_id %ID5%
        Goto, 5GuiClose
    if ((X < 540) && (Y < 590)) && GuiVisible
    {
        DetectHiddenWindows On
        Melt(ID, Trans, 0)
        WinMove, ahk_id %ID%,, 540
        Melt(ID, Trans, 1)
    }
    Gui, 5:Default
    Gui, +LastFound +Resize
    WinGet, ID5
    WinSet, Transparent, 0
    Gui, Color, White
    Gui, Add, Text, x0 y0 w515 h550 -Background
    Gui, Add, Text, x4 y4 w507 h73 +0x6
    Gui, Font, s10 bold, Arial
    Gui, Add, Text, x9 y11 BackgroundTrans, Содержание:
    Gui, Font, s9 norm underline
    Gui, Add, Text, gPass x30 y32 cBlue BackgroundTrans, Работа с программой
    Gui, Add, Text, gPass xp yp+16 cBlue BackgroundTrans, Контекстное меню
    Gui, Add, Text, gPass x200 y32 cBlue BackgroundTrans, Меню иконки в трее
    Gui, Add, Text, gPass xp yp+16 cBlue BackgroundTrans, Горячие клавиши
    Gui, Font, s10 norm
    HelpText =
(Join
     Программа «ScreenСatcher» создана для получения скриншотов экрана или его областе
й и сохранения их в файлы с расширениями jpg, bmp, tif, gif, png.`n
`n                                        Работа с программой.`n`n     После запуска ф
айла на экране появляется полупрозрачное окно, которое можно перемещать левой кнопкой м
ыши и менять его размеры.`n`n     Чтобы получить скриншот области экрана, разместите ок
но точно над ней и кликните дважды в пределах окна. Изображение будет записано в файл
, который появится в выбранной папке (по умолчанию – в папке скрипта).`n     Чтобы полу
чить скриншот всего экрана, скройте (при необходимости) окно программы нажатием средне
й кнопки мыши и нажмите клавишу PrintScreen.`n     Для получения скриншота активного ок
на нажмите Alt + PrintScreen.`n`n     Управление программой осуществляется через контек
стное меню главного окна (клик правой кнопкой мыши в пределах окна) и меню иконки програ
ммы в трее (клик правой кнопкой мыши на иконке программы в трее).`n
`n                                          Контекстное меню.`n`nColor – Transparent.`nУ
становки цвета и прозрачности окна.`n`nResize Pointers.`nВыбор индикатора, отображаемог
о при изменении размеров окна: модифицированный курсор мыши, либо цветные маркеры.`n`nW
rite Method.`nСпособ сохранения изображения в файл. Выбираете тот, который будет работат
ь у Вас корректнее (не сработал первый – попробуйте второй).`n`nOut Directory.`nПри выбо
ре этого пункта появляется подменю с названием текущей папки, в которую будут помещатьс
я файлы скриншотов. Для смены папки кликните это подменю.`n`nExtension.`nВыбор расширени
я файлов, в которые будут записываться скриншоты. При выборе JPG открывается подменю с д
вумя пунктами. 1-ый – текущее значение качества (степени сжатия) JPEG, кликните его, есл
и оно Вас устраивает. 2-ой – Change Quality – смена качества JPEG.`n`nSave.`nСохранит
ь в файл скриншот области экрана под окном программы.`n`nHide.`nСпрятать окно программы
.`n`n                                          Меню иконки в трее.`n`nHide.`nСпрятать ок
но программы.`n`nShow.`nПоказать окно программы.`n
`n                                            Горячие клавиши.`n`nP
ause, а также щелчок средней кнопкой мыши – скрыть/показать окно.`nScrollLock – вернут
ь окно в центр экрана.`nPrintScreen – если окно скрипта скрыто, скриншот всего экрана, е
сли видимо – скриншот области экрана, лежащей непосредственно под окном.`nAlt + PrintScr
een – скриншот активного окна.`nEsc – закрытие окон установок и справки, если открыты, и
ли выход из программы.`nЕсли открыто окно установок, щелчок ЛКМ по названию слайдера – у
становка в левую крайнюю позицию, ПКМ – в правую крайнюю.`nF1 – вызов справки.
)
    Gui, Add, Edit, x3 y81 w509 h466 ReadOnly hwndEditID, % HelpText
    GuiControl, Focus, Static1
    Gui, Show, x0 y0 w515 h550, ScreenСatcher Help
    Melt(ID5, 255, 1, 40)
    Return

Pass:
    SendMessage, EM_LINEFROMCHAR := 201, InStr(HelpText, A_GuiControl) - 1,,, ahk_id %EditID%
    GotoLineUp(ErrorLevel + 1, EditID)
    SendInput, {Home}+{Right 3}
    Return

5GuiSize:
    GuiControl, Move, Static1, w%A_GuiWidth% h%A_GuiHeight%
    GuiControl, Move, Static2, % "w" A_GuiWidth - 8
    GuiControl, Move, Edit1, % "w" A_GuiWidth - 6 "h" A_GuiHeight - 84
    Return

5GuiClose:
    Melt(ID5, 255, 0, 40)
    Gui, 5:Destroy
    Return

Exit:
    While (idx := a_index + 2) < 6
        IfWinExist, % "ahk_id" ID%idx%
            Gosub, %idx%GuiClose
    if GuiVisible
    {
        Melt(ID, Trans, 0)
        Gui, Destroy
    }
    Ini_WriteSect("Color", "Red", Red_, "Green", Green_, "Blue", Blue_)
    Ini_WriteSect("Transparent", "Trans", Trans)
    Ini_WriteSect("Extension", "ext", ext)
    Ini_WriteSect("Out Directory", "OutDirectory", OutDirectory)
    Ini_WriteSect("Write Method", "WriteMethod", WriteMethod)
    Ini_WriteSect("Resize Pointers", "ResizePointers", ResizePointers)
    Ini_WriteSect("Quality JPEG", "Quality", Quality)

    RestoreCursors()
    ExitApp

#IfWinActive ScreenСatcher ahk_class AutoHotkeyGUI
F1:: Goto, Help

#IfWinActive ScreenСatcher Help ahk_class AutoHotkeyGUI
F1:: Goto, Help
~WheelUp::
~WheelDown::
    GuiControl, 5:Focus, Edit1
    Return

#IfWinExist Color – Transparent ahk_class AutoHotkeyGUI
Esc:: Goto, 3GuiClose

#IfWinExist Quality of JPEG ahk_class AutoHotkeyGUI
Esc:: Goto, 4GuiClose

#IfWinExist ScreenСatcher Help ahk_class AutoHotkeyGUI
Esc:: Goto, 5GuiClose

#IfWinExist
PrintScreen::
    IfWinExist, ahk_id %ID%
    {
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0, 50)
        Gui, 2:-Caption +LastFound
        Gui, 2:Show, x%X% y%Y% w%W% h%H% hide
        WinActivate
        Send, !{PrintScreen}
        Gui, 2:Destroy
        Melt(ID, Trans, 1, 50)
    }
    Else
        Send, {PrintScreen}

WriteFile:
    IfNotExist, % OutDirectory
        OutDirectory := A_ScriptDir
    if WriteMethod = Paint
        SaveBufferToFileViaPaint(OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext)
    else
        Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext, Quality)
    Return

~!PrintScreen:: Goto, WriteFile

MButton::
Pause::
    Melt(ID, Trans, GuiVisible := !GuiVisible)
    if GuiVisible
        Menu, Tray, Rename, Show                Pause, Hide                  Pause
    Else
        Menu, Tray, Rename, Hide                  Pause, Show                Pause
    Return

ScrollLock::
    if GuiVisible
        Melt(ID, Trans, 0)
    Else
        Menu, Tray, Rename, Show                Pause, Hide                  Pause
    Gui, Show, % "x" A_ScreenWidth/2 - 100 "y" A_ScreenHeight/2 - 118 "w200 h200"
    Melt(ID, 130, 1), Trans := 130, GuiVisible := 1
    GuiControl, 3:, Trans, 130
    Return

Esc::
GuiClose:
    ExitApp

Melt(hWnd, Trans, Appear, N = 20)
{
    WinShow, ahk_id %hWnd%
    While A_Index * N < Trans
    {
        WinSet, Transparent, % Appear ? A_Index * N : Trans - A_Index * N, ahk_id %hWnd%
        Sleep, 10
    }
    if Appear
        WinSet, Transparent, % Trans, ahk_id %hWnd%
    Else
        WinHide, ahk_id %hWnd%
}

WM_LBUTTONDBLCLK(wp, lp, msg, hwnd)
{
    global ID
    if (hwnd = ID)
        Gosub, PrintScreen
}

WM_LBUTTONDOWN(wp, lp, msg, hwnd)
{
    global ID, ID3, ID4, Var
    if (hwnd = ID) && (!Var || GetKeyState("Alt"))
        PostMessage, WM_NCLBUTTONDOWN := 0xA1, 2,,, ahk_id %ID%
    if (hwnd = ID3)
        SetValue1(0)
    if (hwnd = ID4)
        SetValue2(0)
}

WM_RBUTTONDOWN(wp, lp, msg, hwnd)
{
    global ID3, ID4
    if (hwnd = ID3)
        SetValue1(255)
    if (hwnd = ID4)
        SetValue2(255)
}

SetValue1(Pos)
{
    local Control, Text
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 3:, % "msctls_trackbar32" SubStr(Control, 7), % Pos
    Gui, 3:Submit, NoHide
    GuiControlGet, Text, 3:, % Control
    %Text%_ := SubStr("00" . Trans(%Text%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

    Gosub, MarkerColor
    Gosub, TransSet
}

SetValue2(Pos)
{
    local Control
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 4:, msctls_trackbar321, % Pos
    Gui, 4:Submit, NoHide
    Quality := QSlider
}

InvertColor(Red, Green, Blue)
{
    _Red := SubStr("00" . Trans(Trans(Red, 16, 10) ^ 255, 10, 16), -1)
    _Green := SubStr("00" . Trans(Trans(Green, 16, 10) ^ 255, 10, 16), -1)
    _Blue := SubStr("00" . Trans(Trans(Blue, 16, 10) ^ 255, 10, 16), -1)
    Return "0x" _Blue _Green _Red
}

Ini_WriteSect(Section, Key1, Value1, Key2 = "", Value2 = ""
   , Key3 = "", Value3 = "", Key4 = "", Value4 = "", Key5 = "", Value5 = ""
   , Key6 = "", Value6 = "", Key7 = "", Value7 = "", Key8 = "", Value8 = ""
   , Key9 = "", Value9 = "", Key10 = "", Value10 = "")
{
; Пишет секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniWrite, % Value%a_index%, % FileName, % Section, % Key%a_index%
}

Ini_ReadSect(Section, Key1, ByRef var1, Default1 = "", Key2 = "", ByRef var2 = "", Default2 = ""
   , Key3 = "", ByRef var3 = "", Default3 = "", Key4 = "", ByRef var4 = "", Default4 = ""
   , Key5 = "", ByRef var5 = "", Default5 = "", Key6 = "", ByRef var6 = "", Default6 = ""
   , Key7 = "", ByRef var7 = "", Default7 = "", Key8 = "", ByRef var8 = "", Default8 = ""
   , Key9 = "", ByRef var9 = "", Default9 = "", Key10 = "", ByRef var10 = "", Default10 = "")
{
; Читает секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniRead, var%a_index%, % FileName, % Section, % Key%a_index%, % Default%a_index%
}

Trans(Number, N, K)
{
; Переводит число Number из системы счисления N в систему счисления K. Number должно
; быть написано без префикса, и, если содержит буквенные символы, в кавычках.
; Возвращает значение без префикса.

    if N = 10
        Return Trans_Dec(Number, K)
    if K = 10
        Return Trans_ToDec(Number, N)
    Else
        Return Trans_Dec(Trans_ToDec(Number, N), K)
}

Trans_Dec(Number, K)
{
    if K = 16
    {
        SetFormat, integer, hex
        TransNumber := SubStr(Number + 0, 3)
        SetFormat, integer, dec
        Return TransNumber
    }
    if (Number < K)
        Return Number < 10 ? Number : Chr(Asc("A") + Number - 10)
    Mod := Mod(Number,K) < 10 ? Mod(Number,K) : Chr(Asc("A") + Mod(Number,K) - 10)
    Return Trans_Dec(Floor(Number/K),K) . Mod
}

Trans_ToDec(Number, N)
{
    if N = 16
    {
        SetFormat, integer, d
        Number := "0x" . Number
        Return Number + 0
    }
    StringCaseSense on
    if StrLen(Number) = 1
    {
        if Number between a and z
            Number := Asc(Number) - Asc("a") + 10
        if Number between A and Z
            Number := Asc(Number) - Asc("A") + 10
        Return Number
    }
    SubString := SubStr(Number,1,1)
    if SubString between a and z
        SubString := Asc(SubString) - Asc("a") + 10
    if SubString between A and Z
        SubString := Asc(SubString) - Asc("A") + 10
    Return SubString*N**(StrLen(Number)-1) + Trans_ToDec(SubStr(Number,2),N)
}

GotoLineUp(N, Hwnd_Edit)
{
; Осуществляет переход к строке с номером N в контроле Edit, строка, если
; возможно, становится первой видимой

   EM_LINEINDEX := 0xBB, EM_SETSEL := 0xB1, EM_SCROLLCARET := 0xB7
   EM_GETFIRSTVISIBLELINE := 0xCE, EM_LINESCROLL := 0xB6
   SendMessage, EM_LINEINDEX, N - 1,,, ahk_id %Hwnd_Edit%
   SendMessage, EM_SETSEL, Errorlevel, Errorlevel,, ahk_id %Hwnd_Edit%
   SendMessage, EM_SCROLLCARET,,,, ahk_id %Hwnd_Edit%
   SendMessage, EM_GETFIRSTVISIBLELINE,,,, ahk_id %Hwnd_Edit%
   SendMessage, EM_LINESCROLL,, N - 1 - Errorlevel,, ahk_id %Hwnd_Edit%
   ControlFocus,, ahk_id %Hwnd_Edit%
   SendInput, {End}
}


Convert(sFileFr = "", sFileTo = "", nQuality = "")
{
    If    sFileTo  =
        sFileTo := A_ScriptDir . "\screen.bmp"
    SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

    If Not    hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
        Return    sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo . "\" . sNameTo . ".bmp") : ""
    VarSetCapacity(si, 16, 0), si := Chr(1)
    DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

    If    !sFileFr
    {
        DllCall("OpenClipboard", "Uint", 0)
        If     DllCall("IsClipboardFormatAvailable", "Uint", 2)
                                                            && (hBM:=DllCall("GetClipboardData", "Uint", 2))
        DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0, "UintP", pImage)
        DllCall("CloseClipboard")
    }
    Else If    sFileFr Is Integer
        DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0, "UintP", pImage)
    Else    DllCall("gdiplus\GdipLoadImageFromFile"
                                                    , "Uint", Unicode4Ansi(wFileFr,sFileFr), "UintP", pImage)

    DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
    VarSetCapacity(ci,nSize,0)
    DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
    Loop, %    nCount
        If    InStr(Ansi4Unicode(NumGet(ci,76*(A_Index-1)+44)), "." . sExtTo)
        {
            pCodec := &ci+76*(A_Index-1)
            Break
        }
    If    InStr(".JPG.JPEG.JPE.JFIF", "." . sExtTo) && nQuality<>"" && pImage && pCodec
    {
    DllCall("gdiplus\GdipGetEncoderParameterListSize", "Uint", pImage
                                                                                        , "Uint", pCodec, "UintP", nSize)
    VarSetCapacity(pi,nSize,0)
    DllCall("gdiplus\GdipGetEncoderParameterList", "Uint", pImage, "Uint", pCodec, "Uint"
                                                                                                        , nSize, "Uint", &pi)
    Loop, %    NumGet(pi)
        If    NumGet(pi,28*(A_Index-1)+20)=1 && NumGet(pi,28*(A_Index-1)+24)=6
        {
            pParam := &pi+28*(A_Index-1)
            NumPut(nQuality,NumGet(NumPut(4,NumPut(1,pParam+0)+20)))
            Break
        }
    }

    If    pImage
        pCodec ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage
            , "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec
            , "Uint", pParam) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap"
            , "Uint", pImage, "UintP", hBitmap
            , "Uint", 0) . SetClipboardData(hBitmap)
            , DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

    DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
    DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
    DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
    hFile:=    DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0
                                                                        , "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16
                                                                                    , "Uint", 6, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint", 8, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20)
                                                                    , "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
    DllCall("CloseHandle", "Uint", hFile)
}

SetClipboardData(hBitmap)
{
    DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
    hDIB :=    DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
    pDIB :=    DllCall("GlobalLock", "Uint", hDIB)
    DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
    DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
    DllCall("GlobalUnlock", "Uint", hDIB)
    DllCall("DeleteObject", "Uint", hBitmap)
    DllCall("OpenClipboard", "Uint", 0)
    DllCall("EmptyClipboard")
    DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
    DllCall("CloseClipboard")
}

Unicode4Ansi(ByRef wString, sString)
{
    nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                                                    , "int", -1, "Uint", 0, "int", 0)
    VarSetCapacity(wString, nSize * 2)
    DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1
                                                                                    , "Uint", &wString, "int", nSize)
    Return    &wString
}

Ansi4Unicode(pString)
{
    nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                                        , "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
    VarSetCapacity(sString, nSize)
    DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                            , "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
    Return    sString
}

SaveBufferToFileViaPaint(FilePath)
{
    global Quality
    Critical
    WM_COMMAND = 0x111

    RegRead, BMPHeight_Old, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPHeight
    RegRead, BMPWidth_Old, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth

    if (BMPHeight_Old = "") || (BMPWidth_Old = "")
    {
        MsgBox, 16, Error!, Ошибка чтения реестра!, 2
        Return
    }

    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPHeight, 1
    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth, 1

    DetectHiddenWindows, On
    SplitPath, FilePath, OutFileName, OutDir, OutExtension, OutNameNoExt
    if OutExtension != bmp
        Old_FilePath := FilePath, FilePath := A_Temp . "\" . OutNameNoExt . ".bmp"
    FileAppend,, %FilePath%
    Run, mspaint "%FilePath%",, Hide
    WinWait, ahk_class MSPaintApp

    ;команда меню "Правка" - "Вставить"
    PostMessage, WM_COMMAND, 57637

    ;команда меню "Файл" - "Сохранить"
    PostMessage, WM_COMMAND, 57603

    WinClose
    WinWaitClose,,, 1
    if ErrorLevel
    {
        WinShow
        MsgBox, 48, Error!, Ошибка работы с mspaint.exe!, 2
    }

    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View,BMPHeight,%BMPHeight_Old%
    RegWrite, REG_DWORD, HKCU
        , Software\Microsoft\Windows\CurrentVersion\Applets\Paint\View, BMPWidth, %BMPWidth_Old%

    if OutExtension != bmp
    {
        Convert(FilePath, Old_FilePath, Quality)
        FileDelete, % FilePath
    }
}

SetCursor(pShape, pCtrl="")
{
    return SetCursor_(pShape, pCtrl, 0)
}

SetCursor_(wparam, lparam, msg)
{
    global ID, ID3, ID5
    static WM_SETCURSOR = 0x20, WM_MOUSEMOVE = 0x200
    static IDC_HAND = 32649, IDC_ARROW = 32512
    static hover, cursor, ctrls = "`n", init

    if !init
        init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"), OnMessage(WM_MOUSEMOVE, "SetCursor_")

    if A_Gui =
    {
        cursor := DllCall("LoadCursor", UInt, 0, Int, %WPARAM%, UInt)
        ctrls .= lparam "=" cursor "`n"
    }

    If (msg = WM_SETCURSOR)
        ifEqual, hover, 1, return 1

    if (msg = WM_MOUSEMOVE)
    {
        MouseGetPos,,, ID_Win, Control
        if (ID_Win = ID)
            Return

        If j := InStr(ctrls, "`n" Control "=")
        {
            if (ID_Win = ID5) && (SubStr(Control, 7) < 4)
            {
                DllCall("SetCursor", UInt, IDC_ARROW), hover := ""
                Return
            }
            hover := true
            j += 2 + StrLen(Control)
            j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j) - j + 1)
            DllCall("SetCursor", UInt, j)
        }
        else DllCall("SetCursor", UInt, IDC_ARROW), hover := ""
    }
}

SetSystemCursor(IDC)
{
    IDC_SIZENWSE = 32642
    IDC_SIZENESW = 32643
    IDC_SIZEWE = 32644
    IDC_SIZENS = 32645
    IDC_ARROW = 32512
    CursorHandle := DllCall( "LoadCursor", Uint, 0, Int, %IDC%, Uint)
    DllCall( "SetSystemCursor", Uint, CursorHandle, Int, IDC_ARROW)
}

RestoreCursors()
{
   SPI_SETCURSORS = 0x57
   DllCall( "SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0 )
}


Control_Colors(Hwnd, Msg, wParam, lParam = 0)
{
    Thread, Priority, 2147483647

    If !(Hwnd+0) {
        GuiControlGet, nHwnd, Hwnd, %Hwnd%
        Hwnd := nhwnd
   }

   Static OldWinProc := ""          ; origin Windowprocedure
   Static NewWinProc := ""          ; new Windowprocedure
   Static SetValue := "Set"         ; take over Values
   Static Register := "RCB"         ; RegisterCallBack
   Static ValueList := ""           ; Values

   If (A_EventInfo <> NewWinProc) {
      If (Msg = SetValue) {
         If (RegExMatch(ValueList, "m)^" . (Hwnd +0) . "\|")) {
            ValueList := RegExReplace(ValueList
                                     , "m)^" . (Hwnd + 0) . "\|.*$"
                                     , (Hwnd + 0) . "|"
                                     . (wParam + 0) . "|"
                                     . (lParam + 0))
         } Else {
            ValueList .= (Hwnd + 0) . "|"
                      .  (wParam + 0) . "|"
                      .  (lParam + 0) .  "`r`n"
         }
         Return
      }
      If (Msg = Register) {
         If (NewWinProc = "") {
            NewWinProc := RegisterCallback("Control_Colors","",4)
            OldWinProc := DllCall("SetWindowLong"
                                 , UInt, Hwnd
                                 , Int, -4
                                 , Int, NewWinProc
                                 , UInt)
         }
         Return
      }
      Return
   }
   ; 0x0133 : WM_CTLCOLOREDIT
   ; 0x0138 : WM_CTLCOLORSTATIC
   If (Msg = 0x0133 Or Msg = 0x0135 Or Msg = 0x0138) {
      If (RegExMatch(ValueList, "m)^"
                     . (lParam + 0) . "\|(?P<BG>\d+)\|(?P<TX>\d+)$"
                     , C)) {
         DllCall("SetTextColor", UInt, wParam, UInt, CTX)
         DllCall("SetBkColor", UInt, wParam, UInt, CBG)
         Return, DllCall("CreateSolidBrush", UInt, CBG)
      }
   }
   Return DllCall("CallWindowProcA"
                  , UInt, OldWinProc
                  , UInt, Hwnd
                  , UInt, Msg
                  , UInt, wParam
                  , UInt, lParam)
}

Единственная проблема — я так и не узнал, работает ли скрипт под Vista. Поэтому, прошу тех, кто пользуется Vista, сделать следующее:
1. Убедиться, что Ваша версия AHK не ниже, чем 1.0.48.
2. Запустить скрипт.
3. Выбрать в контекстном меню окна скрипта Write Method\Via Paint и попробовать сохранить скриншот.
4. В случае, если п.3 выполнен успешно, выбрать в контекстном меню Extension\Tif и попробовать сохранить скриншот.
О результатах прошу отписаться здесь.

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

65 (изменено: migomigo, 2009-07-11 02:14:52)

Re: AHK: Сохранить маленький произвольный кусок экрана

Моя конфигурация:
Vista Home Premium(на ноутбуке) - Последний Апдейт
AutoHotKey - 1.0.48.03

Если переключаю скрипт в "Via Paint" и делаю "Скрин", скрипт сохраняет пустой файл, и начинает вести себя неадекватно. (Окошко перемещяется, но меню не работает. Единственный выход - завершить через ПрогМенеджер)

Если не переключать "Via Pain", то скрипт ведет себя полность Адекватно. Но,  сохраняет только черный прямоугольник, согласно размеров окошка в независимости от формата картинки. Перепробовал все фарматы в обеих режимах. Скрин в моей ноутовской висте так и не удалось сохранить.

Завтра, попробую потестить на ПК с Вистой. Результаты опишу.
Если о чем то не сказал - спрашивайте..

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

66

Re: AHK: Сохранить маленький произвольный кусок экрана

migomigo, а ежели попробовать скомпилировать скрипт и проделать т.н. «Запуск от имени Администратора», как будет себя вести?

67 (изменено: migomigo, 2009-07-11 17:10:45)

Re: AHK: Сохранить маленький произвольный кусок экрана

Хм.. У меня приложение AutoHotKey установлено от имени администратора. В противном случае скрипты не имеют никаких прав..
  Сейчас попробую скомпилировать..

Добавлено:

У скомпилированного скрипта те же свойства что и у нескомпилированного...
На ПК Vista Ultimate - теже свойства....

(Via Paint - после попытки сделать снимок экрана, скрипт перестает реагировать на элементы управления... )

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

68

Re: AHK: Сохранить маленький произвольный кусок экрана

Спасибо, migomigo. А код из этого поста у тебя работает?

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

69 (изменено: migomigo, 2009-07-15 14:07:58)

Re: AHK: Сохранить маленький произвольный кусок экрана

Почему-то WinWaitClose - ожидает даже после закрытия окна...

Вот в таком виде работает:

F12::
FileName := A_DD "." A_MM "." A_YEAR "=" A_Hour "Hour" A_Min "Min" A_Sec "Sec.bmp"
DetectHiddenWindows, On
SendInput {PRINTSCREEN} ; снимок всего экрана (PrtSc)
FileAppend,, %FileName%
Run, MSPaint %FileName%,, Hide
WinWait, ahk_class MSPaintApp
PostMessage, 0x111, 57637, 0, , ahk_class MSPaintApp
PostMessage, 0x111, 57603, 0, , ahk_class MSPaintApp
PostMessage, 0x111, 57665, 0, , ahk_class MSPaintApp
Return
AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

70

Re: AHK: Сохранить маленький произвольный кусок экрана

2migomigo: коллега, в одном ключевом слове две ошибки — это перебор; поправьте злосчастную команду WinWaitClose .

71

Re: AHK: Сохранить маленький произвольный кусок экрана

Спасибо, точно! Сейчас поправлю!

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

72

Re: AHK: Сохранить маленький произвольный кусок экрана

migomigo, я немного подредактировал код из поста #64. Скопируй, пожалуйста, ещё раз, и попробуй опять Via Paint.

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

73

Re: AHK: Сохранить маленький произвольный кусок экрана

Теперь скрипт работает без "лагов". После выбора Виа Пеинт, продолжает реагировать на элементы управления. Но, вместо скрина, сохраняется только черная заливка (черный прямоугольник).

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

74

Re: AHK: Сохранить маленький произвольный кусок экрана

И даже если выбрать расширение bmp?

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

75

Re: AHK: Сохранить маленький произвольный кусок экрана

Да. Всеравно дает черный прямоугольник..

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

76

Re: AHK: Сохранить маленький произвольный кусок экрана

Понял, в чём проблема. Видимо, в Vista нельзя сделать скриншот скрытого окна. Нужен скриншот области экрана с заданными координатами. Попробую переписать.

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

77 (изменено: teadrinker, 2009-07-26 19:17:22)

Re: AHK: Сохранить маленький произвольный кусок экрана

migomigo, попробуй, пожалуйста, такой вариант:

    #NoEnv
    #UseHook
    OnExit, Exit
    SetWinDelay, 0
    SetBatchLines, -1
    CoordMode, Mouse

    Menu, Tray, Icon, Shell32.dll, 95

    Ini_ReadSect("Color", "Red", Red_, "FF", "Green", Green_, "C7", "Blue", Blue_, "00")
    Ini_ReadSect("Transparent", "Trans", Trans, 130)
    Ini_ReadSect("Extension", "ext", ext, "bmp")
    Ini_ReadSect("Out Directory", "OutDirectory", OutDirectory, A_ScriptDir)
    Ini_ReadSect("Resize Pointers", "ResizePointers", ResizePointers, "Cursors")
    Ini_ReadSect("Quality JPEG", "Quality", Quality, 100)

    Menu, Tray, NoStandard
    Menu, Tray, Add, Hide                  Pause, Pause
    Menu, Tray, Add
    Menu, Tray, Add, Help                  F1, Help
    Menu, Tray, Add
    Menu, Tray, Add, Exit                   Esc, Exit

    Menu, ResizePointers, Add, Cursors, ResizePointers
    Menu, ResizePointers, Add, Markers, ResizePointers
    Menu, ResizePointers, Check, %ResizePointers%

    Menu, OutDirectory, Add, % OutDirectory, OutDirectory

    Menu, Quality, Add, Quality = %Quality%`%, QualityOK
    Menu, Quality, Add, Change Quality, SetQuality

    Menu, Extensions, Add, JPG, :Quality
    Menu, Extensions, Add, BMP, Extensions
    Menu, Extensions, Add, TIF, Extensions
    Menu, Extensions, Add, GIF, Extensions
    Menu, Extensions, Add, PNG, Extensions
    Menu, Extensions, Check, %ext%

    Menu, MainMenu, Add, % "Color – Transparent  ", Settings
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Resize Pointers, :ResizePointers
    Menu, MainMenu, Add, Out Directory, :OutDirectory
    Menu, MainMenu, Add, Extension, :Extensions
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Save                              PrintScreen, PrintScreen
    Menu, MainMenu, Add, Hide                               Pause, Pause
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Help                               F1, Help
    Menu, MainMenu, Add
    Menu, MainMenu, Add, Exit                                Esc, GuiClose

    Gui, +LastFound -Caption +AlwaysOnTop +Owner
    WinGet, ID
    WinSet, Transparent, 0
    Gui, Color, % Red_ Green_ Blue_

    Locations = x190 y190|x0 y190|x0 y0|x190 y0|x190 y95|x95 y190|x0 y95|x95 y0
    StringSplit, Location, Locations,|
    Loop 8
        Gui, Add, Text, % "w10 h10 Hidden hwndText" a_index "ID " Location%a_index%

    Gosub, MarkerColor
    Control_Colors(ID, "RCB", 0, 0)

    Loop 7
        SetCursor("IDC_HAND", "Static" a_index)

    Gui, Show, h200 w200, ScreenСatcher

    OnMessage(0x201, "WM_LBUTTONDOWN")
    OnMessage(0x203, "WM_LBUTTONDBLCLK")
    OnMessage(0x204, "WM_RBUTTONDOWN")

    Hotkey, LButton, WinResize, Off
    Melt(ID, Trans, 1), GuiVisible := 1
    SetTimer, %ResizePointers%, 50
    Return

Cursors:
    S = 10
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3) || (ID_Win = ID4)
    {
        RestoreCursors()
        Hotkey, LButton, Off
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H
    if ((X_M <= XW) && (X_M > XW - 2*S) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M <= XW) && (X_M > XW - S) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 1

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - S))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M <= YH) && (Y_M > YH - 2*S))
        Var = 2

    else if ((X_M < X + 2*S) && (X_M >= X) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M < X + S) && (X_M >= X) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 3

    else if ((X_M <= XW ) && (X_M > XW - 2*S) && (Y_M < Y + S) && (Y_M >= Y))
                    || ((X_M <= XW ) && (X_M > XW - S) && (Y_M < Y + 2*S) && (Y_M >= Y))
        Var = 4

    else if (X_M <= XW) && (X_M > XW - S) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 5
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M <= YH) && (Y_M > YH - S)
        Var = 6
    else if (X_M < X + S) && (X_M >= X) && (Y_M <= YH - S) && (Y_M >= Y + S)
        Var = 7
    else if (X_M <= XW - S) && (X_M >= X + S) && (Y_M < Y + S) && (Y_M >= Y)
        Var = 8
    else
        Var =

    if Var
    {
        Hotkey, LButton, On
        if ((Var = 1) || (Var = 3)) && (Cursor != "IDC_SIZENWSE")
            RestoreCursors(), SetSystemCursor("IDC_SIZENWSE"), Cursor := "IDC_SIZENWSE"

        if ((Var = 2) || (Var = 4)) && (Cursor != "IDC_SIZENESW")
            RestoreCursors(), SetSystemCursor("IDC_SIZENESW"), Cursor := "IDC_SIZENESW"

        if ((Var = 5) || (Var = 7)) && (Cursor != "IDC_SIZEWE")
            RestoreCursors(), SetSystemCursor("IDC_SIZEWE"), Cursor := "IDC_SIZEWE"

        if ((Var = 6) || (Var = 8)) && (Cursor != "IDC_SIZENS")
            RestoreCursors(), SetSystemCursor("IDC_SIZENS"), Cursor := "IDC_SIZENS"
    }
    else
    {
        Hotkey, LButton, Off
        RestoreCursors(), Cursor := ""
    }
    Return

Markers:
    MouseGetPos, X_M, Y_M, ID_Win
    if (ID_Win = ID3) || (ID_Win = ID4)
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
        Return
    }
    WinGetPos, X, Y, W, H, ahk_id %ID%
    XW := X + W, YH := Y + H

    if (X_M <= XW+ 20) && (X_M >= XW - 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 1

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 2

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 3

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 4

    else if (X_M <= XW + 20) && (X_M >= XW - 10) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 5

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= YH + 20) && (Y_M >= YH - 10)
        Var = 6

    else if (X_M <= X + 10) && (X_M >= X - 20) && (Y_M < YH - 10) && (Y_M > Y + 10)
        Var = 7

    else if (X_M < XW - 10) && (X_M > X + 10) && (Y_M <= Y + 10) && (Y_M >= Y - 20)
        Var = 8

    else Var =

    if Var
    {
        Hotkey, LButton, On
        GuiControl, Show, Static%Var%
        Loop 8
            if (a_index != Var)
                GuiControl, Hide, Static%a_index%
    }
    else
    {
        Hotkey, LButton, Off
        Loop 8
            GuiControl, Hide, Static%a_index%
    }
    Return

WinResize:
    SetTimer, %ResizePointers%, Off
    X_M_Old := X_M, Y_M_Old := Y_M
    While GetKeyState("LButton", "P")
    {
        MouseGetPos, X_M, Y_M
        dX := X_M - X_M_Old, dY := Y_M - Y_M_Old
        IfEqual, Var, 1, WinMove, ahk_id %ID%,,,, W + dX, H + dY
        IfEqual, Var, 2, WinMove, ahk_id %ID%,, X + dX,, W - dX, H + dY
        IfEqual, Var, 3, WinMove, ahk_id %ID%,, X + dX, Y + dY, W - dX, H - dY
        IfEqual, Var, 4, WinMove, ahk_id %ID%,,, Y + dY, W + dX, H - dY
        IfEqual, Var, 5, WinMove, ahk_id %ID%,,,, W + dX
        IfEqual, Var, 6, WinMove, ahk_id %ID%,,,,, H + dY
        IfEqual, Var, 7, WinMove, ahk_id %ID%,, X + dX,, W - dX
        IfEqual, Var, 8, WinMove, ahk_id %ID%,,, Y + dY,, H - dY
        Sleep, 10
    }
    SetTimer, %ResizePointers%, On
    Return

GuiSize:
    GuiControl, Move, Static1, % "x" A_GuiWidth - 10 "y" A_GuiHeight - 10
    GuiControl, Move, Static2, % "x0 y" A_GuiHeight - 10
    GuiControl, Move, Static3, % "x0 y0"
    GuiControl, Move, Static4, % "x" A_GuiWidth - 10 "y0"
    GuiControl, Move, Static5, % "x" A_GuiWidth - 10 "y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static6, % "x" (A_GuiWidth - 10)/2 "y" A_GuiHeight - 10
    GuiControl, Move, Static7, % "x0 y" (A_GuiHeight - 10)/2
    GuiControl, Move, Static8, % "x" (A_GuiWidth - 10)/2 "y0"
    Return

GuiContextMenu:
    RestoreCursors()
    Menu, MainMenu, Show
    Return

QualityOK:
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
    Return

SetQuality:
    Old_Quality := Quality
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
    IfWinExist, ahk_id %ID4%
        Goto, 4GuiClose
    Gui, 4:+owner1 +LastFound
    WinGet, ID4
    WinSet, Transparent, 0
    Gui, 4:Color, CCC8C0
    Gui, 4:Font, s9, Arial
    Gui, 4:Add, Text, x11 y17 w29 cBlue, Quality:
    Gui, 4:Add, Slider, vQSlider gQualitySet x58 y15 w182 h25 ToolTip AltSubmit, % Quality
    Gui, 4:Add, Button, gQOk x80 y50 w90 h23, OK
    XQ := X_M - 260 < 0 ? 0 : X_M - 260, YQ := Y_M - 105 < 0 ? 0 : Y_M - 105
    Gui, 4:Show, x%XQ% y%YQ% w250 h85, Quality of JPEG
    Melt(ID4, 255, 1)
    Return

QualitySet:
    Quality := QSlider
    Return

QOk:
    WinClose, ahk_id %ID4%
    Return

4GuiClose:
    if (Quality != Old_Quality)
        Menu, Quality, Rename, Quality = %Old_Quality%`%, Quality = %Quality%`%
    Melt(ID4, 255, 0)
    Gui, 4:Destroy
    Return

Extensions:
    Menu, Extensions, UnCheck, %ext%
    StringLower, ext, A_ThisMenuItem
    Menu, Extensions, Check, %ext%
    Return

OutDirectory:
    Old_OutDirectory := OutDirectory
    Gosub, Pause
    FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
    OutDirectory := OutDir ? OutDir : OutDirectory
    if (OutDirectory != Old_OutDirectory)
        Menu, OutDirectory, Rename, %Old_OutDirectory%, %OutDirectory%
    if !GuiVisible
        Gosub, Pause
    Return

ResizePointers:
    Menu, ResizePointers, UnCheck, %ResizePointers%
    SetTimer, %ResizePointers%, Off
    ResizePointers := A_ThisMenuItem
    Menu, ResizePointers, Check, %ResizePointers%
    Loop 8
        GuiControl, Hide, Static%a_index%
    SetTimer, %ResizePointers%, 50
    RestoreCursors()
    Return

Settings:
    IfWinExist, ahk_id %ID3%
        Goto, 3GuiClose
    Gui, 3:+owner1 +LastFound
    WinGet, ID3
    WinSet, Transparent, 0
    Gui, 3:Color, CCC8C0

    Gui, 3:Font, s9, Arial
    Gui, 3:Add, Text, x11 y17 w29 cRed, Red
    Gui, 3:Add, Text, x10 y47 w30 cGreen, Green
    Gui, 3:Add, Text, x11 y77 w29 cBlue, Blue
    Gui, 3:Add, Text, x10 y107 w30 cWhite, Trans

    Options = x43 w197 h20 Range0-255 ToolTip AltSubmit
    Gui, 3:Add, Slider, vRed gColorSet %Options% y15, 0x%Red_%
    Gui, 3:Add, Slider, vGreen gColorSet %Options% y45, 0x%Green_%
    Gui, 3:Add, Slider, vBlue gColorSet %Options% y75, 0x%Blue_%
    Gui, 3:Add, Slider, vTrans gTransSet %Options% y105, % Trans

    Gui, 3:Add, Button, g3GuiClose x80 y140 w90 h23, OK

    WinGetPos, X, Y, W, H, ahk_id %ID%
    3Gui_Y := (Y + H + 15 + 180 <= A_ScreenHeight) ? Y + H + 15 : Y - 180 - 35
    3Gui_Y := (3Gui_Y < 0) ? 0 : 3Gui_Y
    3Gui_X := (X+(W-250)/2+250 > A_ScreenWidth) ? A_ScreenWidth - 250 : X + (W-256)/2
    3Gui_X := (3Gui_X < 0) ? 0 : 3Gui_X

    GuiControl, 3:Focus, Static1
    Gui, 3:Show, x%3Gui_X% y%3Gui_Y% w250 h180, Color – Transparent
    Melt(ID3, 255, 1)
    Return

ColorSet:
    %A_GuiControl%_ := SubStr("00" . Trans(%A_GuiControl%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

MarkerColor:
    MarkerColor := InvertColor(Red_, Green_, Blue_)
    Loop 8
        Control_Colors(Text%a_index%ID, "Set", MarkerColor)
    Return

TransSet:
    WinSet, Transparent, % Trans, ahk_id %ID%
    Return

3GuiClose:
    Melt(ID3, 255, 0)
    Gui, 3:Destroy
    Return

Help:
    IfWinExist, ahk_id %ID5%
        Goto, 5GuiClose
    if ((X < 540) && (Y < 590)) && GuiVisible
    {
        DetectHiddenWindows On
        Melt(ID, Trans, 0)
        WinMove, ahk_id %ID%,, 540
        Melt(ID, Trans, 1)
    }
    Gui, 5:Default
    Gui, +LastFound +Resize
    WinGet, ID5
    WinSet, Transparent, 0
    Gui, Color, White
    Gui, Add, Text, x0 y0 w515 h550 -Background
    Gui, Add, Text, x4 y4 w507 h73 +0x6
    Gui, Font, s10 bold, Arial
    Gui, Add, Text, x9 y11 BackgroundTrans, Содержание:
    Gui, Font, s9 norm underline
    Gui, Add, Text, gPass x30 y32 cBlue BackgroundTrans, Работа с программой
    Gui, Add, Text, gPass xp yp+16 cBlue BackgroundTrans, Контекстное меню
    Gui, Add, Text, gPass x200 y32 cBlue BackgroundTrans, Меню иконки в трее
    Gui, Add, Text, gPass xp yp+16 cBlue BackgroundTrans, Горячие клавиши
    Gui, Font, s10 norm
    HelpText =
(Join
     Программа «ScreenСatcher» создана для получения скриншотов экрана или его областе
й и сохранения их в файлы с расширениями jpg, bmp, tif, gif, png.`n
`n                                        Работа с программой.`n`n     После запуска ф
айла на экране появляется полупрозрачное окно, которое можно перемещать левой кнопкой м
ыши и менять его размеры.`n`n     Чтобы получить скриншот области экрана, разместите ок
но точно над ней и кликните дважды в пределах окна. Изображение будет записано в файл
, который появится в выбранной папке (по умолчанию – в папке скрипта).`n     Чтобы полу
чить скриншот всего экрана, скройте окно программы нажатием средне
й кнопки мыши и нажмите клавишу PrintScreen.`n     Для получения скриншота активного ок
на нажмите Alt + PrintScreen.`n`n     Управление программой осуществляется через контек
стное меню главного окна (клик правой кнопкой мыши в пределах окна) и меню иконки програ
ммы в трее (клик правой кнопкой мыши на иконке программы в трее).`n
`n                                          Контекстное меню.`n`nColor – Transparent.`nУ
становки цвета и прозрачности окна.`n`nResize Pointers.`nВыбор индикатора, отображаемог
о при изменении размеров окна: модифицированный курсор мыши, либо цветные маркеры.`n`nOu
t Directory.`nПри выбо
ре этого пункта появляется подменю с названием текущей папки, в которую будут помещатьс
я файлы скриншотов. Для смены папки кликните это подменю.`n`nExtension.`nВыбор расширени
я файлов, в которые будут записываться скриншоты. При выборе JPG открывается подменю с д
вумя пунктами. 1-ый – текущее значение качества (степени сжатия) JPEG, кликните его, есл
и оно Вас устраивает. 2-ой – Change Quality – смена качества JPEG.`n`nSave.`nСохранит
ь в файл скриншот области экрана под окном программы.`n`nHide.`nСпрятать окно программы
.`n`n                                          Меню иконки в трее.`n`nHide.`nСпрятать ок
но программы.`n`nShow.`nПоказать окно программы.`n
`n                                            Горячие клавиши.`n`nP
ause, а также щелчок средней кнопкой мыши – скрыть/показать окно.`nScrollLock – вернут
ь окно в центр экрана.`nPrintScreen – если окно скрипта скрыто, скриншот всего экрана, е
сли видимо – скриншот области экрана, лежащей непосредственно под окном.`nAlt + PrintScr
een – скриншот активного окна.`nEsc – закрытие окон установок и справки, если открыты, и
ли выход из программы.`nЕсли открыто окно установок, щелчок ЛКМ по названию слайдера – у
становка в левую крайнюю позицию, ПКМ – в правую крайнюю.`nF1 – вызов справки.
)
    Gui, Add, Edit, x3 y81 w509 h466 ReadOnly hwndEditID, % HelpText
    GuiControl, Focus, Static1
    Gui, Show, x0 y0 w515 h550, ScreenСatcher Help
    Melt(ID5, 255, 1, 40)
    Return

Pass:
    SendMessage, EM_LINEFROMCHAR := 201, InStr(HelpText, A_GuiControl) - 1,,, ahk_id %EditID%
    GotoLineUp(ErrorLevel + 1, EditID)
    SendInput, {Home}+{Right 3}
    Return

5GuiSize:
    GuiControl, Move, Static1, w%A_GuiWidth% h%A_GuiHeight%
    GuiControl, Move, Static2, % "w" A_GuiWidth - 8
    GuiControl, MoveDraw, Edit1, % "w" A_GuiWidth - 6 "h" A_GuiHeight - 84
    Return

5GuiClose:
    Melt(ID5, 255, 0, 40)
    Gui, 5:Destroy
    Return

Exit:
    While (idx := a_index + 2) < 6
        IfWinExist, % "ahk_id" ID%idx%
            Gosub, %idx%GuiClose
    if GuiVisible
    {
        Melt(ID, Trans, 0)
        Gui, Destroy
    }
    Ini_WriteSect("Color", "Red", Red_, "Green", Green_, "Blue", Blue_)
    Ini_WriteSect("Transparent", "Trans", Trans)
    Ini_WriteSect("Extension", "ext", ext)
    Ini_WriteSect("Out Directory", "OutDirectory", OutDirectory)
    Ini_WriteSect("Resize Pointers", "ResizePointers", ResizePointers)
    Ini_WriteSect("Quality JPEG", "Quality", Quality)

    RestoreCursors()
    ExitApp

#IfWinActive ScreenСatcher ahk_class AutoHotkeyGUI
F1:: Goto, Help

#IfWinActive ScreenСatcher Help ahk_class AutoHotkeyGUI
F1:: Goto, Help
~WheelUp::
~WheelDown::
    GuiControl, 5:Focus, Edit1
    Return

#IfWinExist Color – Transparent ahk_class AutoHotkeyGUI
Esc:: Goto, 3GuiClose

#IfWinExist Quality of JPEG ahk_class AutoHotkeyGUI
Esc:: Goto, 4GuiClose

#IfWinExist ScreenСatcher Help ahk_class AutoHotkeyGUI
Esc:: Goto, 5GuiClose

#IfWinExist
PrintScreen::
    IfWinExist, ahk_id %ID%
    {
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0, 50)
        Rect := X "," Y "," X + W "," Y + H
    }
    Else
    {
        Send, {PrintScreen}
        Goto, ~!PrintScreen
    }
    IfNotExist, % OutDirectory
        OutDirectory := A_ScriptDir
    CaptureScreen(Rect, OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext, Quality)
    Melt(ID, Trans, 1, 50)
    Return

~!PrintScreen::
    IfNotExist, % OutDirectory
        OutDirectory := A_ScriptDir
    Convert("", OutDirectory "\" A_Year  A_MM  A_DD "-" A_Hour A_Min A_Sec "." ext, Quality)
    Return

MButton::
Pause::
    Melt(ID, Trans, GuiVisible := !GuiVisible)
    if GuiVisible
        Menu, Tray, Rename, Show                Pause, Hide                  Pause
    Else
        Menu, Tray, Rename, Hide                  Pause, Show                Pause
    Return

ScrollLock::
    if GuiVisible
        Melt(ID, Trans, 0)
    Else
        Menu, Tray, Rename, Show                Pause, Hide                  Pause
    Gui, Show, % "x" A_ScreenWidth/2 - 100 "y" A_ScreenHeight/2 - 118 "w200 h200"
    Melt(ID, 130, 1), Trans := 130, GuiVisible := 1
    GuiControl, 3:, Trans, 130
    Return

Esc::
GuiClose:
    ExitApp

Melt(hWnd, Trans, Appear, N = 20)
{
    WinShow, ahk_id %hWnd%
    While A_Index * N < Trans
    {
        WinSet, Transparent, % Appear ? A_Index * N : Trans - A_Index * N, ahk_id %hWnd%
        Sleep, 10
    }
    if Appear
        WinSet, Transparent, % Trans, ahk_id %hWnd%
    Else
        WinHide, ahk_id %hWnd%
}

WM_LBUTTONDBLCLK()
{
    if A_Gui = 1
        Gosub, PrintScreen
}

WM_LBUTTONDOWN()
{
    WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
    if (A_Gui = 1) && (!Var || GetKeyState("Alt"))
        PostMessage, WM_NCLBUTTONDOWN, HTCAPTION
    if A_Gui = 3
        SetValue1(0)
    if A_Gui = 4
        SetValue2(0)
}

WM_RBUTTONDOWN()
{
    if A_Gui = 3
        SetValue1(255)
    if A_Gui = 4
        SetValue2(255)
}

SetValue1(Pos)
{
    local Control, Text
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 3:, % "msctls_trackbar32" SubStr(Control, 7), % Pos
    Gui, 3:Submit, NoHide
    GuiControlGet, Text, 3:, % Control
    %Text%_ := SubStr("00" . Trans(%Text%, 10, 16), -1)
    Gui, 1:Color, % Red_ Green_ Blue_

    Gosub, MarkerColor
    Gosub, TransSet
}

SetValue2(Pos)
{
    local Control
    MouseGetPos,,,, Control
    if !InStr(Control, "Static")
        Return
    GuiControl, 4:, msctls_trackbar321, % Pos
    Gui, 4:Submit, NoHide
    Quality := QSlider
}

InvertColor(Red, Green, Blue)
{
    _Red := SubStr("00" . Trans(Trans(Red, 16, 10) ^ 255, 10, 16), -1)
    _Green := SubStr("00" . Trans(Trans(Green, 16, 10) ^ 255, 10, 16), -1)
    _Blue := SubStr("00" . Trans(Trans(Blue, 16, 10) ^ 255, 10, 16), -1)
    Return "0x" _Blue _Green _Red
}

Ini_WriteSect(Section, Key1, Value1, Key2 = "", Value2 = ""
   , Key3 = "", Value3 = "", Key4 = "", Value4 = "", Key5 = "", Value5 = ""
   , Key6 = "", Value6 = "", Key7 = "", Value7 = "", Key8 = "", Value8 = ""
   , Key9 = "", Value9 = "", Key10 = "", Value10 = "")
{
; Пишет секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniWrite, % Value%a_index%, % FileName, % Section, % Key%a_index%
}

Ini_ReadSect(Section, Key1, ByRef var1, Default1 = "", Key2 = "", ByRef var2 = "", Default2 = ""
   , Key3 = "", ByRef var3 = "", Default3 = "", Key4 = "", ByRef var4 = "", Default4 = ""
   , Key5 = "", ByRef var5 = "", Default5 = "", Key6 = "", ByRef var6 = "", Default6 = ""
   , Key7 = "", ByRef var7 = "", Default7 = "", Key8 = "", ByRef var8 = "", Default8 = ""
   , Key9 = "", ByRef var9 = "", Default9 = "", Key10 = "", ByRef var10 = "", Default10 = "")
{
; Читает секцию ini-файла в директории скрипта, за раз не более 10-ти ключей

   FileName := A_ScriptDir "\" SubStr(A_ScriptName, 1, -3) "ini"
   While Key%a_index%
      IniRead, var%a_index%, % FileName, % Section, % Key%a_index%, % Default%a_index%
}

Trans(Number, N, K)
{
; Переводит число Number из системы счисления N в систему счисления K. Number должно
; быть написано без префикса, и, если содержит буквенные символы, в кавычках.
; Возвращает значение без префикса.

    if N = 10
        Return Trans_Dec(Number, K)
    if K = 10
        Return Trans_ToDec(Number, N)
    Else
        Return Trans_Dec(Trans_ToDec(Number, N), K)
}

Trans_Dec(Number, K)
{
    if K = 16
    {
        SetFormat, integer, hex
        TransNumber := SubStr(Number + 0, 3)
        SetFormat, integer, dec
        Return TransNumber
    }
    if (Number < K)
        Return Number < 10 ? Number : Chr(Asc("A") + Number - 10)
    Mod := Mod(Number,K) < 10 ? Mod(Number,K) : Chr(Asc("A") + Mod(Number,K) - 10)
    Return Trans_Dec(Floor(Number/K),K) . Mod
}

Trans_ToDec(Number, N)
{
    if N = 16
    {
        SetFormat, integer, d
        Number := "0x" . Number
        Return Number + 0
    }
    StringCaseSense on
    if StrLen(Number) = 1
    {
        if Number between a and z
            Number := Asc(Number) - Asc("a") + 10
        if Number between A and Z
            Number := Asc(Number) - Asc("A") + 10
        Return Number
    }
    SubString := SubStr(Number,1,1)
    if SubString between a and z
        SubString := Asc(SubString) - Asc("a") + 10
    if SubString between A and Z
        SubString := Asc(SubString) - Asc("A") + 10
    Return SubString*N**(StrLen(Number)-1) + Trans_ToDec(SubStr(Number,2),N)
}

GotoLineUp(N, Hwnd_Edit)
{
; Осуществляет переход к строке с номером N в контроле Edit, строка, если
; возможно, становится первой видимой

   EM_LINEINDEX := 0xBB, EM_SETSEL := 0xB1, EM_SCROLLCARET := 0xB7
   EM_GETFIRSTVISIBLELINE := 0xCE, EM_LINESCROLL := 0xB6
   SendMessage, EM_LINEINDEX, N - 1,,, ahk_id %Hwnd_Edit%
   SendMessage, EM_SETSEL, Errorlevel, Errorlevel,, ahk_id %Hwnd_Edit%
   SendMessage, EM_SCROLLCARET,,,, ahk_id %Hwnd_Edit%
   SendMessage, EM_GETFIRSTVISIBLELINE,,,, ahk_id %Hwnd_Edit%
   SendMessage, EM_LINESCROLL,, N - 1 - Errorlevel,, ahk_id %Hwnd_Edit%
   ControlFocus,, ahk_id %Hwnd_Edit%
   SendInput, {End}
}

CaptureScreen(aRect, sFile, nQuality)
{
    StringSplit, rt, aRect, `,, %A_Space%%A_Tab%
    nL := rt1
    nT := rt2
    nW := rt3 - rt1
    nH := rt4 - rt2

    mDC := DllCall("CreateCompatibleDC", "Uint", 0)
    hBM := CreateDIBSection(mDC, nW, nH)
    oBM := DllCall("SelectObject", "Uint", mDC, "Uint", hBM)
    hDC := DllCall("GetDC", "Uint", 0)
    DllCall("BitBlt", "Uint", mDC, "int", 0, "int", 0, "int", nW, "int", nH, "Uint", hDC, "int"
                                                                , nL, "int", nT, "Uint", 0x40000000 | 0x00CC0020)
    DllCall("ReleaseDC", "Uint", 0, "Uint", hDC)
    DllCall("SelectObject", "Uint", mDC, "Uint", oBM)
    DllCall("DeleteDC", "Uint", mDC)
    Convert(hBM, sFile, nQuality), DllCall("DeleteObject", "Uint", hBM)
}

CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
    NumPut(VarSetCapacity(bi, 40, 0), bi)
    NumPut(nW, bi, 4)
    NumPut(nH, bi, 8)
    NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
    NumPut(0,  bi,16)
    Return    DllCall("gdi32\CreateDIBSection", "Uint", hDC, "Uint", &bi, "Uint", 0
                                                                            , "UintP", pBits, "Uint", 0, "Uint", 0)
}

Convert(sFileFr = "", sFileTo = "", nQuality = "")
{
    SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

    If Not    hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll")
        Return    sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo . "\" . sNameTo . ".bmp") : ""
    VarSetCapacity(si, 16, 0), si := Chr(1)
    DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "Uint", &si, "Uint", 0)

    If    !sFileFr
    {
        DllCall("OpenClipboard", "Uint", 0)
        If     DllCall("IsClipboardFormatAvailable", "Uint", 2)
                                                            && (hBM:=DllCall("GetClipboardData", "Uint", 2))
        DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", hBM, "Uint", 0, "UintP", pImage)
        DllCall("CloseClipboard")
    }
    Else If    sFileFr Is Integer
        DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Uint", sFileFr, "Uint", 0, "UintP", pImage)
    Else    DllCall("gdiplus\GdipLoadImageFromFile"
                                                    , "Uint", Unicode4Ansi(wFileFr,sFileFr), "UintP", pImage)

    DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
    VarSetCapacity(ci,nSize,0)
    DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "Uint", &ci)
    Loop, %    nCount
        If    InStr(Ansi4Unicode(NumGet(ci,76*(A_Index-1)+44)), "." . sExtTo)
        {
            pCodec := &ci+76*(A_Index-1)
            Break
        }
    If    InStr(".JPG.JPEG.JPE.JFIF", "." . sExtTo) && nQuality<>"" && pImage && pCodec
    {
        DllCall("gdiplus\GdipGetEncoderParameterListSize", "Uint", pImage
                                                                                        , "Uint", pCodec, "UintP", nSize)
        VarSetCapacity(pi,nSize,0)
        DllCall("gdiplus\GdipGetEncoderParameterList", "Uint", pImage, "Uint", pCodec, "Uint"
                                                                                                        , nSize, "Uint", &pi)
        Loop, %    NumGet(pi)
            If    NumGet(pi,28*(A_Index-1)+20)=1 && NumGet(pi,28*(A_Index-1)+24)=6
            {
                pParam := &pi+28*(A_Index-1)
                NumPut(nQuality,NumGet(NumPut(4,NumPut(1,pParam+0)+20)))
                Break
            }
    }

    If    pImage
        pCodec ? DllCall("gdiplus\GdipSaveImageToFile", "Uint", pImage
            , "Uint", Unicode4Ansi(wFileTo,sFileTo), "Uint", pCodec
            , "Uint", pParam) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap"
            , "Uint", pImage, "UintP", hBitmap
            , "Uint", 0) . SetClipboardData(hBitmap)
            , DllCall("gdiplus\GdipDisposeImage", "Uint", pImage)

    DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
    DllCall("FreeLibrary", "Uint", hGdiPlus)
}

SaveHBITMAPToFile(hBitmap, sFile)
{
    DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
    hFile:=    DllCall("CreateFile", "Uint", &sFile, "Uint", 0x40000000, "Uint", 0
                                                                        , "Uint", 0, "Uint", 2, "Uint", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "int64P", 0x4D42|14+40+NumGet(oi,44)<<16
                                                                                    , "Uint", 6, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "int64P", 54<<32, "Uint", 8, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "Uint", &oi+24, "Uint", 40, "UintP", 0, "Uint", 0)
    DllCall("WriteFile", "Uint", hFile, "Uint", NumGet(oi,20)
                                                                    , "Uint", NumGet(oi,44), "UintP", 0, "Uint", 0)
    DllCall("CloseHandle", "Uint", hFile)
}

SetClipboardData(hBitmap)
{
    DllCall("GetObject", "Uint", hBitmap, "int", VarSetCapacity(oi,84,0), "Uint", &oi)
    hDIB :=    DllCall("GlobalAlloc", "Uint", 2, "Uint", 40+NumGet(oi,44))
    pDIB :=    DllCall("GlobalLock", "Uint", hDIB)
    DllCall("RtlMoveMemory", "Uint", pDIB, "Uint", &oi+24, "Uint", 40)
    DllCall("RtlMoveMemory", "Uint", pDIB+40, "Uint", NumGet(oi,20), "Uint", NumGet(oi,44))
    DllCall("GlobalUnlock", "Uint", hDIB)
    DllCall("DeleteObject", "Uint", hBitmap)
    DllCall("OpenClipboard", "Uint", 0)
    DllCall("EmptyClipboard")
    DllCall("SetClipboardData", "Uint", 8, "Uint", hDIB)
    DllCall("CloseClipboard")
}

Unicode4Ansi(ByRef wString, sString)
{
    nSize := DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString
                                                                                    , "int", -1, "Uint", 0, "int", 0)
    VarSetCapacity(wString, nSize * 2)
    DllCall("MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1
                                                                                    , "Uint", &wString, "int", nSize)
    Return    &wString
}

Ansi4Unicode(pString)
{
    nSize := DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                                        , "int", -1, "Uint", 0, "int",  0, "Uint", 0, "Uint", 0)
    VarSetCapacity(sString, nSize)
    DllCall("WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString
                                            , "int", -1, "str", sString, "int", nSize, "Uint", 0, "Uint", 0)
    Return    sString
}

SetCursor(pShape, pCtrl="")
{
    return SetCursor_(pShape, pCtrl, 0)
}

SetCursor_(wparam, lparam, msg)
{
    global ID, ID3, ID5
    static WM_SETCURSOR = 0x20, WM_MOUSEMOVE = 0x200
    static IDC_HAND = 32649, IDC_ARROW = 32512
    static hover, cursor, ctrls = "`n", init

    if !init
        init := 1, OnMessage(WM_SETCURSOR, "SetCursor_"), OnMessage(WM_MOUSEMOVE, "SetCursor_")

    if A_Gui =
    {
        cursor := DllCall("LoadCursor", UInt, 0, Int, %WPARAM%, UInt)
        ctrls .= lparam "=" cursor "`n"
    }

    If (msg = WM_SETCURSOR)
        ifEqual, hover, 1, return 1

    if (msg = WM_MOUSEMOVE)
    {
        MouseGetPos,,, ID_Win, Control
        if (ID_Win = ID)
            Return

        If j := InStr(ctrls, "`n" Control "=")
        {
            if (ID_Win = ID5) && (SubStr(Control, 7) < 4)
            {
                DllCall("SetCursor", UInt, IDC_ARROW), hover := ""
                Return
            }
            hover := true
            j += 2 + StrLen(Control)
            j := SubStr(ctrls, j, InStr(ctrls, "`n", 0, j) - j + 1)
            DllCall("SetCursor", UInt, j)
        }
        else DllCall("SetCursor", UInt, IDC_ARROW), hover := ""
    }
}

SetSystemCursor(IDC)
{
    IDC_SIZENWSE = 32642
    IDC_SIZENESW = 32643
    IDC_SIZEWE = 32644
    IDC_SIZENS = 32645
    IDC_ARROW = 32512
    CursorHandle := DllCall( "LoadCursor", Uint, 0, Int, %IDC%, Uint)
    DllCall( "SetSystemCursor", Uint, CursorHandle, Int, IDC_ARROW)
}

RestoreCursors()
{
   SPI_SETCURSORS = 0x57
   DllCall( "SystemParametersInfo", UInt, SPI_SETCURSORS, UInt, 0, UInt, 0, UInt, 0 )
}


Control_Colors(Hwnd, Msg, wParam, lParam = 0)
{
    Thread, Priority, 2147483647

    If !(Hwnd+0) {
        GuiControlGet, nHwnd, Hwnd, %Hwnd%
        Hwnd := nhwnd
   }

   Static OldWinProc := ""          ; origin Windowprocedure
   Static NewWinProc := ""          ; new Windowprocedure
   Static SetValue := "Set"         ; take over Values
   Static Register := "RCB"         ; RegisterCallBack
   Static ValueList := ""           ; Values

   If (A_EventInfo <> NewWinProc) {
      If (Msg = SetValue) {
         If (RegExMatch(ValueList, "m)^" . (Hwnd +0) . "\|")) {
            ValueList := RegExReplace(ValueList
                                     , "m)^" . (Hwnd + 0) . "\|.*$"
                                     , (Hwnd + 0) . "|"
                                     . (wParam + 0) . "|"
                                     . (lParam + 0))
         } Else {
            ValueList .= (Hwnd + 0) . "|"
                      .  (wParam + 0) . "|"
                      .  (lParam + 0) .  "`r`n"
         }
         Return
      }
      If (Msg = Register) {
         If (NewWinProc = "") {
            NewWinProc := RegisterCallback("Control_Colors","",4)
            OldWinProc := DllCall("SetWindowLong"
                                 , UInt, Hwnd
                                 , Int, -4
                                 , Int, NewWinProc
                                 , UInt)
         }
         Return
      }
      Return
   }
   ; 0x0133 : WM_CTLCOLOREDIT
   ; 0x0138 : WM_CTLCOLORSTATIC
   If (Msg = 0x0133 Or Msg = 0x0135 Or Msg = 0x0138) {
      If (RegExMatch(ValueList, "m)^"
                     . (lParam + 0) . "\|(?P<BG>\d+)\|(?P<TX>\d+)$"
                     , C)) {
         DllCall("SetTextColor", UInt, wParam, UInt, CTX)
         DllCall("SetBkColor", UInt, wParam, UInt, CBG)
         Return, DllCall("CreateSolidBrush", UInt, CBG)
      }
   }
   Return DllCall("CallWindowProcA"
                  , UInt, OldWinProc
                  , UInt, Hwnd
                  , UInt, Msg
                  , UInt, wParam
                  , UInt, lParam)
}

Здесь Write Method выбирать не нужно.

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

78

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker!
Скрипт работает в Vasta как часы!

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

Респект и уважуха!

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

79

Re: AHK: Сохранить маленький произвольный кусок экрана

Мне кажется что такой скрипт в полное мере заслуживает на добавление в коллекцию!

AutoHotKey Version: 1.1.09.02
Не спеши, а то успеешь..

80

Re: AHK: Сохранить маленький произвольный кусок экрана

migomigo, спасибо за помощь, завтра помещу в коллекцию.

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

81

Re: AHK: Сохранить маленький произвольный кусок экрана

К сожалению, почему-то не удалось прикрепить файл к посту.

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

82

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker пишет:

К сожалению, почему-то не удалось прикрепить файл к посту.

Должен иметь расширение «.zip», и, помнится, при preview поле прикрепления очищается — надо заполнять его заново. Ну, и размер <300KB. Ваш скрипт должен в эти рамки укладываться

83

Re: AHK: Сохранить маленький произвольный кусок экрана

Угу. Теперь есть.

84

Re: AHK: Сохранить маленький произвольный кусок экрана

alexii пишет:

Должен иметь расширение «.zip» ... Ну, и размер <300KB.

Если бы там было это написано!

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

85

Re: AHK: Сохранить маленький произвольный кусок экрана

teadrinker пишет:
alexii пишет:

Должен иметь расширение «.zip» ... Ну, и размер <300KB.

Если бы там было это написано!

Здесь всё есть, вроде: Разделы форума и права посетителей.
Такое впечатление, что в имени файла ScreenСatcher.zip русское "С".

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

86

Re: AHK: Сохранить маленький произвольный кусок экрана

The gray Cardinal пишет:

Здесь всё есть, вроде: Разделы форума и права посетителей.

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

The gray Cardinal пишет:

Такое впечатление, что в имени файла ScreenСatcher.zip русское "С".

Точно, как-то закралась, заменил!

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

87

Re: AHK: Сохранить маленький произвольный кусок экрана

Небольшое дополнение. Изображение теперь не только записывается в файл, но и помещается в буфер обмена.

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

88

Re: AHK: Сохранить маленький произвольный кусок экрана

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

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

спасибо заранее.

ps. как жаль что форум только сейчас обнаружил. столько полезных вещей тут оказалось..

89

Re: AHK: Сохранить маленький произвольный кусок экрана

Если нужно снять скриншот по заданным координатам, то можно использовать функцию из этой темы.

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

90

Re: AHK: Сохранить маленький произвольный кусок экрана

Можно ли дописать скрипт, что бы не просто файл копировался на локальную машину, а загружался на какой-нибудь хостинг картинок?

91

Re: AHK: Сохранить маленький произвольный кусок экрана

Угу, можно, пишите .

92

Re: AHK: Сохранить маленький произвольный кусок экрана

Я тоже не против!

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

93

Re: AHK: Сохранить маленький произвольный кусок экрана

Юмор конечно же у вас хороший, но моих знаний сделать такое просто не хватит

94

Re: AHK: Сохранить маленький произвольный кусок экрана

InFlames, теперь вполне серьёзно, без тени юмора: а почему бы Вам и не попробовать? Не на все возможные сервера, выберете для начала какой-нибудь один, с доступом попроще — и вперёд. Дело в том, что старая поговорка «Не боги горшки обжигают», вполне применима и здесь.

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

95

Re: AHK: Сохранить маленький произвольный кусок экрана

"Кому больше всех надо — тот и делает." Это верно.
В хтмл не силен. Есть идея только через какой-нибудь сторонний клиент.

96

Re: AHK: Сохранить маленький произвольный кусок экрана

А есть ли возможнсоть сохранениякартинки в файл, минуя поинт? Какого типа картинка в памяти? Может ручками заголовок составлять? Думаю палитра всегда одна будет.. тока  разрешение ставить в зависимости от окна!
так мона или нет?

Автор, можете описать алгоритм формирования картинки в памяти, ну и дальше. м?

97

Re: AHK: Сохранить маленький произвольный кусок экрана

Resager пишет:

А есть ли возможнсоть сохранениякартинки в файл, минуя поинт?

А что такое "поинт"?

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

98

Re: AHK: Сохранить маленький произвольный кусок экрана

2teadrinker: перевожу на русский — «Microsoft Paint» («mspaint.exe»).

99

Re: AHK: Сохранить маленький произвольный кусок экрана

А-а-а! Никак не могу привыкнуть к этой смеси английского с нижегородским, которой многие почему-то предпочитают пользоваться. Resager, я не совсем понимаю, ты какой скрипт имеешь ввиду, этот или этот?

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

100

Re: AHK: Сохранить маленький произвольный кусок экрана

OFF:

teadrinker пишет:

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

Вот! А я всё вспоминал, как это называется… И не вспомнил .