2009-09-16 11 views
13

मैं वर्तमान में WatiN के साथ काम कर रहा हूं, और इसे एक महान वेब ब्राउज़िंग स्वचालन उपकरण के रूप में ढूंढ रहा हूं। हालांकि, अंतिम रिलीज के रूप में, यह स्क्रीन कैप्चरिंग कार्यक्षमता की कमी है। मैं कुछ code by Charles Petzold के अलावा स्क्रीन से स्क्रीनशॉट को कैप्चर करने के लिए एक व्यावहारिक समाधान के साथ आया हूं (स्वतंत्र रूप से this StackOverflow question के समान कोड उत्पन्न करना)। दुर्भाग्य से, एक गायब घटक है: वास्तविक विंडो कहां है?मुझे मूल विंडो के बिना एचडब्ल्यूएनडी दी गई विंडो की स्थिति/स्थान कैसे मिल सकता है?

// browser is either an WatiN.Core.IE or a WatiN.Core.FireFox... 
IntPtr hWnd = browser.hWnd; 
string filename = "my_file.bmp"; 
using (Graphics browser = Graphics.FromHwnd(browser.hWnd)) 
using (Bitmap screenshot = new Bitmap((int)browser.VisibleClipBounds.Width, 
             (int)browser.VisibleClipBounds.Height, 
             browser)) 
using (Graphics screenGraphics = Graphics.FromImage(screenshot)) 
{ 
    int hWndX = 0; // Upper left of graphics? Nope, 
    int hWndY = 0; // this is upper left of the entire desktop! 

    screenGraphics.CopyFromScreen(hWndX, hWndY, 0, 0, 
          new Size((int)browser.VisibileClipBounds.Width, 
            (int)browser.VisibileClipBounds.Height)); 
    screenshot.Save(filename, ImageFormat.Bmp); 
} 

सफल:

Watin सुविधाजनक ब्राउज़र की आप के लिए hWnd, तो हम (इस सरल उदाहरण के साथ), स्क्रीन से किसी चित्र की प्रतिलिपि बनाने इसलिए की तरह सेट प्राप्त कर सकते हैं प्रदान करता है! हमें स्क्रीनशॉट मिलते हैं, लेकिन समस्या है: hWndX और hWndY हमेशा स्क्रीन के ऊपरी बाएं कोने को इंगित करते हैं, न कि उस विंडो का स्थान जिसे हम कॉपी करना चाहते हैं।

तब मैंने Control.FromHandle में देखा, हालांकि ऐसा लगता है कि आपने केवल आपके द्वारा बनाए गए फॉर्मों के साथ काम किया है; यदि आप hWnd पास करते हैं तो यह विधि एक शून्य सूचक देता है।

फिर, आगे पढ़ने के लिए मुझे अपने खोज मानदंडों को स्विच करने के लिए नेतृत्व करें ... मैं 'खिड़की का स्थान' खोज रहा था जब अधिकांश लोग वास्तव में खिड़की की 'स्थिति' चाहते थे। यह another SO question पर जाता है जिसने इसके बारे में बात की, लेकिन उनका जवाब देशी तरीकों का उपयोग करना था।

तो, क्या खिड़की की स्थिति खोजने का मूल सी # तरीका है, केवल एचडब्ल्यूएनडी (अधिमानतः केवल .NET 2.0 युग पुस्तकालयों के साथ) दिया गया है?

उत्तर

29

मैं अभी इस परियोजना के माध्यम से चला गया और किसी भी प्रबंधित सी # तरीके को खोजने में असमर्थ था।

/रीड के जवाब पी में जोड़ने के लिए आह्वान कोड है:

