Answered by:
Capture contents of current window

Question
-
I need to be able to capture the contents of a current window as a bitmap about two times a second from a windows forms window and display the picture in a WPF window.
Its a temporary fix for a COM object I am using that isn't playing well with my WPF app, but I need the visual data from it.
My plan for now is to manipulate the control and capture the control's screen output and display it in a WPF picture frame.
How would I go about capturing the inside contents of a window? Minus the window frame?
Answers
-
Since the Control.DrawToBitmap() includes the frame and titlebar when called from a Form instance I've included a variant that just makes a copy of the client portion of a Form.
This little code snippet uses the SendMessage win API to send a WM_PRINT message that copies the forms visual content. The same functionality is utilized in the built in DrawToBitmap(), but includs the PRF_NONCLIENT flag which includes the titlebar and frame in the copy.
Simply copy the code to the form that you want to be able to take snapshots of. If you cannot modify the form's code you can easily modify the function so that is takes a window handle of the Form instead.private const int WM_PRINT = 0x317; private const int PRF_NON_CLIENT = 0x02; private const int PRF_CLIENT = 0x04; private const int PRF_ERASEBKGND = 0x08; private const int PRF_CHILDREN = 0x10; [DllImport("USER32.DLL")] private static extern int SendMessage(HandleRef hWnd, int Msg, IntPtr wParam, int lParam); public Image DrawToBitmap() { Bitmap image = new Bitmap(this.ClientSize.Width, this.ClientSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (Graphics graphics = Graphics.FromImage(image)) { IntPtr hDC = graphics.GetHdc(); SendMessage(new HandleRef(this, this.Handle), WM_PRINT, hDC, PRF_CLIENT | PRF_CHILDREN | PRF_ERASEBKGND); graphics.ReleaseHdc(hDC); } return image; }
/Calle- Proposed as answer by Michael Sun [MSFT]Microsoft employee, Moderator Monday, July 21, 2008 10:14 AM
- Marked as answer by Michael Sun [MSFT]Microsoft employee, Moderator Tuesday, July 22, 2008 4:20 AM
All replies
-
Since the Control.DrawToBitmap() includes the frame and titlebar when called from a Form instance I've included a variant that just makes a copy of the client portion of a Form.
This little code snippet uses the SendMessage win API to send a WM_PRINT message that copies the forms visual content. The same functionality is utilized in the built in DrawToBitmap(), but includs the PRF_NONCLIENT flag which includes the titlebar and frame in the copy.
Simply copy the code to the form that you want to be able to take snapshots of. If you cannot modify the form's code you can easily modify the function so that is takes a window handle of the Form instead.private const int WM_PRINT = 0x317; private const int PRF_NON_CLIENT = 0x02; private const int PRF_CLIENT = 0x04; private const int PRF_ERASEBKGND = 0x08; private const int PRF_CHILDREN = 0x10; [DllImport("USER32.DLL")] private static extern int SendMessage(HandleRef hWnd, int Msg, IntPtr wParam, int lParam); public Image DrawToBitmap() { Bitmap image = new Bitmap(this.ClientSize.Width, this.ClientSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (Graphics graphics = Graphics.FromImage(image)) { IntPtr hDC = graphics.GetHdc(); SendMessage(new HandleRef(this, this.Handle), WM_PRINT, hDC, PRF_CLIENT | PRF_CHILDREN | PRF_ERASEBKGND); graphics.ReleaseHdc(hDC); } return image; }
/Calle- Proposed as answer by Michael Sun [MSFT]Microsoft employee, Moderator Monday, July 21, 2008 10:14 AM
- Marked as answer by Michael Sun [MSFT]Microsoft employee, Moderator Tuesday, July 22, 2008 4:20 AM
-
Hope it works, very few ActiveX controls implement WM_PRINT properly, if at all. Graphics.CopyFromScreen() is unattractive, even if it didn't have the .NET 2.0 SP1 / V3.5 handle leak bug. WPF has some WF interop capabilities, post in the WPF forum if necessary.
Hans Passant. -
-
-