Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
170 views
in Technique[技术] by (71.8m points)

c# - How to get screenshot to include the invoking window (on XP)

I have code that takes a screenshot...

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));
}

On W7, the resulting image includes the pixels of the calling window; but on XP it does not. I would like the image to always include the pixels of the calling process/window. Any clue how I can force this?

UPDATE1: I've done more experimentation with this, and as a result I'm more confused... I took the above code and created a totally separate application so that there is no relationship between this and the application that I was originally launching it from. Strangely enough, I am STILL not seeing the window of that application in the screenshot. So now I have no relationship between the process doing the screenshot and the window that I want included in the screenshot; yet, that window is still not included. I did try the PRNT-SCRN button and that does include the window. Note that this is only a problem on XP.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Set your form's Opacity property to 100 and right-click the TransparencyKey property and select Reset. That ensures that your window is no longer a layered window and won't be missing from the screenshot.

If you want to keep these properties then you'll have to work around in a bug in Graphics.CopyFromScreen(). The overload that uses CopyPixelOperation with the CaptureBlt operation is required to capture layered windows. But won't work due to a bug in the argument validation code. The workaround isn't pretty but functional:

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:empest.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);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...