问题描述
根据下面的链接,我的控制台应用程序的方法 DrawToBitmap
不尊重透明度。
证明链接:http://social.msdn.microsoft.com/Forums/vstudio/en-US/e9704309-0c52-442d-80e0-2f8393dcd313/webbrowser-opacity-problem-
我的HTML code: http://fiddle.jshell.net/L37TC/
< DIV ID =推子的风格=背景颜色:#FF0000> FFFF< / DIV>
< DIV的风格=背景颜色:蓝色,不透明度:0;过滤器:α(不透明度= 0);!>隐匿文字< / DIV>
SomeText
我的C#控制台code:
VAR BMP =新位图(640,480,的PixelFormat :: Format32bppArgb)
VAR网络=(System.Windows.Forms.Control的)发送;
web.DrawToBitmap(BMP,矩形(0,0,640480));
所以我在寻找替代.NET内置的解决方案(没有CEF,Awesomium,或任何扩展的请的)只是一个内置的.NET功能以修复该错误或替代解决方案采取的Web URL的屏幕截图在我的控制台应用程序。
如果我让 web浏览器
窗口看到我的客户,并使用 CopyFromScreen
的不透明度尊重和隐藏文本
不显示,怎么过的,我不想让 web浏览器
窗可见的桌面屏幕。
我在寻找一个内置的解决方案,采取从问题发布网址的截图没有隐藏文本
。换句话说解决的尊重透明度
EDIT1:在我的位图
类
(.NET类没有BMP所有像素格式)具有255的α值,因此问题不在于文件格式。我曾尝试PNG和其他任何.NET支持的格式。
完整源$ C $ C(控制台模板,需要将引用添加到 System.Drawing中
和 System.Windows.Forms的
类节目
{
静态System.Windows.Forms.WebBrowser W =新System.Windows.Forms.WebBrowser();
[STAThread]
静态无效的主要(字串[] args)
{
w.Navigate(http://fiddle.jshell.net/L37TC/show/);
w.DocumentCompleted + = w_DocumentCompleted;
System.Windows.Forms.Application.Run();
而(真)Console.Read();
}
静态无效w_DocumentCompleted(对象发件人,System.Windows.Forms.WebBrowserDocumentCompletedEventArgs E)
{
VAR BMP =新System.Drawing.Bitmap(w.Width,w.Height,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
((System.Windows.Forms.Control的)瓦特).DrawToBitmap(BMP,新System.Drawing.Rectangle(0,0,w.Width,w.Height));
对(INT I = 0; I&其中; w.Width; i ++在)为(诠释J = 0; J&所述; w.Height; J ++)如果(!bmp.GetPixel(I,J).A = 255)
{
Console.WriteLine(阿尔法= 255!);
返回;
}
Console.WriteLine(所有的像素有255阿尔法值);
bmp.Save(@D:\ ss.png,System.Drawing.Imaging.ImageFormat.Png);
//隐藏的文本有0 opcity但它出现在图像
}
}
下面code做到了这一点:方面的CSS不透明度。除其他事项外,它使用的对象的 API来渲染网页的形象。
测试HTML:
<!DOCTYPE HTML><车身风格=背景颜色:灰色'> <股利风格=背景色:蓝色;不透明度:0.2;颜色:黄色'>这是一个文字< / DIV>< /身体GT;
输出:
的code (控制台应用程序):
使用的Microsoft.Win32;使用系统;使用System.ComponentModel;使用System.Drawing中;使用System.Drawing.Imaging;使用了System.Runtime.InteropServices;使用的System.Threading;使用System.Threading.Tasks;使用System.Windows.Forms的;命名空间Console_21697048{ // http://stackoverflow.com/q/21697048/1768303 类节目 { 常量字符串的HTML =< DOCTYPE HTML><车身风格=背景色:灰!><股利风格=背景颜色:蓝色,不透明:0.2;颜色:黄色'>这是一个文字< / DIV>< /身体GT;; 常量字符串FILE_NAME =webpage.png; 只读静态尺寸IMAGE_SIZE =新的大小(320,200); // 主要 静态无效的主要(字串[] args) { 尝试 { //启用HTML5等(假设我们正在运行IE9 +) SetFeatureBrowserFeature(FEATURE_BROWSER_EMULATION,9000); //力软件渲染 SetFeatureBrowserFeature(FEATURE_IVIEWOBJECTDRAW_DMLT9_WITH_GDI,1); SetFeatureBrowserFeature(FEATURE_GPU_RENDERING,0); 使用(VAR公寓=新MessageLoopApartment()) { //与自己的消息循环一个seprate线程创建web浏览器 VAR web浏览器= apartment.Invoke(()=>新建web浏览器()); //导航并等待结果 apartment.Invoke(()=> { VAR pageLoadedTcs =新TaskCompletionSource<布尔>(); webBrowser.DocumentCompleted + =(S,E)=> pageLoadedTcs.TrySetResult(真正的); webBrowser.DocumentText = HTML; 返回pageLoadedTcs.Task; })。等待(); //保存图片 apartment.Invoke(()=> { webBrowser.Size = IMAGE_SIZE; VAR矩形=新的Rectangle(0,0,webBrowser.Width,webBrowser.Height); //获取参考DC 使用(VAR screenGraphics = webBrowser.CreateGraphics()) { 变种screenHdc = screenGraphics.GetHdc(); //创建一个图元文件 使用(VAR图元文件=新的图元文件(screenHdc,矩形,MetafileFrameUnit.Pixel)) { 使用(VAR图形= Graphics.FromImage(图元文件)) { 变种HDC = graphics.GetHdc(); 变种矩形=新矩形(0,0,320,50); OleDraw(webBrowser.ActiveXInstance,DVASPECT_CONTENT,HDC,裁判矩形); graphics.ReleaseHdc(HDC); } //保存图元文件的位图 metafile.Save(FILE_NAME,ImageFormat.Png); } screenGraphics.ReleaseHdc(screenHdc); } }); //处理web浏览器的 apartment.Invoke(()=> webBrowser.Dispose()); web浏览器= NULL; } } 赶上(例外前) { Console.WriteLine(ex.ToString()); } } //互操作 常量UINT DVASPECT_CONTENT = 1; [的DllImport(OLE32.DLL,preserveSig = FALSE)] 静态外部无效OleDraw( [的MarshalAs(UnmanagedType.IUnknown)对象朋克, UINT dwAspect, IntPtr的hdcDraw, [在] REF System.Drawing.Rectangle lprcBounds); // web浏览器功能控制 // http://msdn.microsoft.com/en-us/library/ie/ee330733(v=vs.85).aspx 静态无效SetFeatureBrowserFeature(字符串功能,UINT值) { 如果(LicenseManager.UsageMode!= LicenseUsageMode.Runtime) 返回; 变种的appName = System.IO.Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess()MainModule.FileName。); Registry.SetValue(@HKEY_CURRENT_USER \软件\微软\的Internet Explorer \ MAIN \ FeatureControl \+功能, 的appName,价值,RegistryValueKind.DWord); } } // MessageLoopApartment //更多信息:http://stackoverflow.com/a/21808747/1768303 公共类MessageLoopApartment:IDisposable的 { 螺纹_Thread; // STA线程 的TaskScheduler _taskScheduler; // STA线程的任务调度 公众的TaskScheduler的TaskScheduler {{返回_taskScheduler; }} ///<总结> MessageLoopApartment构造< /总结> 公共MessageLoopApartment() { VAR TCS =新TaskCompletionSource<的TaskScheduler>(); //启动一个STA线程,并得到一个任务调度 _Thread =新主题(startArg => { 事件处理程序idleHandler = NULL; idleHandler =(S,E)=> { //处理Application.Idle只有一次 Application.Idle - = idleHandler; //返回任务调度程序 tcs.SetResult(TaskScheduler.FromCurrentSynchronizationContext()); }; //处理Application.Idle只有一次 //确保我们的消息循环中 //和的SynchronizationContext已经正确安装 Application.Idle + = idleHandler; Application.Run(); }); _thread.SetApartmentState(ApartmentState.STA); _thread.IsBackground = TRUE; _thread.Start(); _taskScheduler = tcs.Task.Result; } ///<总结>关机STA线程< /总结> 公共无效的Dispose() { 如果(_taskScheduler!= NULL) { VAR的TaskScheduler = _taskScheduler; _taskScheduler = NULL; // STA线程上执行Application.ExitThread() Task.Factory.StartNew( ()=> Application.ExitThread(), CancellationToken.None, TaskCreationOptions.None, 的TaskScheduler).Wait(); _thread.Join(); _Thread = NULL; } } ///<总结> Task.Factory.StartNew包装< /总结> 公共无效调用(动作的动作) { Task.Factory.StartNew(动作, CancellationToken.None,TaskCreationOptions.None,_taskScheduler).Wait(); } 公共TResult调用< TResult>(Func键< TResult>动作) { 返回Task.Factory.StartNew(动作, CancellationToken.None,TaskCreationOptions.None,_taskScheduler)。结果; } }}
According to following link and my console application the method DrawToBitmap
doesn't respect opacity.
My HTML code : http://fiddle.jshell.net/L37TC/
<div id="fader" style="background-color: #ff0000">ffff</div>
<div style="background-color: blue; opacity:0;filter:alpha(opacity=0);">HIDDEN TEXT!</div>
SomeText
My C# console code :
var bmp = new Bitmap(640,480, PixelFormat::Format32bppArgb)
var web = (System.Windows.Forms.Control)sender;
web.DrawToBitmap(bmp, Rectangle(0, 0, 640,480));
So I'm looking for alternative .NET built-in solution (no CEF, Awesomium, or any extension please) just a built-in feature of .NET to fix the bug or alternative solution to take screenshot of a web URL in my console application.
If I make WebBrowser
window visible to my client and use CopyFromScreen
the opacity is respected and HIDDEN TEXT
isn't showing, how ever I don't want to make WebBrowser
window visible to desktop screen.
I'm looking for a built-in solution to take a screenshot from posted URL in the question without HIDDEN TEXT
. In other words a solution to respect opacity
.
EDIT1: All pixels in my Bitmap
class
(.NET class not BMP format) has alpha value of 255. So the problem is NOT with file format. I have tried PNG and any other .NET supported format.
Complete source code (Console Template, Need to add references to System.Drawing
and 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
}
}
The following code does just that: respects CSS opacity. Amongst other things, it uses a Metafile
object and OleDraw
API to render the web page's image.
The test HTML:
<!DOCTYPE html>
<body style='background-color: grey'>
<div style='background-color: blue; opacity: 0.2; color: yellow'>This is a text</div>
</body>
The output:
The code (console app):
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 = "<!DOCTYPE html><body style='background-color: grey'><div style='background-color: blue; opacity: 0.2; color: yellow'>This is a text</div></body>";
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<bool>();
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; } }
/// <summary>MessageLoopApartment constructor</summary>
public MessageLoopApartment()
{
var tcs = new TaskCompletionSource<TaskScheduler>();
// 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;
}
/// <summary>shutdown the STA thread</summary>
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;
}
}
/// <summary>Task.Factory.StartNew wrappers</summary>
public void Invoke(Action action)
{
Task.Factory.StartNew(action,
CancellationToken.None, TaskCreationOptions.None, _taskScheduler).Wait();
}
public TResult Invoke<TResult>(Func<TResult> action)
{
return Task.Factory.StartNew(action,
CancellationToken.None, TaskCreationOptions.None, _taskScheduler).Result;
}
}
}
这篇关于如何修复与DrawToBitmap上WebBrowser控件一个不透明的错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!