Плагин ScreenShot.spf

Обсуждение программ nnCron и nnCron LITE

Плагин ScreenShot.spf

Postby dothen » Fri, 28 Apr 2017, 03:43

Делает снимок экрана, окна или прямоугольника, и сохраняет изображение в файл в формате BMP, GIF, PNG, JPG, TIFF.

Code: Select all
\ Файл:       screenshot.spf
\ Автор:      dothen
\ Дата:       28.04.2017
\ Версия:     1.0
\ Описание:
\ Делает снимок экрана, окна или прямоугольника, и сохраняет изображение в файл в формате BMP, GIF, PNG, JPG, TIFF.

\ Подключить плагин extwords.spf

\ Опции:
\ ActivateWindow    - Активизировать окно перед тем как сделать снимок. По умолчанию нет.
\ EnableCursor      - Включает в снимок курсор мыши. По умолчанию нет.
\ EnableTransparent - Включает в снимок полупрозрачные окна, расположенные поверх снимаемого окна. По умолчанию нет. Не участвует в методе FullWindowMethod.

\ Снимок можно делать одним из трех методов: (По умолчанию ClipWindowMethod)
\ SizeWindowMethod - Метод без отсечения. Часть окна, которая выходит за пределы экрана, будет закрашена черным цветом.
\ ClipWindowMethod - Метод с отсечением по границам рабочего стола, или всего экрана если окно TOPMOST.
\ FullWindowMethod - Метод делает снимок целого окна даже если оно перекрыто другими окнами или находится за пределами экрана.

\ Если снимаемое окно полупрозрачное то метод SizeWindowMethod делает снимок целого окна или любого дочернего окна,
\ даже если оно перекрыто другими окнами или находится за пределами экрана.
\ --------------------------------

\ SCREENSHOT ( hwnd -- )
\ Сохранить скриншот указанного окна в файл заданный в настройках.

\ SCREENSHOT-WINDOW ( -- )
\ Сохранить скриншот активного окна в файл заданный в настройках.

\ SCREENSHOT-DESKTOP ( -- )
\ Сохранить скриншот экрана в файл заданный в настройках.

\ SCREENSHOT-FROM-POINT ( -- )
\ Сохранить скриншот окна под курсором в файл заданный в настройках.

\ SCREENSHOT-FROM-CLIPBOARD ( -- )
\ Сохранить скриншот окна, идентификатор которого находится в буфере обмена.

\ (SCREENSHOT) ( hwnd addr-fname -- )
\ Сохранить скриншот указанного окна в указанный файл.

\ SCREENSHOT-RECT ( x y width height hwnd addr-fname -- )
\ Сохранить скриншот указанного прямоугольника указанного окна в указанный файл (координаты относительные).

\ SCREENSHOT# ( x y width height -- )
\ Сохранить скриншот указанного прямоугольника активного окна в файл заданный в настройках.

\ MULTISCREENSHOT  ( sum msec hwnd addr-fname -- )
\ MULTI-SCREENSHOT ( sum msec hwnd -- )
\ Съемка серии скриншотов с коротким интервалом между снимками. Метод FullWindowMethod в MULTI-SCREENSHOT работает нестабильно.
\ sum  - Количество снимков.
\ msec - Пауза в миллисекундах после каждого снимка.
\ hwnd - Дескриптор окна.
\ addr-fname - Адрес строки с полным именем файла. Файлы с одинаковыми именами перезаписываются (поэтому EVAL-SUBST делается внутри слова).


\ ScreenshotFileName: "filename"
\ MultiScreenshotFileName: "filename"
\ Задает имя файла для скриншота и мультискриншота.
\ Снимок можно сохранить в формате: bmp, gif, png, jpg, tiff.
\ Если указать другое или никакое расширение то по умолчанию png.

\ xhwnd  ( -- a u ) \ Дескриптор окна для добавления в имя файла.
\ WinTxt ( -- a u ) \ Заголовок окна для добавления в имя файла.

\ MultiMax - константа устанавливает максимальное число снимков в серийной съемке (по умолчанию 100, можно менять).
\ ------------------------


