简体   繁体   English

如何将HTML加载到WPF的Webbrowser控件中?

[英]How do I load HTML into Webbrowser control for WPF?

My WPF client application is building a custom HTML page, I can load the HTML like this, 我的WPF客户端应用程序正在构建一个自定义HTML页面,我可以像这样加载HTML,

this.myWebBrowser.NavigateToString("<html><body><p>test page</p></body></html>");

The problem I have is how do I load custom HTML into the Webbrowser control, if the HTML has images and css file in it? 我遇到的问题是,如果HTML中包含图像和css文件,如何将自定义HTML加载到Webbrowser控件中?

How do you reference the images and css? 你如何参考图像和CSS? Can the images and css be embedded into the application, or do they need to be in a directory somewhere? 可以将图像和CSS嵌入到应用程序中,还是需要将它们放在某个目录中?

Thanks for the help. 谢谢您的帮助。

Actually, there is such a thing as an HTML page with embedded images. 实际上,有一个带嵌入图像的HTML页面。

You can embed both images and CSS inside an HTML string, using the data URI scheme . 您可以使用数据URI方案将图像和CSS嵌入HTML字符串中。 However, not all versions of IE support this, and the WebBrowser control is really IE. 但是,并非所有版本的IE都支持此功能,而WebBrowser控件实际上就是IE。 If your code might run on a machine with IE < 8, this approach won't help you. 如果你的代码可能在IE <8的机器上运行,这种方法对你没有帮助。

Another option would be to store your images and CSS as embedded resources, write them out to temp files, and then insert absolute URL's to the temp files when you generate your HTML. 另一种选择是将图像和CSS存储为嵌入资源,将它们写入临时文件,然后在生成HTML时将绝对URL插入临时文件。

For the reference, I've stumbled upon this question and used the Joel Mueller answer, but decided to automate parsing the image paths. 作为参考,我偶然发现了这个问题并使用了Joel Mueller的答案,但决定自动解析图像路径。 Maybe somebody will found my code useful for a starter of a similar solution - it's quite rough and dirty, but seems to do the job well. 也许有人会发现我的代码对类似解决方案的启动者很有用 - 它非常粗糙和肮脏,但似乎做得很好。

I am using C# resources, inside my html files I only put image filenames. 我正在使用C#资源,在我的html文件中我只放了图像文件名。 It also allows me to open the file in a normal browser for testing how it'll look. 它还允许我在普通浏览器中打开文件,以测试它的外观。 The code automatically looks for the resource with the same name as filename inside the html, saves it under application data directory, and substitutes the path. 代码自动在html中查找与filename相同的资源,将其保存在应用程序数据目录下,并替换路径。

It's also worth noting that the application will overwrite the file if it differs from the already saved one. 还值得注意的是,如果文件与已保存的文件不同,应用程序将覆盖该文件。 It was mainly needed for the development, but I didn't really had many of those files, so I didn't care about the performance loss here. 它主要用于开发,但我并没有真正拥有这些文件,所以我不关心这里的性能损失。 Omitting this check and assuming the files are up-to-date should enhance the performance. 省略此检查并假设文件是​​最新的应该可以提高性能。

Settings.Default.ApplicationId is a simple string with an application name, used for the directory name inside application data. Settings.Default.ApplicationId是一个带有应用程序名称的简单字符串,用于应用程序数据中的目录名称。

That's how my class ended up looking: 这就是我的班级最终看起来的样子:

    class MyHtmlImageEmbedder
    {
        static protected string _appDataDirectory =
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                Settings.Default.ApplicationId);

        static public string getHtml()
        {
            String apiHelp = Resources.html_file;
            Regex regex = new Regex(@"src=\""(.*)\""", RegexOptions.IgnoreCase);
            MatchCollection mc = regex.Matches(apiHelp);
            foreach (Match m in mc)
            {
                string filename = m.Groups[1].Value;
                Image image = Resources.ResourceManager.GetObject(Path.GetFileNameWithoutExtension(filename)) as Image;
                if (image != null)
                {
                    var path = getPathTo(Path.GetFileNameWithoutExtension(filename) + ".png", imageToPngByteArray(image));
                    apiHelp = apiHelp.Replace(filename, path);
                }
            }
            return apiHelp;
        }

        static public string getPathTo(string filename, byte[] contentBytes)
        {
            Directory.CreateDirectory(_appDataDirectory);
            var path = Path.Combine(_appDataDirectory, filename);
            if (!File.Exists(path) || !byteArrayCompare(contentBytes, File.ReadAllBytes(path)))
            {
                File.WriteAllBytes(path, contentBytes);
            }
            return path;
        }

        [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern int memcmp(byte[] b1, byte[] b2, long count);

        public static bool byteArrayCompare(byte[] b1, byte[] b2)
        {
            // Validate buffers are the same length.
            // This also ensures that the count does not exceed the length of either buffer.  
            return b1.Length == b2.Length && memcmp(b1, b2, b1.Length) == 0;
        }

        public static byte[] imageToPngByteArray(Image image)
        {
            MemoryStream ms = new MemoryStream();
            image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            return ms.ToArray();
        }
    }

Please note that the byteArrayCompareFunction uses memcmp only for performance reasons, but it can be easily substituted with a simple compare loop. 请注意,byteArrayCompareFunction仅出于性能原因使用memcmp,但可以使用简单的比较循环轻松替换它。

Then, I'm just calling browser.NavigateToString(MyHtmlImageEmbedder.getHtml()); 然后,我只是调用browser.NavigateToString(MyHtmlImageEmbedder.getHtml()); .

Since you are generating the HTML, you can set the base url of all script/image by generating a base element which points to somewhere you have control over, like file:/// url pointing to a folder on the disk, a url pointing to localhost where your local web server is listening (too many http server samples on the internet so I don't get into details here), or your web site on the www. 由于您正在生成HTML,因此您可以通过生成指向您可以控制的某个位置的基本元素来设置所有脚本/图像的基本URL,例如指向磁盘上的文件夹的文件:/// url,指向的URL到您本地Web服务器正在侦听的localhost(因特网上有太多的http服务器示例,所以我不在这里详细介绍),或者您的网站在www上。

When you navigate to string, the HTML would be rendered in the same interenet zone as about:blank. 当您导航到字符串时,HTML将在与about:blank相同的interenet区域中呈现。 Depending on the client's IE security zone settings, your HTML may not have have permission to load files in certain locations (like script files on the computer if the page is in the Internet zone). 根据客户端的IE安全区域设置,您的HTML可能没有权限在某些位置加载文件(如果页面位于Internet区域中,则计算机上的脚本文件)。

You can use the Mark of the Web to change your HTML page's internet zone. 您可以使用Web标记更改HTML页面的Internet区域。

You would do it exactly as with every other HTML page. 您可以像其他每个HTML页面一样完成。 The images and CSS would be referenced by URL, just like with any other HTML page. 图像和CSS将由URL引用,就像任何其他HTML页面一样。 There's no magic here. 这里没有魔力。

<WebBrowser Height="200" Name="myWebBrowser"></WebBrowser>
myWebBrowser.NavigateToString("EnterHtmlString");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM