¿Cómo arreglar un error de opacidad con DrawToBitmap en WebBrowser Control?

De acuerdo con el siguiente enlace y mi aplicación de consola, el método DrawToBitmap no respeta la opacidad.

Enlace de prueba: http://social.msdn.microsoft.com/Forums/vstudio/en-US/e9704309-0c52-442d-80e0-2f8393dcd313/webbrowser-opacity-problem-

Mi código HTML: http://fiddle.jshell.net/L37TC/

 
ffff
HIDDEN TEXT!
SomeText

Mi código de consola C #:

 var bmp = new Bitmap(640,480, PixelFormat::Format32bppArgb) var web = (System.Windows.Forms.Control)sender; web.DrawToBitmap(bmp, Rectangle(0, 0, 640,480)); 

Así que estoy buscando una solución alternativa .NET ( sin CEF, Awesomium o cualquier extensión ) solo una función incorporada de .NET para solucionar el error o una solución alternativa para tomar una captura de pantalla de una URL web en mi consola solicitud.

Si hago que la ventana de WebBrowser esté visible para mi cliente y uso CopyFromScreen la opacidad se respeta y HIDDEN TEXT no se muestra, sin embargo, no quiero que la ventana de WebBrowser esté visible en la pantalla del escritorio.

Estoy buscando una solución integrada para tomar una captura de pantalla de la URL publicada en la pregunta sin HIDDEN TEXT . En otras palabras, una solución para respetar la opacity .

EDIT1: Todos los píxeles en mi class Bitmap ( class .NET no en formato BMP) tienen un valor alfa de 255. Por lo tanto, el problema NO es con el formato de archivo. He intentado con PNG y cualquier otro formato compatible con .NET.