WINAPI: DeleteDC GDI32.DLL
WINAPI: CreateCompatibleDC GDI32.DLL
WINAPI: CreateCompatibleBitmap GDI32.DLL
WINAPI: BitBlt GDI32.DLL
WINAPI: PrintWindow USER32.DLL
WINAPI: GetShellWindow USER32.DLL
WINAPI: IntersectRect USER32.DLL
\ WINAPI: CopyImage USER32.DLL

WINAPI: GdiplusStartup GDIPLUS.DLL
WINAPI: GdipCreateBitmapFromHBITMAP GDIPLUS.DLL
WINAPI: GdipSaveImageToFile GDIPLUS.DLL
WINAPI: GdipDisposeImage GDIPLUS.DLL
WINAPI: GdiplusShutdown GDIPLUS.DLL

0 VALUE ScreenshotFileName      \ Адрес строки с именем файла.
0 VALUE MultiScreenshotFileName \ Адрес строки с именем файла.
\ В имя файла надо добавлять время с миллисекундами или %GetTickCount% иначе имена могут совпадать с предыдущими снимками и фалы будут перезаписываться.

100 CONSTANT MultiMax \ Максимальное число снимков в серийной съемке (можно менять).
USER-VALUE WinHwnd \ Дескриптор окна.

USER-VALUE ScreenshotMethod   \ 1 или 0 или -1. По умолчанию 0.
USER-VALUE ActivateWindow?    \ Флаг. Если TRUE то активизировать окно перед тем как сделать снимок. По умолчанию FALSE.
USER-VALUE EnableCursor?      \ Флаг. Если TRUE то включает в снимок курсор мыши. По умолчанию FALSE.
USER-VALUE EnableTransparent? \ Флаг. Если TRUE то включает в снимок полупрозрачные окна, расположенные поверх снимаемого окна (функция BitBlt применяет растровую операцию CAPTUREBLT). По умолчанию FALSE.

: SizeWindowMethod ( -- ) -1 TO ScreenshotMethod ; \ Метод без отсечения.
: ClipWindowMethod ( -- )  0 TO ScreenshotMethod ; \ Метод с отсечением по границам рабочего стола или всего экрана если окно TOPMOST.
: FullWindowMethod ( -- )  1 TO ScreenshotMethod ; \ Метод делает снимок целого окна даже если оно перекрыто другими окнами или находится за пределами экрана.

: ActivateWindow    ( -- ) TRUE TO ActivateWindow? ;
: EnableCursor      ( -- ) TRUE TO EnableCursor? ;
: EnableTransparent ( -- ) TRUE TO EnableTransparent? ;


\ Создает каталог и все промежуточные подкаталоги, если это необходимо.
: DirCreate ( addr-fname -- )
    ASCIIZ> ONLYDIR EVAL-SUBST 2DUP
    EXIST? IF 2DROP ELSE DIR-CREATE THEN
;

: WinExist? ( hwnd -- ? )
    DUP IF IsWindow THEN DUP
    IFNOT
      S" Error: Недействительный дескриптор окна" ?CRON-LOG
    THEN
;

: RectSizeValid? ( b r y x -- ? )
    ROT = -ROT = OR DUP
    IF
      S" WARNING: Высота или ширина окна (прямоугольника) равна нулю." ?CRON-LOG
    THEN
    0=
;

\ Получить прямоугольник который является пересечением двух заданных прямоугольников.
\ Если прямоугольники не пересекаются то возвращает пустой прямоугольник.
: INTERSECT-RECT ( b1 r1 y1 x1 b2 r2 y2 x2 -- b3 r3 y3 x3 )
  { b1 r1 y1 x1 b2 r2 y2 x2 -- b3 r3 y3 x3 }
    0 0 0 0 SP@
    AT x1 AT x2 ROT IntersectRect
    IFNOT
      S" WARNING: Окно вне рабочего стола (прямоугольник вне окна)." ?CRON-LOG
    THEN
