Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用WPF在C#中静默打印HTML文件_C#_Html_Wpf_Printing_Wpf Controls - Fatal编程技术网

使用WPF在C#中静默打印HTML文件

使用WPF在C#中静默打印HTML文件,c#,html,wpf,printing,wpf-controls,C#,Html,Wpf,Printing,Wpf Controls,编辑:完全重写问题并添加悬赏 根据许多教程和stackoverflow问题,我现在可以: 将多个页面一起打印为一个文档 打印实际内容 正确对齐页面上的内容 打印大小正确的文档 解决方案要求HTML文档底部有一些空白,样式标记HTML{overflow:hidden;}-隐藏滚动条并允许滚动用于分页,但我可以接受这一点 剩下的唯一问题是WPF不会渲染webbrowser屏幕外的部分 这意味着,如果我倾斜我的电脑屏幕,我可以正确打印,但如果我不这样做的文件切断了较低的部分 我尝试渲染为位图,但当

编辑:完全重写问题并添加悬赏

根据许多教程和stackoverflow问题,我现在可以:

  • 将多个页面一起打印为一个文档
  • 打印实际内容
  • 正确对齐页面上的内容
  • 打印大小正确的文档
解决方案要求HTML文档底部有一些空白,样式标记HTML{overflow:hidden;}-隐藏滚动条并允许滚动用于分页,但我可以接受这一点

剩下的唯一问题是WPF不会渲染webbrowser屏幕外的部分

这意味着,如果我倾斜我的电脑屏幕,我可以正确打印,但如果我不这样做的文件切断了较低的部分

我尝试渲染为位图,但当我将生成的图像打印为可视图像时,页面是空的

如果您知道如何强制WPF完全渲染或如何正确渲染位图,请帮助我

打印窗口XAML:(打印WPF只在UI线程上工作,否则不会呈现任何内容…)

自定义分页器:

public class WebPaginator : DocumentPaginator
    {
        private readonly WebBrowser webBrowser;
        private readonly int pageScroll;
        private Size pageSize;

        public WebPaginator(WebBrowser webBrowser, int pageScroll, double pageHeight, double pageWidth)
        {
            this.webBrowser = webBrowser;
            this.pageScroll = pageScroll;
            pageSize = new Size(pageWidth, pageHeight);
        }

        public override DocumentPage GetPage(int pageNumber)
        {
            HTMLDocument htmlDoc = webBrowser.Document as HTMLDocument;
            if (htmlDoc != null) htmlDoc.parentWindow.scrollTo(0, pageScroll * pageNumber);
            Rect area = new Rect(pageSize);

            return new DocumentPage(webBrowser, pageSize, area, area);
        }

        public override bool IsPageCountValid
        {
            get { return true; }
        }

        /// <summary>
        /// Returns one less than actual length.
        /// Last page should be whitespace, used for scrolling.
        /// </summary>
        public override int PageCount
        {
            get
            {
                var doc = (IHTMLDocument2)webBrowser.Document;
                var height = ((IHTMLElement2)doc.body).scrollHeight;
                int tempVal = height*10/pageScroll;
                tempVal = tempVal%10 == 0
                    ? Math.Max(height/pageScroll, 1)
                    : height/pageScroll + 1;
                return tempVal > 1 ? tempVal-1 : tempVal;
            }
        }

        public override Size PageSize
        {
            get
            {
                return pageSize;
            }
            set
            {
                pageSize = value;
            }
        }

        /// <summary>
        /// Can be null.
        /// </summary>
        public override IDocumentPaginatorSource Source
        {
            get
            {
                return null;
            }
        }
    }
公共类WebPaginator:DocumentPaginator
{
专用只读网络浏览器;
私有只读int页面滚动;
私人大小页面大小;
公共网页导航器(WebBrowser WebBrowser、int pageScroll、双页高、双页宽)
{
this.webBrowser=webBrowser;
this.pageScroll=页面滚动;
pageSize=新大小(pageWidth、pageHeight);
}
公共覆盖文档页面GetPage(内部页码)
{
HTMLDocument htmlDoc=webBrowser.Document为HTMLDocument;
如果(htmlDoc!=null)htmlDoc.parentWindow.scrollTo(0,pageScroll*pageNumber);
Rect区域=新Rect(页面大小);
返回新文档页面(webBrowser、pageSize、area、area);
}
公共覆盖bool IsPageCountValid
{
获取{return true;}
}
/// 
///返回比实际长度小一个的值。
///最后一页应该是空白,用于滚动。
/// 
公共覆盖整页计数
{
得到
{
var doc=(IHTMLDocument2)webBrowser.Document;
变量高度=((IHTMLElement2)文档正文)。滚动高度;
int tempVal=高度*10/页滚动;
tempVal=tempVal%10==0
?数学最大值(高度/页面滚动,1)
:高度/页面滚动+1;
返回tempVal>1?tempVal-1:tempVal;
}
}
公共覆盖大小PageSize
{
得到
{
返回页面大小;
}
设置
{
pageSize=值;
}
}
/// 
///可以为空。
/// 
公共覆盖IDocumentPaginatorSource源
{
得到
{
返回null;
}
}
}

