1

スクリーンショットを撮るコードがあります...

Size ssSize;
int ssX, ssY, ssWidth, ssHeight;
Bitmap thisScreenshot;
Graphics gfxScreenshot;

public Image Screenshot()
{
ssX = Screen.PrimaryScreen.Bounds.X;
ssY = Screen.PrimaryScreen.Bounds.Y;
ssWidth = Screen.PrimaryScreen.Bounds.Width;
ssHeight = Screen.PrimaryScreen.Bounds.Height;
ssSize = Screen.PrimaryScreen.Bounds.Size;
thisScreenshot = new Bitmap(ssWidth,ssHeight);
gfxScreenshot = Graphics.FromImage(thisScreenshot);
return((Image)gfxScreenshot.CopyFromScreen(ssX, ssY, 0, 0, ssSize));
}

W7 では、結果の画像に呼び出しウィンドウのピクセルが含まれます。しかし、XPではそうではありません。呼び出しプロセス/ウィンドウのピクセルを常に画像に含めたいと思います。これを強制する方法の手がかりはありますか?

UPDATE1: これについてさらに実験を行った結果、さらに混乱しました...上記のコードを使用して、まったく別のアプリケーションを作成し、これと最初に起動していたアプリケーションとの間に関係がないようにしましたそれから。奇妙なことに、スクリーンショットにそのアプリケーションのウィンドウがまだ表示されていません。したがって、スクリーンショットを実行するプロセスと、スクリーンショットに含めたいウィンドウとの間に関係はありません。それでも、そのウィンドウはまだ含まれていません。PRNT-SCRNボタンを試してみましたが、ウィンドウが含まれています。これは XP でのみ発生する問題であることに注意してください。

4

1 に答える 1

4

フォームの Opacity プロパティを 100 に設定し、TransparencyKey プロパティを右クリックして [リセット] を選択します。これにより、ウィンドウがレイヤード ウィンドウではなくなり、スクリーンショットから欠落することがなくなります。

これらのプロパティを保持したい場合は、Graphics.CopyFromScreen() のバグを回避する必要があります。レイヤード ウィンドウをキャプチャするには、CaptureBlt 操作で CopyPixelOperation を使用するオーバーロードが必要です。ただし、引数の検証コードのバグにより機能しません。回避策はきれいではありませんが機能的です:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e) {
            Size sz = Screen.PrimaryScreen.Bounds.Size;
            IntPtr hDesk = GetDesktopWindow();
            IntPtr hSrce = GetWindowDC(hDesk);
            IntPtr hDest = CreateCompatibleDC(hSrce);
            IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
            IntPtr hOldBmp = SelectObject(hDest, hBmp);
            bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
            Bitmap bmp = Bitmap.FromHbitmap(hBmp);
            SelectObject(hDest, hOldBmp);
            DeleteObject(hBmp);
            DeleteDC(hDest);
            ReleaseDC(hDesk, hSrce);
            bmp.Save(@"c:\temp\test.png");
            bmp.Dispose();
        }

        // P/Invoke declarations
        [DllImport("gdi32.dll")]
        static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
        wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
        [DllImport("user32.dll")]
        static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr DeleteDC(IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr DeleteObject(IntPtr hDc);
        [DllImport("gdi32.dll")]
        static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
        [DllImport("gdi32.dll")]
        static extern IntPtr CreateCompatibleDC(IntPtr hdc);
        [DllImport("gdi32.dll")]
        static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr ptr);
    }
}
于 2012-04-19T18:42:59.797 に答える