;
\ : INTERSECT-RECT1 ( b1 r1 y1 x1 b2 r2 y2 x2 -- b3 r3 y3 x3 )
\  { b1 r1 y1 x1 b2 r2 y2 x2 -- b3 r3 y3 x3 }
\    x1 r2 <
\    y1 b2 < AND
\    r1 x2 > AND
\    b1 y2 > AND
\    IF
\      x1 x2 MAX >R
\      y1 y2 MAX >R
\      r1 r2 MIN >R
\      b1 b2 MIN R> R> R>
\    ELSE
\      S" WARNING: Окно вне рабочего стола (прямоугольник вне окна)." ?CRON-LOG
\      0 0 0 0
\    THEN
\ ;

\ Устанавливает прямоугольник отсечения:
\ Весь рабочий стол - если выбран Рабочий стол, Панель задач или TOPMOST оконо.
\ Рабочий стол минус Панель задач - для всех остальных окон.
\ Т.е. на снимке будет та часть окна которая находится на рабочем столе и не перекрыта панелью задач.
: GetDesktopWorkRect ( hwnd -- b r y x )
    DUP >R TOPMOST?                         \ Окно Поверх всех окон?
    R@ GetDesktopWindow = OR                \ или это Рабочий стол?
\   R> 0 Z" Shell_TrayWnd" FindWindowA = OR \ или это Панель задач?
    R> TOP-PARENT-WINDOW GET-WCLASS
    S" Shell_TrayWnd" COMPARE 0= OR \ Панель задач или её дочернее окно.
    IF
      GetDesktopWindow WIN-RECT
    ELSE
\      GetWorkArea
      0 0 0 0 SP@ 0 SWAP 0 48 SystemParametersInfoA DROP \ #define SPI_GETWORKAREA 48
    THEN
;

\ Получить прямоугольник пересечения окна с рабочим столом.
\ Если окно с таким hwnd не существует или всё окно вне рабочего стола,
\ то слово вернет нулевые координаты, и будет сделан снимок окна нулевого размера.
: DesktopIntersectRect ( hwnd -- b r y x )
    DUP >R GetDesktopWorkRect  \ ( -- b1 r1 y1 x1 )
    R> WIN-RECT                \ ( -- b1 r1 y1 x1 b2 r2 y2 x2 )
    INTERSECT-RECT
;
\ Размеры развернутого окна больше чем размеры WORKAREA на толщину рамок.

\ Если дескриптор окна = Desktop или Progman то установить метод ClipWindowMethod.
: ScreenShotSetValidMethod ( hwnd -- )
    DUP GetDesktopWindow =
    OVER GetShellWindow = OR
    SWAP GET-WCLASS S" WorkerW" COMPARE 0= OR
    IF 0 TO ScreenshotMethod THEN

    ScreenshotMethod ABS 1 >
    IF
      0 TO ScreenshotMethod
      S" WARNING: ScreenshotMethod должен быть равен 1, 0 или -1" ?CRON-LOG
    THEN
;

\ Получить координаты окна относительно самого себя.
: RELWINRECT ( hwnd -- height width 0 0 ) WIN-RECT ROT SWAP - -ROT - SWAP 0 0 ;


\ -------------GDI+-------------
\ С помощью GDI+ будем записывать изображение в файл в нужном формате.
\ Инициализирует библиотеку GDI+
: GDIPLUS-STARTUP ( -- GpToken ? )
   0 SP@ >R    \ GpToken
   0 0 0 1 SP@ \ Структура GdiplusStartupInput
   0 SWAP R> GdiplusStartup DUP >R
   IF S" Error GdiplusStartup" ?CRON-LOG THEN
   2DROP 2DROP \ Удалить структуру GdiplusStartupInput
   R>
;

\ Расширение для SCASE(строковый CASE) из плагина extwords.spf
\ Поддерживает работу с масками используя символы * и ?
: wcSOF ( a1 u1 a2-pat u2-pat -- )
    POSTPONE 2OVER POSTPONE 2SWAP POSTPONE WC-COMPARE
    [COMPILE] IF POSTPONE 2DROP
; IMMEDIATE

