Screen capture in Haskell?
The Approach Tikhon mentioned is correct. Just to add some code to the answer he gave above
import Graphics.Win32.Windowimport Graphics.Win32.GDI.Bitmapimport Graphics.Win32.GDI.HDCimport Graphics.Win32.GDI.Graphics2Dmain = 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 :)
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.Gtkimport System.Environmentimport Data.Text as Tmain :: 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)])
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 INT
s 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.