Screenshot method generates black images

After you did not use control.drawtobitmap in C #, my second option was to take screenshots of the desktop and cut out the necessary sections. My hiccup appears when I switch user accounts, although the program does not crash, as soon as the user switches, the program generates only black black images.

I used this code as a reference: WebBrowser.DrawToBitmap () or other methods?

I assume this is logical, it makes sense, as it will help Windows save resources.

What options / solutions do I have in my situation?

Edit 1 made changes to the code for testing:

int c = 0; while (true) { try { c++; Rectangle formBounds = this.Bounds; Bitmap bmp = new Bitmap(formBounds.Width, formBounds.Height); using (Graphics g = Graphics.FromImage(bmp)) g.CopyFromScreen(formBounds.Location, Point.Empty, formBounds.Size); bmp.Save("picture" + c.ToString() + ".jpg"); Thread.Sleep(5000); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } 

this works fine in the user account, but as soon as I switch users, it throws an exception: the handle is invalid.

Any ideas?

Edit 2:

The error in DrawToBitmap is not exactly random ... if I used the code you provided:

 Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); this.DrawToBitmap(bmp, this.ClientRectangle); bmp.Save(".\\picture.jpg"); 

It works great, for example: http://oi61.tinypic.com/1z23ynp.jpg

However, the moment I right-clicked the web browser control, DrawToBitmap will return a blank image.

example: http://oi60.tinypic.com/9ay0yc.jpg

Therefore, I can easily overcome this error by adding

 ((Control)webbrowser1).Enabled = false; 

this makes any click impossible in a web browser, but unfortunately to deactivate it will make my project useless, since its main function is emulation of mouse clicks on a web browser. although this can also be a problem if the window is hidden.

I am currently looking at this post where code is provided to give you a window handle.

To simulate a click in a hidden window , it seems, it may be some kind of value ... really look.

+2
c # browser windows-7 bitmap screenshot
Jun 20 '14 at 15:41
source share
4 answers

What were the problems with DrawToBitmap? It works great here (W8.1, VS2013) even with Webcontrol, and also after switching users. (But see Editing at the end of the conditions!)

 Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); this.DrawToBitmap(bmp, this.ClientRectangle); // Clipboard.SetImage(bmp); for testing only bmp.Dispose(); 

Here is the code to take a screenshot of your window:

 Rectangle formBounds = this.Bounds; Bitmap bmp = new Bitmap(formBounds.Width, formBounds.Height ); using (Graphics g = Graphics.FromImage(bmp)) g.CopyFromScreen(formBounds.Location, Point.Empty, formBounds.Size); //Clipboard.SetImage(bmp); for testing only bmp.Dispose(); 

I can switch users as I want, the program continues to work.

By the way, the link you posted is really old, many things can be improved.

Edit:

With the updated question, everything is much clearer.

So, you want to constantly get a screenshot of your program, even when the user has changed, right? and you want to display WebControl, right?

A user can have three types of desktop: an input / output screen, a splash screen, and one or more regular desktop screens. But while the user is logging out, he does not have a desktop screen at all.

Therefore, the screenshot method will not work if the user does not have an active desktop, and not like g.CopyFromScreen , which will cause a GDI error or use a window handle, as in various solutions on the Internet, including those related to your link leads to. All this, at best, will show a blank or black screen.

So the DrawToBitmap method is the only one that works.

You wrote that he has random errors. This is not what I see.

Problems arise in a predictable way when a user interacts with WebBrowser in any way. This includes scrolling or clicking with or without navigation. After these interactions, WebBrowser will draw itself as an empty box until its URL is reloaded - not only updated, but webBrowser1.Uri = new Uri(uriPath) will also be reloaded. This can be done, see my other post.

WebBrowser also has another problem when executing DrawToBitmap : it will fail (with the specified blank field) for any pages containing the <input type="text" element. I'm not sure how best to solve this, not to mention why this happens in the first place. The screenshot method does not have this particular problem.

Edit 2:

The OP code dug up a code that, using the PrintWindow call, seems to solve all the problems that we had: it works when you log out, works with Refeshing even after clicking in WebBrowser and resets all pages, including text input fields. Hoorah!

