Screen capture in Haskell?

前端 未结 3 1281
傲寒
傲寒 2020-12-14 20:57

Is it possible to capture the screen (or a window) using Haskell in a Windows environment? (ie, taking a screenshot every few minutes or so). If so, how would one go about d

相关标签:
3条回答
  • 2020-12-14 21:42

    You can also do it in a cross-platform way with GTK.

    That would not be much different from doing it with C: Taking a screenshot with 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)])
    
    0 讨论(0)
  • 2020-12-14 21:44

    The Approach Tikhon mentioned is correct. Just to add some code to the answer he gave above

    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.
    

    This was just quickly put together, but it saves a screenshot of to a file named Foo.bmp. Ps. To whomever wrote the Win32 Library, nicely done :)

    0 讨论(0)
  • 2020-12-14 21:47

    You should be able to do this with the Win32 API. Based on What is the best way to take screenshots of a Window with C++ in Windows?, you need to get the context of the window and then copy the image from it using GetWindowDC and BitBlt respectively.

    Looking around the Haskell Win32 API documentation, there is a getWindowDC function in Graphics.Win32.Window. This returns an IO HDC. There is a bitblt function in Graphics.Win32.GDI.Graphics2D. This function takes an HDC along with a bunch of INTs which presumably correspond to the arguments it takes in C++.

    Unfortunately, I don't have a Windows machine handy, so I can't write the actual code. You'll have to figure out how to use the Win32 API functions yourself, which might be a bit of a bother.

    When you do, it would be great if you factored it into a library and put it up on Hackage--Windows does not usually get much love in Haskell land (as I myself show :P), so I'm sure other Windows programmers would be grateful for an easy way to take screenshots.

    0 讨论(0)
提交回复
热议问题