\ Выбрать CLSID по расширению файла.
\ (Microsoft предупреждает, что ClsID кодеков могут отличаться в различных версиях библиотеки GDI+.
\ Функции GdipGetImageEncodersSize и GdipGetImageEncoders, позволяют получить ClsID кодека.)
\ Ну, когда станут отличаться, тогда сделаем с функциями, а пока вот так.
: GetCLSID ( addr-fname -- n n n n )
    >R
    0x2EF31EF8 0x0000739A 0x11D31A04 0x557CF400    \ clsidEncoder BMP
    R> ASCIIZ>
    SCASE
      S" *.bmp"  wcSOF NOOP ENDSOF \ {557CF400-1A04-11D3-9A73-0000F81EF32E}
      S" *.jpg"  wcSOF 1 +  ENDSOF \ {557CF401-1A04-11D3-9A73-0000F81EF32E}
      S" *.jpeg" wcSOF 1 +  ENDSOF \ {557CF401-1A04-11D3-9A73-0000F81EF32E}
      S" *.gif"  wcSOF 2 +  ENDSOF \ {557CF402-1A04-11D3-9A73-0000F81EF32E}
      S" *.tiff" wcSOF 5 +  ENDSOF \ {557CF405-1A04-11D3-9A73-0000F81EF32E}
      S" *.png"  wcSOF 6 +  ENDSOF \ {557CF406-1A04-11D3-9A73-0000F81EF32E}
      S" *"      wcSOF 6 +  ENDSOF
    ENDSCASE
;

\ Сохранить снимок в файл.
: BITMAP2FILE ( hBitmap addr-fname -- )
  { hBitmap file \ GpToken GpBitmap &4 &3 &2 clsid -- }

    GDIPLUS-STARTUP IF DROP EXIT ELSE TO GpToken THEN

    file GetCLSID TO clsid TO &2 TO &3 TO &4
    file ASCIIZ> S>UNICODE DROP TO file

    AT GpBitmap 0 hBitmap GdipCreateBitmapFromHBITMAP DROP
    0 AT clsid file GpBitmap GdipSaveImageToFile IF S" Error GdipSaveImageToFile" ?CRON-LOG THEN
    GpBitmap GdipDisposeImage DROP
    GpToken GdiplusShutdown DROP \ Выгружаем библиатеку gdi+
    file FREE DROP \ Освободить память от S>UNICODE
;


\ ------------Курсор------------
WINAPI: GetCursorInfo USER32.DLL
WINAPI: GetIconInfo USER32.DLL
WINAPI: DrawIcon USER32.DLL

\ Получить дескриптор основного курсора.
: GET-CURSOR ( -- hCursor )
    0 0 0 1 20 SP@ GetCursorInfo DROP 2DROP NIP NIP
;
\ Функция GetCursor извлекает дескриптор текущего курсора который принадлежит вызывающему потоку, а нам нужен основной курсор.

\ Координаты острия(фокуса) курсора на точечном рисунке курсора, относительно левого верхнего угла рисунка курсора.
: HOTSPOT-CURSOR ( -- y x )
    0 0 0 0 0 SP@ GET-CURSOR GetIconInfo 2DROP 2SWAP
    DeleteObject DROP DeleteObject DROP
;

\ Координаты точечного рисунка курсора мыши относительно левого верхнего угла окна.
: CURSOR-POS ( hwnd -- y x )
    ScreenshotMethod 0<>
    IF WIN-POS ELSE DesktopIntersectRect 2SWAP 2DROP SWAP THEN
    MOUSE-POS ROT - >R SWAP - R> SWAP \ Координаты острия курсора относительно левого верхнего угла окна.
    HOTSPOT-CURSOR ROT SWAP - >R - R>
;

WINAPI: PtInRect USER32.DLL

\ Определяем, находится ли курсор внутри заданного прямоугольника.
: MOUSE-INRECT? { b r y x -- ? } MOUSE-POS SWAP AT x PtInRect 0<> ;