[DllImport("user32.dll", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); 
[StructLayout(LayoutKind.Sequential)] 
private struct RECT 
{ 
    public int Left; 
    public int Top; 
    public int Right; 
    public int Bottom; 
    } 

के रूप में यह कॉल करें:

RECT rct = new RECT(); 
    GetWindowRect(hWnd, ref rct); 
+0

धन्यवाद! ऐसा लगता है कि यह करेगा। –

+0

हाय रॉबर्ट, क्या आप अपना पूरा समाधान पोस्ट कर सकते हैं? मैं फ़ायरफ़ॉक्स और अन्य ब्राउज़रों (क्रोम) के लिए स्क्रीनकैप्चर कार्यक्षमता जोड़ना पसंद करूंगा। अग्रिम धन्यवाद! जेरोइन (लीड देव वाटीएन) –

+0

हे! निश्चित रूप से, कर सकते हैं। –

6

नहीं - यदि आपने फॉर्म नहीं बनाया है, तो आपको GetWindowRect को P/Invoke करना होगा। मुझे विश्वास नहीं है कि एक प्रबंधित समकक्ष है।

4

जवाब है के रूप में दूसरों ने कहा है, शायद "नहीं, तुम नहीं एक ले जा सकते हैं मूल विधियों के बिना एक hwnd से एक यादृच्छिक खिड़की का स्क्रीनशॉट। "। चेतावनियां की युगल इससे पहले कि मैं यह दिखाने:

चेतावनी:

जो कोई भी इस कोड का उपयोग करना चाहता के लिए, कृपया ध्यान दें कि आकार VisibleClipBounds से दिए गए केवल विंडो के अंदर है, और नहीं सीमा या शीर्षक पट्टी शामिल करें। यह आकर्षित करने योग्य क्षेत्र है। यदि आपके पास ऐसा था, तो आप पी/इनवॉक के बिना ऐसा करने में सक्षम हो सकते हैं।

(आप ब्राउज़र विंडो के बॉर्डर की गणना कर सकते हैं, तो आप VisibleClipBounds इस्तेमाल कर सकते हैं। यदि आप चाहते हैं तो आप SystemInformation वस्तु का उपयोग Border3DSize जैसे महत्वपूर्ण जानकारी प्राप्त करने के सकता है, या आप एक डमी बनाकर उसका गणना करने के लिए कोशिश कर सकते फॉर्म और deriving the border and title bar height from that, लेकिन यह सब काले जादू की तरह लगता है कि कीड़े बना रहे हैं।)

यह विंडो के Ctrl + प्रिंटरस्क्रीन के बराबर है। यह उन नस्लों को भी नहीं करता है जो WATN स्क्रीनशॉट क्षमता करता है, जैसे ब्राउज़र को स्क्रॉल करना और पूरे पृष्ठ की एक छवि लेना। यह मेरी परियोजना के लिए उपयुक्त है, लेकिन हो सकता है कि आपके लिए न हो।

संवर्द्धन:

अगर आप नेट 3 में और अप-भूमि कर रहे हैं एक विस्तार विधि के लिए बदला जा सकता है, और छवि प्रकार के लिए एक विकल्प के बहुत आसानी से जोड़ा जा सकता है (मैं के लिए डिफ़ॉल्ट इस उदाहरण के लिए ImageFormat.Bmp)।

कोड:

using System.Drawing; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 

public class Screenshot 
{ 
    class NativeMethods 
    { 
     // http://msdn.microsoft.com/en-us/library/ms633519(VS.85).aspx 
     [DllImport("user32.dll", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); 

     // http://msdn.microsoft.com/en-us/library/a5ch4fda(VS.80).aspx 
     [StructLayout(LayoutKind.Sequential)] 
     public struct RECT 
     { 
      public int Left; 
      public int Top; 
      public int Right; 
      public int Bottom; 
     } 
    } 
    /// <summary> 
    /// Takes a screenshot of the browser. 
    /// </summary> 
    /// <param name="b">The browser object.</param> 
    /// <param name="filename">The path to store the file.</param> 
    /// <returns></returns> 
    public static bool SaveScreenshot(Browser b, string filename) 
    { 
     bool success = false; 
     IntPtr hWnd = b.hWnd; 
     NativeMethods.RECT rect = new NativeMethods.RECT(); 
     if (NativeMethods.GetWindowRect(hWnd, ref rect)) 
     { 
      Size size = new Size(rect.Right - rect.Left, 
           rect.Bottom - rect.Top); 
      // Get information about the screen 
      using (Graphics browserGraphics = Graphics.FromHwnd(hWnd)) 
      // apply that info to a bitmap... 
      using (Bitmap screenshot = new Bitmap(size.Width, size.Height, 
                browserGraphics)) 
      // and create an Graphics to manipulate that bitmap. 
      using (Graphics imageGraphics = Graphics.FromImage(screenshot)) 
      { 
       int hWndX = rect.Left; 
       int hWndY = rect.Top; 
       imageGraphics.CopyFromScreen(hWndX, hWndY, 0, 0, size); 
       screenshot.Save(filename, ImageFormat.Bmp); 
       success = true; 
      } 
     } 
     // otherwise, fails. 
     return success; 
    } 
}