Загрузка данных


#NoEnv
#SingleInstance Force


F3::

    ; ========================================================
    ; ОБЛАСТЬ СКРИНШОТА
    ; ========================================================

    X := 0
    Y := 0

    Width := 500
    Height := 500


    ; ========================================================
    ; ПОЛУЧАЕМ DC ЭКРАНА
    ; ========================================================

    hdcScreen := DllCall("GetDC", "UInt", 0)

    if (!hdcScreen)
    {
        MsgBox, 16, Ошибка, Не удалось получить DC экрана.
        return
    }


    ; ========================================================
    ; СОЗДАЁМ MEMORY DC
    ; ========================================================

    hdcMem := DllCall("gdi32\CreateCompatibleDC", "UInt", hdcScreen)

    if (!hdcMem)
    {
        DllCall("ReleaseDC", "UInt", 0, "UInt", hdcScreen)

        MsgBox, 16, Ошибка, Не удалось создать Memory DC.
        return
    }


    ; ========================================================
    ; СОЗДАЁМ BITMAP
    ; ========================================================

    hBitmap := DllCall("gdi32\CreateCompatibleBitmap", "UInt", hdcScreen, "Int", Width, "Int", Height)

    if (!hBitmap)
    {
        DllCall("gdi32\DeleteDC", "UInt", hdcMem)
        DllCall("ReleaseDC", "UInt", 0, "UInt", hdcScreen)

        MsgBox, 16, Ошибка, Не удалось создать Bitmap.
        return
    }


    ; ========================================================
    ; ВЫБИРАЕМ BITMAP
    ; ========================================================

    hOld := DllCall("gdi32\SelectObject", "UInt", hdcMem, "UInt", hBitmap)


    ; ========================================================
    ; КОПИРУЕМ ЭКРАН
    ; ========================================================

    Result := DllCall("gdi32\BitBlt", "UInt", hdcMem, "Int", 0, "Int", 0, "Int", Width, "Int", Height, "UInt", hdcScreen, "Int", X, "Int", Y, "UInt", 0x00CC0020)


    if (!Result)
    {
        ErrorCode := DllCall("GetLastError")

        DllCall("gdi32\SelectObject", "UInt", hdcMem, "UInt", hOld)
        DllCall("gdi32\DeleteObject", "UInt", hBitmap)
        DllCall("gdi32\DeleteDC", "UInt", hdcMem)
        DllCall("ReleaseDC", "UInt", 0, "UInt", hdcScreen)

        MsgBox, 16, Ошибка, BitBlt не смог сделать захват.`nКод: %ErrorCode%
        return
    }


    ; ========================================================
    ; ВОЗВРАЩАЕМ СТАРЫЙ OBJECT
    ; ========================================================

    DllCall("gdi32\SelectObject", "UInt", hdcMem, "UInt", hOld)


    ; ========================================================
    ; УДАЛЯЕМ DC
    ; ========================================================

    DllCall("gdi32\DeleteDC", "UInt", hdcMem)

    DllCall("ReleaseDC", "UInt", 0, "UInt", hdcScreen)


    ; ========================================================
    ; ПОЛУЧАЕМ BITMAPINFO
    ; ========================================================

    VarSetCapacity(BitmapInfo, 40, 0)

    NumPut(40, BitmapInfo, 0, "UInt")
    NumPut(Width, BitmapInfo, 4, "Int")
    NumPut(-Height, BitmapInfo, 8, "Int")
    NumPut(1, BitmapInfo, 12, "UShort")
    NumPut(32, BitmapInfo, 14, "UShort")
    NumPut(0, BitmapInfo, 16, "UInt")
    NumPut(0, BitmapInfo, 20, "UInt")
    NumPut(0, BitmapInfo, 24, "Int")
    NumPut(0, BitmapInfo, 28, "Int")
    NumPut(0, BitmapInfo, 32, "UInt")
    NumPut(0, BitmapInfo, 36, "UInt")


    ; ========================================================
    ; РАЗМЕР ДАННЫХ
    ; ========================================================

    ImageSize := Width * Height * 4


    ; ========================================================
    ; ВЫДЕЛЯЕМ ПАМЯТЬ ПОД ПИКСЕЛИ
    ; ========================================================

    VarSetCapacity(Pixels, ImageSize, 0)


    ; ========================================================
    ; ПОЛУЧАЕМ ПИКСЕЛИ ИЗ HBITMAP
    ; ========================================================

    Result := DllCall(
        "gdi32\GetDIBits",
        "UInt", DllCall("GetDC", "UInt", 0),
        "UInt", hBitmap,
        "UInt", 0,
        "UInt", Height,
        "UInt", &Pixels,
        "UInt", &BitmapInfo,
        "UInt", 0
    )


    ; ========================================================
    ; УДАЛЯЕМ BITMAP
    ; ========================================================

    DllCall("gdi32\DeleteObject", "UInt", hBitmap)


    if (!Result)
    {
        MsgBox, 16, Ошибка, GetDIBits не смог получить пиксели.
        return
    }


    ; ========================================================
    ; СОЗДАЁМ BMP HEADER
    ; ========================================================

    FileHeaderSize := 14
    InfoHeaderSize := 40

    FileSize := FileHeaderSize + InfoHeaderSize + ImageSize


    VarSetCapacity(FileHeader, 14, 0)

    NumPut(0x4D42, FileHeader, 0, "UShort")
    NumPut(FileSize, FileHeader, 2, "UInt")
    NumPut(0, FileHeader, 6, "UShort")
    NumPut(0, FileHeader, 8, "UShort")
    NumPut(54, FileHeader, 10, "UInt")


    ; ========================================================
    ; СОХРАНЯЕМ BMP
    ; ========================================================

    FilePath := A_ScriptDir "\TEST_SCREEN.bmp"


    FileDelete, %FilePath%


    File := FileOpen(FilePath, "w")

    if (!IsObject(File))
    {
        MsgBox, 16, Ошибка, Не удалось открыть BMP-файл для записи.
        return
    }


    File.RawWrite(FileHeader, 14)

    File.RawWrite(BitmapInfo, 40)

    File.RawWrite(Pixels, ImageSize)

    File.Close()


    ; ========================================================
    ; ПРОВЕРКА
    ; ========================================================

    if (!FileExist(FilePath))
    {
        MsgBox, 16, Ошибка, BMP-файл не был создан.
        return
    }


    MsgBox, 64, УСПЕХ!, BMP успешно создан!`n`n%FilePath%

return