After reducing sagging, there is a version that can create a copy of Form or just WebBroser (or any other Control ) with or without borders:

 [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags); public Bitmap CaptureWindow(Control ctl) { //Bitmap bmp = new Bitmap(ctl.Width, ctl.Height); // includes borders Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height); // content only using (Graphics graphics = Graphics.FromImage(bmp)) { IntPtr hDC = graphics.GetHdc(); try { PrintWindow(ctl.Handle, hDC, (uint)0); } finally { graphics.ReleaseHdc(hDC); } } return bmp; } 
+4
Jun 20 '14 at 17:08
source share

Finally, this code works even when I switched users.

Code for taking a snapshot of any unsaved Notepad process (Untitled - Notepad)

  private void Form1_Load(object sender, EventArgs e) { //loop for debugging int c = 0; while(true) { c++; System.Drawing.Bitmap image = CaptureWindow(FindWindow(null, "Untitled - Notepad")); image.Save(".\\picture"+c.ToString()+".jpg"); Thread.Sleep(5000); } } [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags); [DllImport("user32.dll")] public static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); public System.Drawing.Bitmap CaptureWindow(IntPtr hWnd) { System.Drawing.Rectangle rctForm = System.Drawing.Rectangle.Empty; using (System.Drawing.Graphics grfx = System.Drawing.Graphics.FromHdc(GetWindowDC(hWnd))) { rctForm = System.Drawing.Rectangle.Round(grfx.VisibleClipBounds); } System.Drawing.Bitmap pImage = new System.Drawing.Bitmap(rctForm.Width, rctForm.Height); System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(pImage); IntPtr hDC = graphics.GetHdc(); try { PrintWindow(hWnd, hDC, (uint)0); } finally { graphics.ReleaseHdc(hDC); } return pImage; } 

Please note that the window may be hidden, but it should be maximized in the user account in order to get a full screenshot.

+2
Jun 21 '14 at 22:09
source share

Digital Rights Management can stop this because Windows adds protection for digital media.

If, for example, you are trying to create a screen capture in Media Player or Media Center using Graphics Graphics rendering - yes, Microsoft is going to "protect you from any potential lawsuit."

Try this: click "Print Screen" on your keyboard, and then go to Microsoft Paint and try pasting your screen capture on it. Is there anything?

+1
Jun 20 '14 at 18:42
source share

I ran into the same problem and I could not use the CopyFromScreen method because my form with WebBrowser might be hidden. The PrintWindow method also did not work, generating images with black areas, especially when my MDI form is partially covered by the MDI parent form.

Finally, I used the OleDraw method, as in this section on SO, but integrated it into a class derived from WebBrowser. Essentially, it simply cancels the standard control response to the WM_PRINT message. This allows you to create a regular Control.DrawToBitmap not only for WebBrowser, but also for a form with WebBrowser. This also works if the form is hidden (covered by another form, including the parent MDI form) and should work when the user has blocked the session with Win + L (I did not check it).

 public class WebBrowserEx : WebBrowser { private const uint DVASPECT_CONTENT = 1; [DllImport("ole32.dll", PreserveSig = false)] private static extern void OleDraw([MarshalAs(UnmanagedType.IUnknown)] object pUnk, uint dwAspect, IntPtr hdcDraw, [In] ref System.Drawing.Rectangle lprcBounds ); protected override void WndProc(ref Message m) { const int WM_PRINT = 0x0317; switch (m.Msg) { case WM_PRINT: Rectangle browserRect = new Rectangle(0, 0, this.Width, this.Height); // Don't know why, but drawing with OleDraw directly on HDC from m.WParam. // results in badly scaled (stretched) image of the browser. // So, drawing to an intermediate bitmap first. using (Bitmap browserBitmap = new Bitmap(browserRect.Width, browserRect.Height)) { using (var graphics = Graphics.FromImage(browserBitmap)) { var hdc = graphics.GetHdc(); OleDraw(this.ActiveXInstance, DVASPECT_CONTENT, hdc, ref browserRect); graphics.ReleaseHdc(hdc); } using (var graphics = Graphics.FromHdc(m.WParam)) { graphics.DrawImage(browserBitmap, Point.Empty); } } // ignore default WndProc return; } base.WndProc(ref m); } } 
0
Apr 09 '19 at 13:37
source share



All Articles