1 (изменено: Clannad5, 2022-07-07 19:24:21)

Тема: AHK: Сохранение скриншота из буфера обмена Win11

Здравствуйте!
Перерыл весь интернет, но так и не нашел способа сохранять изображение из буфера обмена.

Цель:

1. Нажать PrntScrn.
2. Нажать F2 чтобы активировать скрипт.
3. Когда скрипт активирован, сохранить скриншот из буфера обмена в формате jpg.

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

Самый главный вопрос "Как сохранить буферезированное изображение, которое я либо скопировал в браузере, либо сделал его через PrntScrn?".
Буду рад, если сможете мне с этим помочь!

2

Re: AHK: Сохранение скриншота из буфера обмена Win11

Нашел способ с gdiplus библиотекой:


setbatchlines -1
DllCall("LoadLibrary", "str", "gdiplus")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0) ; sizeof(GdiplusStartupInput) = 16, 24
NumPut(0x1, si, "uint")
DllCall("gdiplus\GdiplusStartup", "ptr*", pToken:=0, "ptr", &si, "ptr", 0)
extension := "jpg"
DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", count:=0, "uint*", size:=0)
VarSetCapacity(ci, size)
DllCall("gdiplus\GdipGetImageEncoders", "uint", count, "uint", size, "ptr", &ci)
if !(count && size)
   throw Exception("Could not get a list of image codec encoders on this system.")
Loop % count
   EncoderExtensions := StrGet(NumGet(ci, (idx:=(48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize, "uptr"), "UTF-16")
      until InStr(EncoderExtensions, "*." extension)
if !(pCodec := &ci + idx)
   throw Exception("Could not find a matching encoder for the specified file format.")

   if !DllCall("IsClipboardFormatAvailable", "UInt", CF_BITMAP := 2)
      throw "There is no image in the Clipboard"
   if !DllCall("OpenClipboard", "Ptr", 0)
      throw "OpenClipboard failed"
   hDIB := DllCall("GetClipboardData", "UInt", CF_DIB := 8, "Ptr")
   image  := DllCall("GetClipboardData", "UInt", CF_BITMAP := 2, "Ptr")
   DllCall("CloseClipboard")
   if !hDIB
      throw "GetClipboardData failed"
   pDIB := DllCall("GlobalLock", "Ptr", hDIB)
   width  := NumGet(pDIB +  4, "UInt")
   height := NumGet(pDIB +  8, "UInt")
   bpp    := NumGet(pDIB + 14, "UShort")
   DllCall("GlobalUnlock", "Ptr", pDIB)
   if (bpp != 32)
      DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", image, "Ptr", 0, "Ptr*", pBitmap)
   else
   {
      hdc := DllCall("CreateCompatibleDC", "Ptr", 0, "Ptr")
      obm := DllCall("SelectObject", "Ptr", hdc, "Ptr", image, "Ptr")
   
      cdc := DllCall("CreateCompatibleDC", "Ptr", hdc, "Ptr")
      VarSetCapacity(bi, 40, 0)
      NumPut(width, bi, 4, "uint")
      , NumPut(-height, bi, 8, "uint")
      , NumPut(40, bi, 0, "uint")
      , NumPut(1, bi, 12, "ushort")
      , NumPut(0, bi, 16, "uInt")
      , NumPut(bpp, bi, 14, "ushort")
      hbm := DllCall("CreateDIBSection", "Ptr", hdc, "Ptr", &bi, "uint", 0, "ptr*", pBits, "Ptr", 0, "uint", 0, "Ptr")
      oB2 := DllCall("SelectObject", "Ptr", cdc, "Ptr", hbm, "Ptr")

      DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", 0x26200A, "Ptr", 0, "Ptr*", pBitmap)

      VarSetCapacity(Rect, 16, 0)
      , NumPut( width, Rect,  8, "uint")
      , NumPut(height, Rect, 12, "uint")
      VarSetCapacity(BitmapData, 16+2*(A_PtrSize ? A_PtrSize : 4), 0)
      , NumPut(width, BitmapData, 0, "uint") ; Width
      , NumPut(height, BitmapData, 4, "uint") ; Height
      , NumPut(4 * width, BitmapData,  8,   "int") ; Stride
      , NumPut(0xE200B, BitmapData, 12, "int") ; PixelFormat
      , NumPut(pBits, BitmapData, 16, "ptr") ; Scan0
      DllCall("gdiplus\GdipBitmapLockBits", "ptr", pBitmap, "ptr", &Rect, "uint", 7, "int", 0xE200B, "ptr", &BitmapData)
      DllCall("BitBlt", "Ptr", cdc, "Int", 0, "Int", 0, "Int", width, "Int", height, "Ptr", hDC , "Int", 0, "Int", 0, "UInt", SRCCOPY := 0x00CC0020)
      DllCall("gdiplus\GdipBitmapUnlockBits", "ptr",pBitmap, "ptr",&BitmapData)

      DllCall("SelectObject", "Ptr", cdc, "Ptr", ob2, "Ptr")
      DllCall("DeleteDC", "Ptr", cdc)
      DllCall("SelectObject", "Ptr", hdc, "Ptr", obm, "Ptr")
      DllCall("DeleteDC", "Ptr", hdc)
      DllCall("DeleteObject", "Ptr", hbm)
   }
   DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "WStr", "gdi" ".jpg", "Ptr", pCodec, "UInt",0)
   DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
   DllCall("DeleteObject", "Ptr", image)

Вопрос исчерпан.