Haskell中的屏幕截图?

时间:2012-08-15 02:59:04

标签: windows haskell wxhaskell

是否可以在Windows环境中使用Haskell捕获屏幕(或窗口)? (即每隔几分钟拍摄一次屏幕截图)。如果是这样,怎么会这样做(再次,在Haskell中,对于Windows环境)?

更多信息: 我是Haskell的初学者。一位朋友希望通过让我为他的会计师事务所鞭打一些程序来削减开发成本,但他坚持认为我使用的是Haskell。他想要一个能够监控不同Windows XP工作站桌面的工具。它可能必须是客户端/服务器类型的应用程序。他只需要监控桌面活动,因此他不想要任何已经上市的昂贵管理软件。我已经筛选了大量的文档,并且只能找到wxHaskell,但我在捕获屏幕方面找不到太多,特别是对于Windows环境。

3 个答案:

答案 0 :(得分:17)

Tikhon提到的方法是正确的。只是为上面给出的答案添加一些代码

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库的人来说,做得很好:)

答案 1 :(得分:12)

您也可以使用GTK以跨平台方式执行此操作。

与使用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)])

答案 2 :(得分:11)

您应该可以使用Win32 API执行此操作。根据{{​​3}},您需要获取窗口的上下文,然后分别使用GetWindowDCBitBlt复制图像。

查看Haskell Win32 API文档,What is the best way to take screenshots of a Window with C++ in Windows?中有getWindowDC函数。这将返回IO HDCGraphics.Win32.Window中有bitblt个功能。这个函数带有HDC和一堆INT,它们可能与Graphics.Win32.GDI.Graphics2D中的参数相对应。

不幸的是,我没有方便的Windows机器,所以我无法编写实际的代码。您必须自己弄清楚如何使用Win32 API函数,这可能有点麻烦。

当你这样做的时候,如果你将它考虑到一个库并把它放在Hackage上会很棒 - Windows通常不会在Haskell的土地上得到太多的爱(正如我自己所示:P),所以我很确定其他Windows程序员会很高兴能够轻松获取屏幕截图。