熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

C#中三種截屏方式小結

2013-11-13 10:17:53  來源: .NET編程 

  昨天寫自動化測試的CASE的時候碰到一個疑難雜症調用截圖的函數去截取一個Popup窗口但是總是把背景程序給截下來Popup窗口就跟看不到一樣本來以為是同步的問題也就是以為先截圖再點擊彈出Popup窗口了後來加了N個ThreadSleep來測試發現根本不是因為這個原因而是截圖的函數截不下來這個窗口
 
  這個為啥呢只好把截圖的函數代碼翻出來看以前是用這種方式的BitBlt(dcImage (int)(rectWidth) (int)(rectHeight) dcScreen (int)(rectLeft) (int)(rectTop) TernaryRasterOperationsSRCCOPY)憑直覺感覺應該是因為這種通過DC的方式對WPF程序支持有問題但是又覺得奇怪就是截取其它的WPF組件和窗口都沒有問題偏偏Popup窗口不行
 
  前些天聽說另外一種截屏的方法這種方法連被遮擋的窗口都可以截於是就Google一大把找打了PrintWindow函數於是就有了第二種解決方案代碼如下
 
IntPtr hdc = NativeGetWindowDC(thisHandle);
if (hdc != IntPtrZero)
{
    IntPtr hdcMem = NativeCreateCompatibleDC(hdc);
    if (hdcMem != IntPtrZero)
    {
        IntPtr hbitmap = NativeCreateCompatibleBitmap(hdc (int)(RectWidth) (int)(RectHeight));
        if (hbitmap != IntPtrZero)
        {
            NativeSelectObject(hdcMem hbitmap);
            NativePrintWindow(thisHandle hdcMem );

  NativeDeleteObject(hbitmap);
            Bitmap bmp = BitmapFromHbitmap(hbitmap);
            bmpSave(sPath);
       }
        NativeDeleteObject(hdcMem);
    }
    NativeReleaseDC(thisHandle hdc);
}

  就是拿到窗口的句柄通過PrintWindow API來截取窗口

  但是更讓人氣憤的事情出現了截出來的窗口中只要是用到WPF組件的地方全部是黑塊兒只有MFC的窗口框架和按鈕可以正常被截取

  於是乎就無奈的繼續分析這個問題我記得WPF是沒有走GDI而是通過Directx渲染的那就是說DC的方式和PrintWindow的方式都不靠譜但是截Directx的貌似還比較復雜

  突然想起來平常報bug的時候都是按PrintScreen然後再處理一下的那應該PrintScreen按鍵是管用的看來只能曲線救國了但是那樣就得走剪切板了貌似會破壞剪切板的數據不過如果我在截取前保存一下數據在截取後再恢復一下剪切板數據那就沒有問題了

  於是就有了第三種解決方案(暫時還沒有加恢復剪切板數據的代碼)

  const uint KEYEVENTF_EXTENDEDKEY = x;
const uint KEYEVENTF_KEYUP = x;
const byte VK_SNAPSHOT = xC;
Nativekeybd_event(VK_SNAPSHOT x KEYEVENTF_EXTENDEDKEY UIntPtrZero);
Nativekeybd_event(VK_SNAPSHOT x KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP UIntPtrZero);

  IDataObject iObj = ClipboardGetDataObject();
if (iObjGetDataPresent(DataFormatsBitmap true))
{
    Bitmap bmpScreen = iObjGetData(DataFormatsBitmap true) as Bitmap;
    Bitmap bmpOutput = new Bitmap((int)thisRectWidth (int)thisRectHeight SystemDrawingImagingPixelFormatFormatbppRgb);
    Graphics g = GraphicsFromImage(bmpOutput);
    Rectangle destRectangle = new Rectangle( (int)thisRectWidth (int)thisRectHeight);
    gDrawImage(bmpScreendestRectangle  (int)thisRectX (int)thisRectY (int)thisRectWidth

  (int)thisRectHeight GraphicsUnitPixel);
    bmpOutputSave(sPath SystemDrawingImagingImageFormatBmp);
}

  測試可用只好先用著了

  不過還有幾個問題先寫下來留待以後解決

   針對第三種方案既然可以按PrintScreen鍵截圖那對應的API是什麼總覺得發鍵盤消息沒有直接調API穩定

   針對WPF截圖有沒有更好的解決方案


From:http://tw.wingwit.com/Article/program/net/201311/13188.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.