Código fuente completo (Plantilla de consola, Necesidad de agregar referencias a System.Drawing y System.Windows.Forms

 class Program { static System.Windows.Forms.WebBrowser w = new System.Windows.Forms.WebBrowser(); [STAThread] static void Main(string[] args) { w.Navigate("http://fiddle.jshell.net/L37TC/show/"); w.DocumentCompleted += w_DocumentCompleted; System.Windows.Forms.Application.Run(); while (true) Console.Read(); } static void w_DocumentCompleted(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e) { var bmp = new System.Drawing.Bitmap(w.Width, w.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); ((System.Windows.Forms.Control)w).DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, w.Width, w.Height)); for (int i = 0; i < w.Width; i++) for (int j = 0; j < w.Height; j++) if (bmp.GetPixel(i, j).A != 255) { Console.WriteLine("Alpha != 255"); return; } Console.WriteLine("All pixels have alpha value of 255"); bmp.Save(@"d:\ss.png", System.Drawing.Imaging.ImageFormat.Png); // HIDDEN TEXT has opcity of 0 but it's appearing in image } } 

Estoy buscando una solución integrada para tomar una captura de pantalla de la URL publicada en la pregunta sin HIDDEN TEXT. En otras palabras, una solución para respetar la opacidad.

El siguiente código hace precisamente eso: respeta la opacidad de CSS . Entre otras cosas, utiliza un objeto Metafile y la API OleDraw para representar la imagen de la página web.

La prueba HTML:

   
This is a text

La salida:

opacidad

El código (aplicación de consola):

 using Microsoft.Win32; using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace Console_21697048 { // http://stackoverflow.com/q/21697048/1768303 class Program { const string HTML = "
This is a text
"; const string FILE_NAME = "webpage.png"; readonly static Size IMAGE_SIZE = new Size(320, 200); // Main static void Main(string[] args) { try { // enable HTML5 etc (assuming we're running IE9+) SetFeatureBrowserFeature("FEATURE_BROWSER_EMULATION", 9000); // force software rendering SetFeatureBrowserFeature("FEATURE_IVIEWOBJECTDRAW_DMLT9_WITH_GDI", 1); SetFeatureBrowserFeature("FEATURE_GPU_RENDERING", 0); using (var apartment = new MessageLoopApartment()) { // create WebBrowser on a seprate thread with its own message loop var webBrowser = apartment.Invoke(() => new WebBrowser()); // navigate and wait for the result apartment.Invoke(() => { var pageLoadedTcs = new TaskCompletionSource(); webBrowser.DocumentCompleted += (s, e) => pageLoadedTcs.TrySetResult(true); webBrowser.DocumentText = HTML; return pageLoadedTcs.Task; }).Wait(); // save the picture apartment.Invoke(() => { webBrowser.Size = IMAGE_SIZE; var rectangle = new Rectangle(0, 0, webBrowser.Width, webBrowser.Height); // get reference DC using (var screenGraphics = webBrowser.CreateGraphics()) { var screenHdc = screenGraphics.GetHdc(); // create a metafile using (var metafile = new Metafile(screenHdc, rectangle, MetafileFrameUnit.Pixel)) { using (var graphics = Graphics.FromImage(metafile)) { var hdc = graphics.GetHdc(); var rect = new Rectangle(0, 0, 320, 50); OleDraw(webBrowser.ActiveXInstance, DVASPECT_CONTENT, hdc, ref rectangle); graphics.ReleaseHdc(hdc); } // save the metafile as bitmap metafile.Save(FILE_NAME, ImageFormat.Png); } screenGraphics.ReleaseHdc(screenHdc); } }); // dispose of webBrowser apartment.Invoke(() => webBrowser.Dispose()); webBrowser = null; } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } // interop const uint DVASPECT_CONTENT = 1; [DllImport("ole32.dll", PreserveSig = false)] static extern void OleDraw( [MarshalAs(UnmanagedType.IUnknown)] object pUnk, uint dwAspect, IntPtr hdcDraw, [In] ref System.Drawing.Rectangle lprcBounds); // WebBrowser Feature Control // http://msdn.microsoft.com/en-us/library/ie/ee330733(v=vs.85).aspx static void SetFeatureBrowserFeature(string feature, uint value) { if (LicenseManager.UsageMode != LicenseUsageMode.Runtime) return; var appName = System.IO.Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); Registry.SetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\" + feature, appName, value, RegistryValueKind.DWord); } } // MessageLoopApartment // more info: http://stackoverflow.com/a/21808747/1768303 public class MessageLoopApartment : IDisposable { Thread _thread; // the STA thread TaskScheduler _taskScheduler; // the STA thread's task scheduler public TaskScheduler TaskScheduler { get { return _taskScheduler; } } /// MessageLoopApartment constructor public MessageLoopApartment() { var tcs = new TaskCompletionSource(); // start an STA thread and gets a task scheduler _thread = new Thread(startArg => { EventHandler idleHandler = null; idleHandler = (s, e) => { // handle Application.Idle just once Application.Idle -= idleHandler; // return the task scheduler tcs.SetResult(TaskScheduler.FromCurrentSynchronizationContext()); }; // handle Application.Idle just once // to make sure we're inside the message loop // and SynchronizationContext has been correctly installed Application.Idle += idleHandler; Application.Run(); }); _thread.SetApartmentState(ApartmentState.STA); _thread.IsBackground = true; _thread.Start(); _taskScheduler = tcs.Task.Result; } /// shutdown the STA thread public void Dispose() { if (_taskScheduler != null) { var taskScheduler = _taskScheduler; _taskScheduler = null; // execute Application.ExitThread() on the STA thread Task.Factory.StartNew( () => Application.ExitThread(), CancellationToken.None, TaskCreationOptions.None, taskScheduler).Wait(); _thread.Join(); _thread = null; } } /// Task.Factory.StartNew wrappers public void Invoke(Action action) { Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, _taskScheduler).Wait(); } public TResult Invoke(Func action) { return Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, _taskScheduler).Result; } } }