1

Тема: AutoHotkey: сохранение скриншота экрана в файл

Скрипт сохраняет скриншот экрана в корне диска C: в виде bmp-файла по клавише F12.

F12::
;работаем со скрытыми окнами
DetectHiddenWindows, On
;делаем снимок экрана
Send, {PRINTSCREEN} ; снимок всего экрана (PrtSc)
;Send, !{PRINTSCREEN} ; снимок активного окна (Alt + PrtSc)
;создаём пустой файл
FileAppend,, C:\PrScr.bmp
;открываем пустой файл в скрытом окне Paint
Run, mspaint C:\PrScr.bmp,, Hide
;ждём запуска Paint
WinWait, PrScr.bmp - Paint
;команда меню "Правка" - "Вставить"
PostMessage, 0x111, 57637, 0, , PrScr.bmp - Paint
;команда меню "Файл" - "Сохранить"
PostMessage, 0x111, 57603, 0, , PrScr.bmp - Paint
;команда меню "Файл" - "Выход"
PostMessage, 0x111, 57665, 0, , PrScr.bmp - Paint
;ждём завершения работы Paint
WinWaitClose, PrScr.bmp - Paint
Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

2 (изменено: teadrinker, 2009-07-30 21:20:40)

Re: AutoHotkey: сохранение скриншота экрана в файл

Следующий скрипт даёт возможность сохранить в файл скриншот произвольно выбранной области экрана. Управление через контекстное меню главного окна.
Перед запуском убедитесь, что Ваша версия AHK не ниже, чем 1.0.48. Если Ваша ОС старше, чем Windows XP, Вам потребуется скачать и поместить в директорию скрипта gdiplus.dll.
Пред началом работы прочитайте Help (F1).

    #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     Чтобы получить скриншот области экрана, разместите ок