\ Рисовать курсор.
: DRAW-CURSOR { newDC hwnd -- }
    EnableCursor?
    IF
      hwnd WIN-RECT MOUSE-INRECT? ScreenshotMethod -1 = AND
      hwnd DesktopIntersectRect MOUSE-INRECT? ScreenshotMethod 1 <> AND OR
      WIN-FROM-POINT TOP-PARENT-WINDOW hwnd = ScreenshotMethod 1 = AND OR
      IF GET-CURSOR hwnd CURSOR-POS newDC DrawIcon DROP THEN
    THEN
;


\ ------------------------------
\ Проверяет корректность заданных координат прямоугольника.
\ Оставляет на стеке координаты и TRUE или только FALSE
: RECT-CORRECT? { x y width height hwnd -- height width y x true | false }

    hwnd WinExist? IFNOT FALSE EXIT THEN
    hwnd WIN-RECT RectSizeValid? IFNOT FALSE EXIT THEN
    x y MIN 0< IF S" Error: x и y прямоугольника не должны быть меньше нуля." ?CRON-LOG FALSE EXIT THEN
    width height MIN 1 < IF S" Error: Ширина и высота прямоугольника должны быть больше нуля." ?CRON-LOG FALSE EXIT THEN

\ Если даны координаты отдельного участка окна, то сначала вычисляем его пересечение с указанным окном (участок может выйти за пределы окна).
\ Если даны координаты целого окна то пересечение - целое окно.
    hwnd RELWINRECT
    y height + x width + y x
    INTERSECT-RECT
    TO x   TO y   x - TO width    y - TO height

    hwnd ScreenShotSetValidMethod

\ Если метод = 0 то вычисляем пересечение рабочего стола и найденного пересечения.
    ScreenshotMethod
    IFNOT
      hwnd GetDesktopWorkRect
      hwnd WIN-POS y + TO y x + TO x
      y height + x width + y x
      INTERSECT-RECT
      TO x   TO y   x - TO width    y - TO height \ Прямоугольник пересечения (координаты относительно DesktopWorkRect).
      hwnd WIN-POS
      y SWAP - TO y \ Вычисляем координаты x и y относительно окна.
      x SWAP - TO x
    THEN
    y height + x width + y x RectSizeValid? IFNOT FALSE EXIT THEN

    height width y x TRUE
;

\ Сохранить скриншот указанного прямоугольника в указанный файл (координаты относительно hwnd).
\ В методе FullWindowMethod, ширина и высота участка всегда отсчитывается от левого верхнего угла окна (так работает функция PrintWindow).
\ Пример: FullWindowMethod 100 100 200 200 SCREENSHOT#
: SCREENSHOT-RECT ( x y width height hwnd addr-fname -- )
  { x y width height hwnd file \ winDC newDC hBitmap defObject -- }

    hwnd TO WinHwnd \ WinHwnd используется при формировании имени файла, если в имя файла добавляется дескриптор окна (слово xhwnd) или заголовок окна (слово WinTxt).
    x y width height hwnd RECT-CORRECT?
    IF TO x TO y TO width TO height ELSE EXIT THEN

    hwnd GetWindowDC TO winDC
    winDC CreateCompatibleDC TO newDC
    height width winDC CreateCompatibleBitmap TO hBitmap
    hBitmap newDC SelectObject TO defObject

    ScreenshotMethod 0>
    IF
      0 newDC hwnd PrintWindow DROP \ #define PW_CLIENTONLY 0x00000001
    ELSE
      EnableTransparent? 0x40000000 AND 0x00CC0020 OR y x winDC height width 0 0 newDC BitBlt DROP \ #define SRCCOPY 0xCC0020  #define CAPTUREBLT 0x40000000 Включает в снимок полупрозрачные окна, расположенные поверх снимаемого окна.
    THEN

    newDC hwnd DRAW-CURSOR

    hBitmap file BITMAP2FILE

    defObject newDC SelectObject DROP
    hBitmap DeleteObject DROP
    newDC DeleteDC DROP
    winDC hwnd ReleaseDC DROP
;

\ Съемка серии скриншотов с коротким интервалом между снимками. PrintWindow в MULTI-SCREENSHOT работает нестабильно.
\ sum  - Количество снимков.
\ msec - Пауза в миллисекундах после каждого снимка.
\ hwnd - Дескриптор окна.
\ addr-fname - Адрес строки с полным именем файла. Файлы с одинаковыми именами перезаписываются.
: MULTISCREENSHOT ( sum msec hwnd addr-fname -- )
  { sum msec hwnd file \ x y width height winDC newDC hBitmap defObject GpToken GpBitmap &4 &3 &2 clsid -- }

    sum ABS MultiMax MIN TO sum
    hwnd TO WinHwnd \ WinHwnd используется при формировании имени файла, если в имя файла добавляется дескриптор окна (слово xhwnd) или заголовок окна (слово WinTxt).
    hwnd WinExist? IFNOT EXIT THEN
    hwnd WIN-RECT RectSizeValid? IFNOT EXIT THEN
    file DirCreate

    GDIPLUS-STARTUP IF DROP EXIT ELSE TO GpToken THEN
    file GetCLSID TO clsid TO &2 TO &3 TO &4

    hwnd GetWindowDC TO winDC
    winDC CreateCompatibleDC TO newDC

    hwnd GetDesktopWorkRect  \ ( b1 r1 y1 x1 --  )

    BEGIN hwnd WinExist? sum 0> AND WHILE \ Если окно закроется во время цикла.
      sum 1- TO sum
      2OVER 2OVER    \ ( b1 r1 y1 x1 b1 r1 y1 x1 --  )
      hwnd WIN-RECT  \ ( b1 r1 y1 x1 b1 r1 y1 x1 b2 r2 y2 x2 --  )
      2DUP >R >R
      INTERSECT-RECT \ ( b1 r1 y1 x1 b3 r3 y3 x3 --  )

  ScreenshotMethod IF 2DROP 2DROP hwnd WIN-RECT THEN

      TO x    TO y    x - TO width    y - TO height  \ ( b1 r1 y1 x1 --  )
      R> R>
      x SWAP - 0 MAX TO x
      y SWAP - 0 MAX TO y

      height width winDC CreateCompatibleBitmap TO hBitmap
      hBitmap newDC SelectObject TO defObject

  ScreenshotMethod
  IF
    0 newDC hwnd PrintWindow DROP \ PrintWindow в MULTI-SCREENSHOT работает нестабильно.
  ELSE
    EnableTransparent? 0x40000000 AND 0x00CC0020 OR y x winDC height width 0 0 newDC BitBlt DROP \ #define SRCCOPY 0xCC0020  #define CAPTUREBLT 0x40000000 Включает в снимок полупрозрачные окна, расположенные поверх снимаемого окна.
  THEN

  newDC hwnd DRAW-CURSOR

      file ASCIIZ> EVAL-SUBST S>UNICODE DROP >R
      AT GpBitmap 0 hBitmap GdipCreateBitmapFromHBITMAP DROP
      0 AT clsid R@ GpBitmap GdipSaveImageToFile IF S" Error GdipSaveImageToFile" ?CRON-LOG THEN

      GpBitmap GdipDisposeImage DROP \ Освободить память
      defObject newDC SelectObject DROP
      hBitmap DeleteObject DROP \ Освободить память
      R> FREE DROP \ Освободить память от S>UNICODE
      msec PAUSE
    REPEAT

    2DROP 2DROP \ Удаляем из стека GetDesktopWorkRect
    newDC DeleteDC DROP
    winDC hwnd ReleaseDC DROP
    AT GpToken GdiplusShutdown DROP \ Выгружаем библиотеку gdi+
;

\ Примеры:
\ 10 100 GetDesktopWindow Z" d:\SCREENSHOT\image%GetTickCount%.png" MULTI-SCREENSHOT
\ 10 100 WIN-FROM-POINT Z" d:\SCREENSHOT\image%GetTickCount%.gif" MULTI-SCREENSHOT
\ EVAL-SUBST для имени файла делается внутри слова MULTI-SCREENSHOT


\ Сохранить скриншот указанного окна в указанный файл.
: (SCREENSHOT) ( hwnd addr-fname -- )
    >R >R
\    0 0 R@ WIN-SIZE R> R> SCREENSHOT-RECT
    0 0 R@ WIN-RECT ROT SWAP - -ROT - R> R> SCREENSHOT-RECT
;

\ Сохранить скриншот указанного окна в файл заданный в настройках.
: SCREENSHOT ( hwnd -- )
    TO WinHwnd
    ActivateWindow? IF WinHwnd WinActivate THEN
    ScreenshotFileName COUNT EVAL-SUBST 2>R
    2R@ ONLYDIR EXIST?
    IFNOT
      2R@ ONLYDIR DIR-CREATE
    THEN
    WinHwnd 2R> DROP (SCREENSHOT)
;
\ Размеры развернутого окна больше чем размеры WorkArea на толщину рамок.

\ Сохранить скриншот экрана в файл заданный в настройках.
: SCREENSHOT-DESKTOP ( -- )
    GetDesktopWindow SCREENSHOT
;

\ Сохранить скриншот активного окна в файл заданный в настройках.
: SCREENSHOT-WINDOW ( -- )
    GetForegroundWindow SCREENSHOT
;

\ Сохранить скриншот окна под курсором в файл заданный в настройках.
: SCREENSHOT-FROM-POINT ( -- )
    WIN-FROM-POINT SCREENSHOT
;

\ Сохранить скриншот окна, идентификатор которого находится в буфере обмена.
: SCREENSHOT-FROM-CLIPBOARD ( -- )
    CLIPBOARD@ S>NUM
    DUP WinExist? IF SCREENSHOT ELSE DROP THEN
;

\ Сохранить скриншот указанного прямоугольника активного окна в файл заданный в настройках.
: SCREENSHOT# ( x y width height -- )
    GetForegroundWindow TO WinHwnd
\    GetDesktopWindow TO WinHwnd
    ActivateWindow? IF WinHwnd WinActivate THEN
    ScreenshotFileName COUNT EVAL-SUBST DROP >R
    WinHwnd R> SCREENSHOT-RECT
;

\ Сохранить серию скриншотов указанного окна в файл(ы) заданный в настройках.
: MULTI-SCREENSHOT ( sum msec hwnd -- )
    MultiScreenshotFileName COUNT DROP
    MULTISCREENSHOT
;



\ Дескриптор окна для добавления в имя файла.
: xhwnd ( -- a u )
    WinHwnd
    BASE @ SWAP HEX
    S>D <# # # # # # # # # S" 0x" HOLDS #>
    ROT BASE !
;

\ Недопустимые символы в имени файла.
SCONSTANT badchar \/:*?"<>|+ .%!@

\ Заголовок окна для добавления в имя файла.
: WinTxt ( -- a u )
    WinHwnd GET-WTEXT 16 MIN \ Можно сделать длиннее или короче.
    badchar NIP 0 DO badchar DROP I + C@ [CHAR] ^ CharReplace LOOP
;


: ScreenshotFileName:      ( "fname" -- ) C", TO ScreenshotFileName ;
: MultiScreenshotFileName: ( "fname" -- ) C", TO MultiScreenshotFileName ;



Примеры ниже, в кронтабе nncron_screenshot.tab
Last edited by dothen on Fri, 28 Apr 2017, 04:08, edited 1 time in total.
dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58

Кронтаб nncron_screenshot.tab

Postby dothen » Fri, 28 Apr 2017, 03:46

Кронтаб nncron_screenshot.tab

Примеры задач для плагина screenshot.spf

Code: Select all
# Файл:       nncron_screenshot.tab
# Автор:      dothen
# Дата:       28.04.2017
# Версия:     1.0
# Описание: Примеры задач для плагина screenshot.spf

# Подключить плагины extwords.spf screenshot.spf
# Подключить кронтаб nncron_extwords2.tab (http://www.nncron.ru/forums/viewtopic.php?f=5&t=13361#p35725)

# Горячие клавиши:
# Shift+PrintScreen - Меню.
# Ctrl+PrintScreen - Экран.
# Win+PrintScreen - Активное окно.

