[ACCEPTED]-How do I find the position / location of a window given a hWnd without NativeMethods?-screenshot

Accepted answer
Score: 38

I just went through this on a project and 3 was unable to find any managed C# way.

To 2 add to Reed's answer the P/Invoke code is:

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

Call 1 it as:

  RECT rct = new RECT();
  GetWindowRect(hWnd, ref rct);
Score: 6

No - if you didn't create the form, you 2 have to P/Invoke GetWindowRect. I don't believe there 1 is a managed equivalent.

Score: 4

The answer is as others have stated, probably 26 "No, you cannot take a screenshot of 25 a random window from an hwnd without native 24 methods.". Couple of caveats before 23 I show it:

Forewarning:

For anyone who wants to use this 22 code, note that the size given from the 21 VisibleClipBounds is only inside the window, and 20 does not include the border or title bar. It's 19 the drawable area. If you had that, you 18 might be able to do this without p/invoke.

(If 17 you could calculate the border of the browser 16 window, you could use the VisibleClipBounds. If 15 you wanted, you could use the SystemInformation object to 14 get important info like Border3DSize, or you could try 13 to calculate it by creating a dummy form 12 and deriving the border and title bar height from that, but that all sounds like the black 11 magic that bugs are made of.)

This is equivalent 10 to Ctrl+Printscreen of the window. This 9 also does not do the niceties that the WatiN 8 screenshot capability does, such as scroll 7 the browser and take an image of the whole 6 page. This is suitable for my project, but 5 may not be for yours.

Enhancements:

This could be changed 4 to be an extension method if you're in .NET 3 3 and up-land, and an option for the image 2 type could be added pretty easily (I default 1 to ImageFormat.Bmp for this example).

Code:

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

More Related questions