но точно над ней и кликните дважды в пределах окна или нажмите PrintScreen. Изображени
е будет помещено в буфер обмена и записано в файл
, который появится в выбранной папке (по умолчанию – в папке скрипта).`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, 0, Quality)
    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)
    If    sFile = 0
        SetClipboardData(hBM)
    Else
        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)
}

Функции CaptureScreen(), SetCursor(), SetSystemCursor() и Control_Colors() взяты с оф. форума и приспособлены для данного скрипта.
Функции Ini_WriteSect(), Ini_ReadSect(), Trans() и GotoLineUp() написаны для общего случая и предназначены для использования через библиотеку.
Если кто-нибудь захочет задать вопрос по работе скрипта или сообщить о замеченных багах — прошу писать в эту тему.

Post's attachments

ScreenCatcher.zip 235.92 kb, 640 downloads since 2009-07-26 

You don't have the permssions to download the attachments of this post.
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3 (изменено: teadrinker, 2010-11-18 21:46:52)

Re: AutoHotkey: сохранение скриншота экрана в файл

Новая версия предыдущего скрипта.
Добавлено:
Возможность работы под AHK_Lw. При этом скрипт должен быть соханён в формате UTF-8.
Возможность запуска при загрузке системы, при этом окно скрипта изначально будет скрыто.
Возможность делать скриншоты чаще, чем раз в секунду.
Возможность включения в скриншот курсора.

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

#Requires AutoHotkey v1

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

icoPath = %A_ScriptDir%\ScreenCatcher.ico
if (FileExist(icoPath) && !A_IsCompiled)
    Menu, Tray, Icon, % icoPath

If !pToken := GdipStart()
{
    MsgBox, 48, Ошибка GDI+!
        , Убедитесь в наличии gdiplus.dll в вашей системе!
    ExitApp
}

Ini_ReadSect("Color-Transparent", "Red", Red_, "FF"
    , "Green", Green_, "C7"
    , "Blue", Blue_, "00"
    , "Transparent", Trans, 130)

Ini_ReadSect("Settings", "Output", Output, "File"
    , "Out Directory", OutDirectory, A_ScriptDir
    , "Extension", ext, "bmp"
    , "Capture Cursor", CaptureCursor, 0
    , "High Speed", HighSpeed, 0
    , "Resize Pointers", ResizePointers, "Cursors"
    , "Quality JPEG", Quality, 100)

Menu, Tray, NoStandard
Menu, Tray, Add, Hide Pause, Pause
Menu, Tray, Add
Menu, Tray, Add, Help F1, Help
if !A_IsCompiled
{
    Menu, Tray, Add
    Menu, Tray, Add, Reload, Reload
    Menu, Tray, Add, Edit, Edit
}
Menu, Tray, Add
Menu, Tray, Add, Exit, ExitApp

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

Menu, OutDirectory, Add, % OutDirectory, OutDirectory
Menu, OutDirectory, Add, Change 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
if Output = File
    Menu, Extensions, Check, %ext%

Menu, Output, Add, Clipboard, OutClip
Menu, Output, Add, File, :Extensions
Menu, Output, Check, % Output

Menu, MainMenu, Add, % "Color – Transparent ", Settings
Menu, MainMenu, Add
Menu, MainMenu, Add, Resize Pointers, :ResizePointers
Menu, MainMenu, Add, Out Directory, :OutDirectory
Menu, MainMenu, Add, Output, :Output
Menu, MainMenu, Add
Menu, MainMenu, Add, Capture Cursor, CaptureCursor
if CaptureCursor
    Menu, MainMenu, Check, Capture Cursor

Menu, MainMenu, Add, High Speed, HighSpeed
if HighSpeed
    Menu, MainMenu, Check, High Speed

Menu, MainMenu, Add, Run on Windows Startup, Startup
FileGetShortcut, % A_Startup "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1.lnk")
    , OutTarget,, OutArgs
if (OutTarget = A_ScriptFullPath && OutArgs = 1)
{
    Menu, MainMenu, Check, Run on Windows Startup
    Startup = 1
}
Menu, MainMenu, Add
Menu, MainMenu, Add, Save F12, AreaScreenshot
Menu, MainMenu, Add, Hide Pause, HideShow
Menu, MainMenu, Add
Menu, MainMenu, Add, Help F1, Help
Menu, MainMenu, Add
Menu, MainMenu, Add, Exit, ExitApp

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 +0xE hwndText" a_index "ID " Location%a_index%

Gosub, MarkerColor

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

if 1 = 1
{
    Gui, Show, h200 w200 Hide, ScreenСatcher
    GuiVisible := 0
    Menu, Tray, Rename, Hide Pause, Show Pause
}
Else
{
    Gui, Show, h200 w200, ScreenСatcher
    Melt(ID, Trans, 1), GuiVisible := 1
}

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

Hotkey, LButton, WinResize, Off
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

GuiClose:
    Gosub, HideShow
Return

GuiEscape:
    Gosub, HideShow
Return

GuiContextMenu:
    RestoreCursors()
    Menu, MainMenu, Show
Return

QualityOK:
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
CheckOutput:
    Menu, Output, UnCheck, Clipboard
    Menu, Output, Check, File
    Output = File
Return

SetQuality:
    Old_Quality := Quality
    Menu, Extensions, UnCheck, %ext%
    Menu, Extensions, Check, % (ext := "jpg")
    Gosub, CheckOutput
    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%
    Gosub, CheckOutput
Return

OutClip:
    Menu, Output, UnCheck, File
    Menu, Extensions, UnCheck, %ext%
    Menu, Output, Check, Clipboard
    Output = Clipboard
Return

OutDirectory:
    if A_ThisMenuItem = Change OutDirectory
    {
        Old_OutDirectory := OutDirectory
        Gosub, HideShow
        FileSelectFolder, OutDir, *%OutDirectory%, 3, Select Out Directory:
        OutDirectory := OutDir ? OutDir : OutDirectory
        if (OutDirectory != Old_OutDirectory)
            Menu, OutDirectory, Rename, %Old_OutDirectory%, %OutDirectory%
        if !GuiVisible
            Gosub, HideShow
    }
    Else
        Run, % OutDirectory
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

CaptureCursor:
    CaptureCursor := !CaptureCursor
    Menu, MainMenu, % CaptureCursor ? "Check" : "UnCheck", Capture Cursor
Return

HighSpeed:
    HighSpeed := !HighSpeed
    Menu, MainMenu, % HighSpeed ? "Check" : "UnCheck", High Speed
Return

Startup:
    if Startup := !Startup
    {
        FileCreateShortcut, % A_ScriptFullPath
            , % A_Startup "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1.lnk")
            , % A_ScriptDir, 1
        Menu, MainMenu, Check, Run on Windows Startup
    }
    Else
    {
        FileDelete, % A_Startup "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1.lnk")
        Menu, MainMenu, UnCheck, Run on Windows Startup
    }
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
        SetColorToControl(Text%a_index%ID, 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
    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.`r`n
`r`n                                        Работа с программой.`r`n`r`n     После запу
ска файла на экране появляется полупрозрачное окно, которое можно перемещать левой кнопко
й мыши и менять его размеры.`r`n`r`n     Чтобы получить скриншот области экрана, размести
те окно точно над ней и кликните дважды в пределах окна или нажмите F12. В зависимос
ти от установок, доступных через меню, изображение будет помещено либо в буфер обмена
, либо записано в файл, который появится в папке вывода (по умолчанию – в папке скрипта)
. Перед получением скриншота окно программы можно скрыть, если оно мешает, нажатием клав
иши Pause или средней кнопки мыши. В этом случае программа сработает при нажатии F12.
`r`n     Чтобы получить скриншот всего экрана, скройте окно программы и нажмите PrintScre
en.`r`n     Для получения скриншота активного окна нажмите Shift + PrintScreen
.`r`n`r`n     Управление программой осуществляется горячими клавишами, через контекстно
е меню главного окна (клик правой кнопкой мыши в пределах окна) и меню иконки программ
ы в трее (клик правой кнопкой мыши на иконке программы в трее)
.`r`n`r`n                                          Контекстное меню.`r`n`r`nColo
r – Transparent.`r`nУстановки цвета и прозрачности окна.`r`n`r`nResize Pointers.`r`nВыбо
р индикатора, отображаемого при изменении размеров окна: модифицированный курсор мыши, либ
о цветные маркеры.`r`n`r`nOut Directory.`r`nПри выборе этого пункта появляется подменю с н
азванием текущей папки, в которую будут помещаться файлы скриншотов. Для смены папки кликн
ите это подменю.`r`n`r`nOutput.`r`nПри выборе подменю Clipboard скриншот будет записыватьс
я в буфер обмена. File — выбор расширения файлов, в которые будут записываться скриншоты
. При выборе JPG открывается подменю с двумя пунктами. 1-ый – текущее значение качества (с
тепени сжатия) JPEG, кликните его, если оно Вас устраивает. 2-ой – Change Quality – смен
а качества JPEG.`r`n`r`nCapture Cursor.`r`nПри установке галочки в этот пункт меню в скрин
шот будет включен курсор.`r`n`r`nHigh Speed.`r`nЕсли преполагается делать скриншоты чаще
, чем раз в секунду, поставьте галочку в этот пункт меню. При выборе High Speed перед пол
учением скришота лучше скрыть окно скрипта. В этом режиме к названию файла бу
дут добавляться милисекунды.`r`n`r`nRun on Windows Startup.`r`nПри выборе этого пункта созд
аётся ярлык программы в папке автозагрузки текущего пользователя, и при следующей загрузк
е программа запустится автоматически, окно её первоначально будет скрыто. При снятии галочк
и с этого пункта ярлык удаляется.`r`n`r`nSave.`r`nПолучить скриншот области экрана под окно
м программы.`r`n`r`nHide.`r`nСпрятать окно программы
.`r`n`r`n                                          Меню иконки в трее.`r`n`r`nHide.`r`nСп
рятать окно программы.`n`nShow.`nПоказать окно программы.`r`n
`r`n                                            Горячие клавиши.`n`nMButton (средняя к
нопка мыши) — скрыть окно.`nCtrl + MButton — скрыть/показать окно.`nPause – скрыть/показат
ь окно.`nScrollLock – показать окно в центре экрана.`nF12 – скриншот области экрана, лежаще
й непосредственно под окном программы.`nPrintScreen — скриншот всего экрана.`nShift + Print
Screen – скриншот активного окна.`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
Return

Reload:
Reload
Return

Edit:
Edit
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:
    Gui, 5:Destroy
Return

Exit:
GdipShutdown(pToken)
While (idx := a_index + 2) < 6
    IfWinExist, % "ahk_id" ID%idx%
        Gosub, %idx%GuiClose
if GuiVisible
{
    Melt(ID, Trans, 0)
    Gui, Destroy
}
RestoreCursors()

Ini_WriteSect("Color-Transparent", "Red", Red_
    , "Green", Green_
    , "Blue", Blue_
    , "Transparent", Trans)

Ini_WriteSect("Settings", "Output", Output
    , "Out Directory", OutDirectory
    , "Extension", ext
    , "Capture Cursor", CaptureCursor
    , "High Speed", HighSpeed
    , "Resize Pointers", ResizePointers
    , "Quality JPEG", Quality)
ExitApp:
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, AreaScreenshot
}

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" _Red _Green _Blue
}

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 "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1.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 "\" RegExReplace(A_ScriptName, "(.*)\..*", "$1.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}
}

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%, ptr)
        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%, ptr)
    DllCall("SetSystemCursor", ptr, CursorHandle, Int, IDC_ARROW)
}

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

SetColorToControl(hwnd, Color)
{
    WinGetPos,,, w, h, ahk_id %hwnd%
    sColor := 0xFF000000|Color
    DllCall("gdiplus\GdipCreateSolidFill", Int, sColor, "ptr*", pBrush)
    DllCall("gdiplus\GdipCreateBitmapFromScan0", Int, w
        , Int, h, Int, 0, Int, 0x26200A, UInt, 0, "ptr*", pBitmap)
    DllCall("gdiplus\GdipGetImageGraphicsContext", ptr, pBitmap, "ptr*", G)
    DllCall("gdiplus\GdipFillRectangle"
        , ptr, G, ptr, pBrush, "float", 0, "float", 0, "float", w, "float", h)
    DllCall("gdiplus\GdipCreateHBITMAPFromBitmap"
        , ptr, pBitmap, "ptr*", hBitmap, Int, 0xffffffff)
    SendMessage, STM_SETIMAGE := 0x172, 0x0, hBitmap,, ahk_id %hwnd%
    DllCall("DeleteObject", ptr, ErrorLevel)
    DllCall("gdiplus\GdipDeleteBrush", ptr, pBrush)
    DllCall("gdiplus\GdipDeleteGraphics", ptr, G)
    DllCall("gdiplus\GdipDisposeImage", ptr, pBitmap)
    DllCall("DeleteObject", ptr, hBitmap)
}

CaptureScreen(aRect, sFile, nQuality, Cursor)
{
    pBitmap := BitmapFromScreen(aRect, Cursor, 0x40000000 | 0x00CC0020)
    If sFile = 0
        SetBitmapToClipboard(pBitmap)
    Else
        SaveBitmapToFile(pBitmap, sFile, nQuality)
    DllCall("gdiplus\GdipDisposeImage", ptr, pBitmap)
}

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

CaptureCursor(hDC, nL, nT)
{
    VarSetCapacity(mi, 16 + A_PtrSize, 0)
    NumPut(16 + A_PtrSize, mi)
    DllCall("GetCursorInfo", ptr, &mi)
    bShow := NumGet(mi, 4, "UInt")
    hCursor := NumGet(mi, 8)
    xCursor := NumGet(mi, 8 + A_PtrSize, "UInt")
    yCursor := NumGet(mi, 12 + A_PtrSize, "UInt")

    If bShow && hCursor:=DllCall("CopyIcon", ptr, hCursor, ptr)
    {
        VarSetCapacity(ni, 8 + A_PtrSize * 3, 0)
        DllCall("GetIconInfo", ptr, hCursor, ptr, &ni)
        bIcon := NumGet(ni, 0, "UInt")
        xHotspot := NumGet(ni, 4, "UInt")
        yHotspot := NumGet(ni, 8, "UInt")
        hBMMask := NumGet(ni, 8 + A_PtrSize)
        hBMColor := NumGet(ni, 8 + A_PtrSize * 2)

        DllCall("DrawIcon", ptr, hDC, Int, xCursor - xHotspot - nL
            , Int, yCursor - yHotspot - nT, ptr, hCursor)
        DllCall("DestroyIcon", ptr, hCursor)
        If hBMMask
            DllCall("DeleteObject", ptr, hBMMask)
        If hBMColor
            DllCall("DeleteObject", ptr, hBMColor)
    }
}

SetBitmapToClipboard(pBitmap) {
    ; modified by Marius Șucan to have this function report errors

    Static Ptr := "UPtr"
    off1 := A_PtrSize = 8 ? 52 : 44
    off2 := A_PtrSize = 8 ? 32 : 24

    pid := DllCall("GetCurrentProcessId","uint")
    hwnd := WinExist("ahk_pid " . pid)
    r1 := DllCall("OpenClipboard", Ptr, hwnd)
    If !r1
        Return -1

    hBitmap := CreateHBITMAPFromBitmap(pBitmap, 0)
    If !hBitmap
    {
        DllCall("CloseClipboard")
        Return -3
    }

    r2 := DllCall("EmptyClipboard")
    If !r2
    {
        DllCall("DeleteObject", ptr, hBitmap)
        DllCall("CloseClipboard")
        Return -2
    }

    DllCall("GetObject", Ptr, hBitmap, "int", VarSetCapacity(oi, A_PtrSize = 8 ? 104 : 84, 0), Ptr, &oi)
    hdib := DllCall("GlobalAlloc", "uint", 2, Ptr, 40+NumGet(oi, off1, "UInt"), Ptr)
    pdib := DllCall("GlobalLock", Ptr, hdib, Ptr)
    DllCall("RtlMoveMemory", Ptr, pdib, Ptr, &oi+off2, Ptr, 40)
    DllCall("RtlMoveMemory", Ptr, pdib+40, Ptr, NumGet(oi, off2 - A_PtrSize, Ptr), Ptr, NumGet(oi, off1, "UInt"))
    DllCall("GlobalUnlock", Ptr, hdib)
    DllCall("DeleteObject", ptr, hBitmap)
    r3 := DllCall("SetClipboardData", "uint", 8, Ptr, hdib) ; CF_DIB = 8
    DllCall("CloseClipboard")
    DllCall("GlobalFree", Ptr, hdib)
    E := r3 ? 0 : -4 ; 0 - success
    Return E
}

CreateHBITMAPFromBitmap(pBitmap, Background:=0xffffffff) {
    ; background should be zero, to not alter alpha channel of the image
    hBitmap := 0
    DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "UPtr", pBitmap, "UPtr*", hBitmap, "int", Background)
    return hBitmap
}

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

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

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

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

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

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

#IfWinExist ScreenСatcher ahk_class AutoHotkeyGUI
    MButton:: Goto, HideShow

#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
F12:: ; Скриншот области под окном скрипта
AreaScreenshot:
    Critical
    OutFileName := A_Year A_MM A_DD "-" A_Hour A_Min A_Sec (HighSpeed ? "-" A_MSec : "")
    IfWinExist, ahk_id %ID%
    {
        Vis = 1
        WinGetPos, X, Y, W, H, ahk_id %ID%
        Melt(ID, Trans, 0, 50)
    }
    Else
    {
        Vis = 0
        DetectHiddenWindows, On
        WinGetPos, X, Y, W, H, ahk_id %ID%
    }
    Rect := X "|" Y "|" W "|" H

    IfNotExist, % OutDirectory
        OutDirectory := A_ScriptDir

    if Output = File
        CaptureScreen(Rect, OutDirectory "\" OutFileName "." ext, Quality, CaptureCursor)
    Else
        CaptureScreen(Rect, 0, Quality, CaptureCursor)
    if Vis = 1
        Melt(ID, Trans, 1, 50)
Return

PrintScreen:: ; Скриншот всего экрана
    Critical
    OutFileName := A_Year A_MM A_DD "-" A_Hour A_Min A_Sec (HighSpeed ? "-" A_MSec : "")
    if Output = File
        CaptureScreen(0, OutDirectory "\" OutFileName "." ext, Quality, CaptureCursor)
    Else
        CaptureScreen(0, 0, Quality, CaptureCursor)
Return

+PrintScreen:: ; Shift + PrintScreen — Скриншот активного окна
    Critical
    OutFileName := A_Year A_MM A_DD "-" A_Hour A_Min A_Sec (HighSpeed ? "-" A_MSec : "")
    WinGetPos, X, Y, W, H, A
    Rect := X "|" Y "|" W "|" H
    if Output = File
        CaptureScreen(Rect, OutDirectory "\" OutFileName "." ext, Quality, CaptureCursor)
    Else
        CaptureScreen(Rect, 0, Quality, CaptureCursor)
Return

^MButton:: ; Ctrl + MButton — показать/скыть окно
    Pause::
HideShow:
    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

Если кто-нибудь захочет задать вопрос по работе скрипта или сообщить о замеченных багах — прошу писать в эту тему.
В архиве скрипт, иконка и скомпилированный файл.

Post's attachments

ScreenCatcher.zip 240.11 kb, 367 downloads since 2010-11-18 

You don't have the permssions to download the attachments of this post.
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder