Подтвердить что ты не робот

Захват экрана в Haskell?

Можно ли захватить экран (или окно) с помощью Haskell в среде Windows? (т.е. снимать скриншот каждые несколько минут или около того). Если да, то как это сделать (опять же, в Haskell, для среды Windows)?

Дополнительная информация: Я новичок в Haskell. Друг хочет сократить расходы на разработку, заставив меня вырвать некоторые программы для его бухгалтерской фирмы, но он настаивает на том, что я использую Haskell. Ему нужен инструмент, который позволит ему контролировать рабочие станции разных рабочих станций Windows XP. Вероятно, это будет приложение типа клиент/сервер. Ему нужно только следить за работой на рабочем столе, поэтому он не хочет ни одного дорогого программного обеспечения для управления, которое уже находится на рынке. Я просеял много документации и только дошел до поиска wxHaskell, но не смог найти многого для захвата экрана, особенно для сред Windows.

4b9b3361

Ответ 1

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

import Graphics.Win32.Window
import Graphics.Win32.GDI.Bitmap
import Graphics.Win32.GDI.HDC
import Graphics.Win32.GDI.Graphics2D

main = do desktop   <- getDesktopWindow -- Grab the Hwnd of the desktop, GetDC 0, GetDC NULL etc all work too
          hdc       <- getWindowDC (Just desktop) -- Get the dc handle of the desktop
          (x,y,r,b) <- getWindowRect desktop -- Find the size of the desktop so we can know which size the destination bitmap should be
                                             -- (left, top, right, bottom)
          newDC     <- createCompatibleDC (Just hdc) -- Create a new DC to hold the copied image. It should be compatible with the source DC
          let width  = r - x -- Calculate the width
          let height = b - y -- Calculate the Height
          newBmp    <- createCompatibleBitmap hdc width height -- Create a new Bitmap which is compatible with the newly created DC
          selBmp    <- selectBitmap newDC newBmp -- Select the Bitmap into the DC, drawing on the DC now draws on the bitmap as well
          bitBlt newDC 0 0 width height hdc 0 0 sRCCOPY -- use SRCCOPY to copy the desktop DC into the newDC
          createBMPFile "Foo.bmp" newBmp newDC  -- Write out the new Bitmap file to Foo.bmp
          putStrLn "Bitmap image copied" -- Some debug message
          deleteBitmap selBmp -- Cleanup the selected bitmap
          deleteBitmap newBmp -- Cleanup the new bitmap
          deleteDC newDC      -- Cleanup the DC we created.

Это было просто скомпоновано, но оно сохраняет скриншот файла с именем Foo.bmp. Ps. Кому, кто написал библиотеку Win32, красиво сделано:)

Ответ 2

Вы также можете сделать это кросс-платформенным способом с помощью GTK.

Это не сильно отличается от того, чтобы делать это с помощью C: Снимок экрана с C/GTK.

{-# LANGUAGE OverloadedStrings #-}

import Graphics.UI.Gtk
import System.Environment
import Data.Text as T

main :: IO ()
main = do
    [fileName] <- getArgs
    _ <- initGUI
    Just screen <- screenGetDefault
    window <- screenGetRootWindow screen
    size <- drawableGetSize window
    origin <- drawWindowGetOrigin window
    Just pxbuf <-
        pixbufGetFromDrawable
            window
            ((uncurry . uncurry Rectangle) origin size)
    pixbufSave pxbuf fileName "png" ([] :: [(T.Text, T.Text)])

Ответ 3

Вы можете сделать это с помощью API Win32. На основе Каков наилучший способ сделать скриншоты окна с С++ в Windows?, вам нужно получить контекст окна, а затем скопировать изображение с него, используя GetWindowDC и BitBlt соответственно.

Оглядываясь на документацию API Haskell Win32, есть функция GetWindowDC в Graphics.Win32.Window. Это возвращает IO HDC. Существует функция BitBlt в Graphics.Win32.GDI.Graphics2D. Эта функция принимает HDC вместе с связкой INT, которая, по-видимому, соответствует аргументам, которые она принимает в С++.

К сожалению, у меня нет операционной системы Windows, поэтому я не могу написать фактический код. Вам нужно будет выяснить, как использовать функции API Win32 самостоятельно, что может быть немного неприятным.

Когда вы это сделаете, было бы здорово, если бы вы включили его в библиотеку и поместили в Hackage - Windows обычно не получает много любви на земле Haskell (как я сам показываю: P), поэтому я уверен другие программисты Windows были бы благодарны за простой способ сделать скриншоты.