# Если запускать задачи из меню nnCron то активным окном будет скрытое окно "nnCron control window".

<%

\ Имя файла для скриншота.
ScreenshotFileName: "e:\Screenshot\%YYYY%-%MM%\%DD%_%WinTxt%_%xhwnd%_%hh%-%mm%-%ss%-%mss%.png"

\ Имя файла для мультискриншота.
MultiScreenshotFileName: "e:\Screenshot\%YYYY%-%MM%\Multi\%DD%\%WinTxt%_%hh%-%mm%-%ss%-%mss%.png"

\ Всплывающее меню - Screenshot
: Menu-Screenshot ( -- )
    POPUPMENU
      S" Скриншот экрана" 10 MENUITEM
      S" Скриншот окна" 20 MENUITEM
      S" Скриншот окна (FullWindow)" 30 MENUITEM
      MENUSEPARATOR
      S" Скриншот участка (пример)" 40 MENUITEM
      S" Скриншот окна под курсором" 50 MENUITEM
      S" Скриншот окна под курсором (FullWindow)" 55 MENUITEM
      S" Скриншот окна (HWND из буфера обмена)" 60 MENUITEM
      S" Скриншот окна (HWND из буфера обмена)(FullWindow)" 65 MENUITEM
      S" Копировать HWND под курсором" 100 MENUITEM
    END-MENU
    GetForegroundWindow >R
    RunMenu
    R> WinActivate \ Активизировать окно которое было активно перед вызовом меню.
    CASE
      0   OF NOOP ENDOF
      10  OF SCREENSHOT-DESKTOP ENDOF
      20  OF SCREENSHOT-WINDOW ENDOF
      30  OF FullWindowMethod SCREENSHOT-WINDOW ENDOF
      40  OF 150 150 500 500 SCREENSHOT# ENDOF
      50  OF EnableCursor SCREENSHOT-FROM-POINT ENDOF
      55  OF EnableCursor FullWindowMethod SCREENSHOT-FROM-POINT ENDOF
      60  OF SCREENSHOT-FROM-CLIPBOARD ENDOF
      65  OF FullWindowMethod SCREENSHOT-FROM-CLIPBOARD ENDOF
     100  OF WIN-FROM-POINT N>HEX CLIPBOARD! ENDOF
      DUP OF NOOP ENDOF
    ENDCASE
;

: show-osd ( a u -- )
    550 380 OSD-POS
    S" Arial" 50 0xFF0000 OSD-FONT
    300 OSD-PAUSED
;


%>


#( CLASSIC-TASK-#-Скриншот_активное_окно
SingleInstance
WatchHotKey: "${PRTSC}"   \ Win+PrintScreen
Action:
    EnableTransparent
    EnableCursor

\ Делается три снимка разными методами.
    ClipWindowMethod SCREENSHOT-WINDOW

    SizeWindowMethod SCREENSHOT-WINDOW

    FullWindowMethod SCREENSHOT-WINDOW

    S" Окно" show-osd

)#


#( CLASSIC-TASK-#-Скриншот_экран
SingleInstance
WatchHotKey: "^{PRTSC}"   \ Ctrl+PrintScreen
Action:
    EnableCursor
    SCREENSHOT-DESKTOP
    S" Экран" show-osd
)#


#( CLASSIC-TASK-#-Меню-Скриншот
SingleInstance
WatchHotKey: "+{PRTSC}"   \ Shift+PrintScreen
Action:
    Menu-Screenshot
)#


#( CLASSIC-TASK-#-Мульти-Скриншот
SingleInstance
WatchHotKey: "^+{PRTSC}"   \ Ctrl+Shift+PrintScreen
Action:
    EnableTransparent
    EnableCursor
    ClipWindowMethod

    10  \ Количество снимков.
    100 \ Интервал между снимками.
    GetForegroundWindow \ Дескриптор окна.
    MULTI-SCREENSHOT
    S" Мульти" show-osd
)#


dothen
 
Posts: 184
Joined: Mon, 16 Mar 2015, 04:58


Return to nnCron forum (Russian)

Who is online

Users browsing this forum: No registered users and 2 guests