您可以使用标准IE的打印功能(通过),如下所示:

public partial class PrintWindow : Window
{
    public PrintWindow()
    {
        InitializeComponent();
        webBrowser.Navigate("http://www.google.com");
    }

    // I have added a button to demonstrate
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // NOTE: this works only when the document as been loaded
        IOleServiceProvider sp = webBrowser.Document as IOleServiceProvider;
        if (sp != null)
        {
            Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
            Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");
            const int OLECMDID_PRINT = 6;
            const int OLECMDEXECOPT_DONTPROMPTUSER = 2;

            dynamic wb; // will be of IWebBrowser2 type, but dynamic is cool
            sp.QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, out wb);
            if (wb != null)
            {
                // note: this will send to the default printer, if any
                wb.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, null, null);
            }
        }
    }

    [ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IOleServiceProvider
    {
        [PreserveSig]
        int QueryService([MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [MarshalAs(UnmanagedType.LPStruct)]  Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);
    }
}

试试这个链接。使用IHTMLDocument2打印也会生成一个空文档并始终提示用户,即使在execCommand调用中将ShowUI设置为false。直接从UI打印是绝对要求吗?我是说从网络浏览器那里?您是否考虑过将相同的URL单独传递给为此目的而设计的更好的工具?也许吧?最终,从PDF打印将产生更一致的结果,一旦它击中纸张…嗯,不,我开始意识到,webbrowser控制方法是完全不可能的。它不是一个真正的WPF控件,而是一个包装的COM控件。这意味着它不会做你让它做的事。我设法让它觉得屏幕比实际的要大,但由于它是一个COM控件,所以它没有渲染,只是黑色。我还尝试了RenderRotateTransform,但控件中的内容保持未旋转。我会考虑你的链接/解决方案,但我有点厌倦尝试随机的东西了。我可能会完全改变我的方法。我的投票,我认为这是一个很好的答案(可以直接从webBrowser_LoadCompleted中调用,根据您的说明),我也会建议在这种情况下使用IE的打印功能,即使我个人倾向于使用工具(如SharpDevelopmentPrePrinting)和从PDF打印(如上面评论中所述)这可以工作,但它会以双面/双面打印吗?(我现在没有访问打印机的权限,只有XPS文件打印机)它将使用默认打印机和默认设置进行打印,不管它们是什么。是的,开箱即用。复制粘贴此文件并检查打印机默认值-无问题:)如果无法更改默认打印机,并且所需打印机不是默认打印机,是否有这样的答案?
public class WebPaginator : DocumentPaginator
    {
        private readonly WebBrowser webBrowser;
        private readonly int pageScroll;
        private Size pageSize;

        public WebPaginator(WebBrowser webBrowser, int pageScroll, double pageHeight, double pageWidth)
        {
            this.webBrowser = webBrowser;
            this.pageScroll = pageScroll;
            pageSize = new Size(pageWidth, pageHeight);
        }

        public override DocumentPage GetPage(int pageNumber)
        {
            HTMLDocument htmlDoc = webBrowser.Document as HTMLDocument;
            if (htmlDoc != null) htmlDoc.parentWindow.scrollTo(0, pageScroll * pageNumber);
            Rect area = new Rect(pageSize);

            return new DocumentPage(webBrowser, pageSize, area, area);
        }

        public override bool IsPageCountValid
        {
            get { return true; }
        }

        /// <summary>
        /// Returns one less than actual length.
        /// Last page should be whitespace, used for scrolling.
        /// </summary>
        public override int PageCount
        {
            get
            {
                var doc = (IHTMLDocument2)webBrowser.Document;
                var height = ((IHTMLElement2)doc.body).scrollHeight;
                int tempVal = height*10/pageScroll;
                tempVal = tempVal%10 == 0
                    ? Math.Max(height/pageScroll, 1)
                    : height/pageScroll + 1;
                return tempVal > 1 ? tempVal-1 : tempVal;
            }
        }

        public override Size PageSize
        {
            get
            {
                return pageSize;
            }
            set
            {
                pageSize = value;
            }
        }

        /// <summary>
        /// Can be null.
        /// </summary>
        public override IDocumentPaginatorSource Source
        {
            get
            {
                return null;
            }
        }
    }
public partial class PrintWindow : Window
{
    public PrintWindow()
    {
        InitializeComponent();
        webBrowser.Navigate("http://www.google.com");
    }

    // I have added a button to demonstrate
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // NOTE: this works only when the document as been loaded
        IOleServiceProvider sp = webBrowser.Document as IOleServiceProvider;
        if (sp != null)
        {
            Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
            Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");
            const int OLECMDID_PRINT = 6;
            const int OLECMDEXECOPT_DONTPROMPTUSER = 2;

            dynamic wb; // will be of IWebBrowser2 type, but dynamic is cool
            sp.QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, out wb);
            if (wb != null)
            {
                // note: this will send to the default printer, if any
                wb.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER, null, null);
            }
        }
    }

    [ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IOleServiceProvider
    {
        [PreserveSig]
        int QueryService([MarshalAs(UnmanagedType.LPStruct)] Guid guidService, [MarshalAs(UnmanagedType.LPStruct)]  Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);
    }
}