2012-04-19 69 views
1

我有一些代碼,需要一個屏幕截圖...如何獲得屏幕截圖,包括調用窗口(XP系統)

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上的一個問題。

+0

我已經嘗試了這兩種不同的方式。在第一個(原始)情況下,上述方法是我想要捕獲的窗口(作爲整個屏幕的一部分)的調用過程的一部分。在第二種情況下,我啓動一個進程並從那裏調用它。在這兩種情況下,XP都不包含父窗口。我的猜測是,由於某種原因,所有調用進程的祖先都不包含在屏幕截圖中。希望有一種解決方法。 – 2012-04-19 17:16:30

+0

在這裏黑暗中摸索...你確定調用程序的窗口實際上是在你調用這個函數的時候顯示的嗎?例如,如果您在Form.Create中執行此操作,則可能窗口尚未呈現。 – 2012-04-19 18:00:52

+0

好想法,但沒有。我調出應用程序,只需點擊一下按鈕(本質上)即可完成屏幕截圖。 – 2012-04-19 18:10:20

回答

4

將表單的不透明度屬性設置爲100,然後右鍵單擊TransparencyKey屬性並選擇重置。這可以確保您的窗口不再是分層窗口,並且不會從截圖中丟失。

如果你想保留這些屬性,那麼你將不得不解決Graphics.CopyFromScreen()中的錯誤。捕獲分層窗口需要使用CopyPixelOperation和CaptureBlt操作的重載。但由於參數驗證代碼中的錯誤而無法工作。解決方法是不漂亮,但功能:

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

賓果!你的第一個建議(不透明度= 100,重置透明度)訣竅。我設置了透明度鍵,在此之前我用不透明度來描述,所以顯然我沒有正確地「撤消」那個。謝謝你的幫助! – 2012-04-19 19:02:12