无需预览即可打印 WebBrowser,即单击打印

2023-11-24

我有一个 c# .Net 应用程序,它打开一个自定义打印预览表单(损害显示 HTML 文件的 WebBrowser 表单控件和打印 Web 浏览器控件内容的按钮:

webBrowser.Print();

但是,我现在想打印 HTML 文件而不打开此表单。

我尝试将 html 加载到网络浏览器表单中而不显示表单并调用 webBrowser.Print() 但不会打印任何内容。看来只有显示表单并将 HTML 加载到控件中才能打印。


我有一个示例控制台应用程序,它使用 WinForms 打印一组 HTML 文件WebBrowser。您可以借用DoWorkAsync它的一部分用于 WinForms 应用程序中的打印任务,几乎无需任何更改:

// by Noseratio - http://stackoverflow.com/users/1768303/noseratio
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ConsoleApplicationWebBrowser
{
    class Program
    {
        // Entry Point of the console app
        static void Main(string[] args)
        {
            try
            {
                // download each page and dump the content
                var task = MessageLoopWorker.Run(DoWorkAsync,
                    "http://www.example.com", "http://www.example.net", "http://www.example.org");
                task.Wait();
                Console.WriteLine("DoWorkAsync completed.");
            }
            catch (Exception ex)
            {
                Console.WriteLine("DoWorkAsync failed: " + ex.Message);
            }
            Console.WriteLine("Press Enter to exit.");
            Console.ReadLine();
        }

        // navigate WebBrowser to the list of urls in a loop
        static async Task<object> DoWorkAsync(object[] args)
        {
            Console.WriteLine("Start working.");

            var wb = new WebBrowser();
            wb.ScriptErrorsSuppressed = true;

            if (wb.Document == null && wb.ActiveXInstance == null)
                throw new ApplicationException("Unable to initialize the underlying WebBrowserActiveX");

            // get the underlying WebBrowser ActiveX object;
            // this code depends on SHDocVw.dll COM interop assembly,
            // generate SHDocVw.dll: "tlbimp.exe ieframe.dll",
            // and add as a reference to the project
            var wbax = (SHDocVw.WebBrowser)wb.ActiveXInstance;

            TaskCompletionSource<bool> loadedTcs = null;
            WebBrowserDocumentCompletedEventHandler documentCompletedHandler = (s, e) =>
                loadedTcs.TrySetResult(true); // turn event into awaitable task

            TaskCompletionSource<bool> printedTcs = null;
            SHDocVw.DWebBrowserEvents2_PrintTemplateTeardownEventHandler printTemplateTeardownHandler = (p) =>
                printedTcs.TrySetResult(true); // turn event into awaitable task

            // navigate to each URL in the list
            foreach (var url in args)
            {
                loadedTcs = new TaskCompletionSource<bool>();
                wb.DocumentCompleted += documentCompletedHandler;
                try
                {
                    wb.Navigate(url.ToString());
                    // await for DocumentCompleted
                    await loadedTcs.Task;
                }
                finally
                {
                    wb.DocumentCompleted -= documentCompletedHandler;
                }

                // the DOM is ready, 
                Console.WriteLine(url.ToString());
                Console.WriteLine(wb.Document.Body.OuterHtml);

                // print the document
                printedTcs = new TaskCompletionSource<bool>();
                wbax.PrintTemplateTeardown += printTemplateTeardownHandler;
                try
                {
                    wb.Print();
                    // await for PrintTemplateTeardown - the end of printing
                    await printedTcs.Task;
                }
                finally
                {
                    wbax.PrintTemplateTeardown -= printTemplateTeardownHandler;
                }
                Console.WriteLine(url.ToString() + " printed.");
            }

            wb.Dispose();
            Console.WriteLine("End working.");
            return null;
        }

    }

    // a helper class to start the message loop and execute an asynchronous task
    public static class MessageLoopWorker
    {
        public static async Task<object> Run(Func<object[], Task<object>> worker, params object[] args)
        {
            var tcs = new TaskCompletionSource<object>();

            var thread = new Thread(() =>
            {
                EventHandler idleHandler = null;

                idleHandler = async (s, e) =>
                {
                    // handle Application.Idle just once
                    Application.Idle -= idleHandler;

                    // return to the message loop
                    await Task.Yield();

                    // and continue asynchronously
                    // propogate the result or exception
                    try
                    {
                        var result = await worker(args);
                        tcs.SetResult(result);
                    }
                    catch (Exception ex)
                    {
                        tcs.SetException(ex);
                    }

                    // signal to exit the message loop
                    // Application.Run will exit at this point
                    Application.ExitThread();
                };

                // 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();
            });

            // set STA model for the new thread
            thread.SetApartmentState(ApartmentState.STA);

            // start the thread and await for the task
            thread.Start();
            try
            {
                return await tcs.Task;
            }
            finally
            {
                thread.Join();
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无需预览即可打印 WebBrowser,即单击打印 的相关文章

随机推荐

  • 加载 Ninject 组件 ICache 时出错

    我在 asp net web api 项目中使用 ninject 并开始收到此间歇性 ninject 错误 加载 Ninject 组件 ICache 时出错 内核的组件容器中尚未注册此类组件 我在用着 忍者3 0 1 10 Ninject
  • complus异常代码-532462766

    使用Visual Studio 2010 实体框架4 0 ADO NET POCO实体生成器 在代码行上 MecDbEnt Domains AddObject 主题 MecDbEnt SaveChanges 在这条线上 应用程序抛出以下异常
  • 如何使用 CSS 在 HTML 表单中为单选按钮制作多行、垂直和水平对齐的标签?

    假设有以下标记 fieldset legend Radio Buttons legend ol li li ol fieldset
  • 强制 try 块在两者之间中断的最佳方法是什么?

    我有一个try catch阻止我想要的break like a switch阻止但我找不到推荐的方法 我正在获取大量数据try catch块并希望在满足特定条件的情况下停止其间的获取 只是为了让它现在正常工作 我故意强制代码进入catch
  • CBCentralManager iOS10 和 iOS9

    所以我要迁移到 iOS10 但我还需要我的代码在 iOS9 上运行 我正在使用 CoreBluetooth 和 CBCentralManagerDelegate 我可以让我的代码适用于 iOS10 但我也需要后备才能适用于 iOS9 fun
  • len(List) 与读取变量的性能

    类似的问题已经被问过len 函数的成本这里 然而 这个问题着眼于成本len它自己 假设我有一个重复多次的代码len List 每次都是O 1 读取变量也是O 1 再加上分配它也是O 1 作为旁注 我发现n files len Files 比
  • 如何将点击事件从一个div传递到另一个div?

    我需要找到一种方法将点击事件从顶部的 div 传递到其下方的 div 并忽略较高 div 上的点击 有一种已知的方法可以模拟单击事件并将其传递给另一个 div 但这不是自然行为 也是最不想要的选项 看来事件冒泡在这里没有帮助 因为顶部的 d
  • 如何在 YouTube Android 播放器中为 YouTube 视频提供开始和结束参数?

    我正在使用 Youtube Player api 在我的应用程序中播放 YouTube 视频 我想从假设 36 秒开始播放视频 并希望在 65 秒左右结束该视频 例子 我正在使用 youtubeAndroidPlayerApi 我没有找到
  • IIS Web 部署 - 创建虚拟目录?

    在 VS2010 IIS 7 5 上开发站点时 我使用 Web Deploy 将站点从我的计算机发布到开发站点服务器 该站点有大约 40 个虚拟目录 我想在部署期间在服务器上自动创建这些目录 有没有一种简单的方法可以做到这一点 我正在考虑编
  • ASP.NET 表单身份验证和“无身份验证”子文件夹

    是否可以禁用经过表单验证的网站子文件夹中的所有身份验证 你如何做到这一点 是的 将 web config 文件放在子文件夹中 其中包含以下内容
  • 如何构建自定义 libcurl 以仅支持 HTTP / HTTPS 协议

    我仅使用 libcurl 来发出 HTTP HTTPS 请求 我已经下载了源代码并构建为静态库 我的最终可执行文件的大小有所增加 我正在尝试减少我的可执行文件 因为我有其他限制 在分析过程中 我观察到 libcurl 是支持许多协议 包括
  • 如何循环遍历表的所有行? (MySQL)

    我有一张表A 有一个主键ID 现在我想遍历 A 中的所有行 我发现类似 对于 A 中的每条记录 之类的内容 但这似乎不是您在 MySQL 中执行的方式 事情是对于每一行 我想获取一个字段并对其进行转换 将其插入到另一个表中 然后更新该行的一
  • 嵌入编程式 UIView 中的自动布局 XIB 未调整父级的大小

    我有一个 xib 文件 表示一个带有自动布局的简单视图 我正在实例化它 NSBundle mainBundle loadNibNamed name 0 并添加到以编程方式创建的UIView via addSubview 问题是视图没有拉伸以
  • 如何检测Python在幕后进行的方法调用?

    特别是 我想查看特定代码行正在调用哪个魔术方法 例如 我知道1 2实际上打电话 1 add 2 and 1 2 3 0 calls 1 2 3 getitem 0 我想知道其他操作调用了哪些魔术方法 而不必在网上查找 没有一个好的方法来检查
  • 使用 Node js imap 读取电子邮件正文

    我正在尝试读取使用 Node js 检索的电子邮件正文 我正在使用这个 npm 模块 https github com mscdex node imap 除了阅读正文内容之外 我几乎可以获得电子邮件的所有信息 有任何想法吗 Thanks 您
  • Laravel 5.6 aws cloudwatch 日志

    将 laravel 从 5 4 升级到 5 6 Laravel 从 5 6 版本开始删除了 app gt configureMonologUsing aws 的教程不再适用 https aws amazon com tw blogs dev
  • 如何制作没有文字的单选按钮?

    我只想要一个没有文本的简单 RadioBttun 我执行了下面的代码 但我得到的是一个单选按钮小部件 空间很小 我认为这是保留给文本的 那么应该如何摆脱这个空间呢
  • 为什么锁对象必须是静态的?

    在多线程中使用私有静态只读对象进行锁定是很常见的 据我所知 私有通过加强封装减少了锁定对象的入口点 从而减少了对最重要内容的访问 但为什么是静态的呢 private static readonly object Locker new obj
  • 使用 QtCreator 设置 GDB

    我有一个使用OpenCV和cmake的简单项目 并且有两个源文件 只有segmentation h和segmentation cpp 这是 cmake 文件 project Segment cmake minimum required VE
  • 无需预览即可打印 WebBrowser,即单击打印

    我有一个 c Net 应用程序 它打开一个自定义打印预览表单 损害显示 HTML 文件的 WebBrowser 表单控件和打印 Web 浏览器控件内容的按钮 webBrowser Print 但是 我现在想打印 HTML 文件而不打开此表单