13

Windows 環境で Haskell を使用して画面 (またはウィンドウ) をキャプチャすることは可能ですか? (つまり、数分ごとにスクリーンショットを撮ります)。もしそうなら、どのようにこれを行うのですか?

詳細: 私は Haskell の初心者です。ある友人が、彼の会計事務所のために私にいくつかのプログラムをまとめてもらうことで開発コストを削減したいと考えていますが、彼は私が Haskell を使用することを主張しています。彼は、さまざまな Windows XP ワークステーションのデスクトップを監視できるツールが必要です。おそらく、クライアント/サーバー タイプのアプリケーションである必要があります。彼はデスクトップ アクティビティを監視するだけでよいため、すでに市場に出回っている高価な管理ソフトウェアは必要としません。私は多くのドキュメントをふるいにかけましたが、wxHaskell を見つけることしかできませんでしたが、特に Windows 環境では、画面のキャプチャについてはあまり見つけられませんでした。

4

3 に答える 3

19

ティコンが言及したアプローチは正しいです。彼が上で与えた答えにいくつかのコードを追加するだけです

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 ライブラリを書いた人へ、よくやった :)

于 2012-08-15T09:29:05.800 に答える
14

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)])
于 2012-08-15T15:46:49.140 に答える
12

これは、Win32 API を使用して実行できるはずです。Windows で C++ を使用してウィンドウのスクリーンショットを撮る最良の方法は何ですか? 、ウィンドウのコンテキストを取得し、それぞれ と を使用してそこから画像をコピーする必要がありGetWindowDCますBitBlt

Haskell Win32 API ドキュメントを見回すと、 にgetWindowDC関数がありGraphics.Win32.Windowます。これは を返しますIO HDCbitbltに機能がありGraphics.Win32.GDI.Graphics2Dます。この関数は、おそらくC++で受け取る引数に対応する一連の を受け取りHDCます。INT

残念ながら、手元に Windows マシンがないため、実際のコードを書くことができません。Win32 API 関数を自分で使用する方法を理解する必要がありますが、これは少し面倒かもしれません。

そうした場合、それをライブラリに分解して Hackage に載せるとよいでしょう。Windows は通常、Haskell の世界ではあまり愛されていません (私自身が示しているように :P)。スクリーンショットを撮る簡単な方法に感謝します。

于 2012-08-15T04:23:21.677 に答える