打印以编程方式创建的矩形

Posted

技术标签:

【中文标题】打印以编程方式创建的矩形【英文标题】:Print rectangle created programmatically 【发布时间】:2021-06-15 08:16:19 【问题描述】:

我想将 WebView 设置为 WebViewBrush 以便添加内部矩形和打印矩形。我想在后端做所有事情,我不想使用 XAML 代码。

我这样做是因为我在获得打印预览时得到模糊/模糊的文本。所以人们说解决这个问题的方法是创建WebViewBrush,然后创建一个矩形来打印它

首先我将画布和画笔创建为:

  private Windows.UI.Xaml.Controls.WebView ViewToPrint = new Windows.UI.Xaml.Controls.WebView();
  private Windows.UI.Xaml.Controls.WebViewBrush wvBrush = new Windows.UI.Xaml.Controls.WebViewBrush();
  private Windows.UI.Xaml.Shapes.Rectangle rectangle = new Windows.UI.Xaml.Shapes.Rectangle();

然后在方法中我将 WebView 分配给 WebViewBrush 并将其添加到矩形中,

public async void Print(Xamarin.Forms.WebView viewToPrint, string html)
        
        ViewToPrint.NavigateToString(html);
        wvBrush.SetSource(ViewToPrint);
        wvBrush.Redraw();
        rectangle.Fill = wvBrush;
        rectangle.Width = 200;
        rectangle.Height = 200;

        

然后在打印预览方法中,我希望看到矩形预览为:

 private void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
        
           
            printDoc.SetPreviewPage(e.PageNumber, rectangle);
        

但是我的矩形是空白的,我看不到里面的任何东西。我做错了什么

重现问题:

Xamarin 共享项目类:

   private readonly IPrintUWPService _printUWPService = DependencyService.Get<IPrintUWPService>();

   public void Printhtml()
        
        
   var meta = "<meta name='viewport' content='width=device-width, initial-scale=5.0, maximum-scale=5.0, minimum-scale=1.0'>";
            var style = "<style>svgheight:140px; width:140px; pfont-size:20px; </style>";

         var  _htmlSource = @$"
                    <!DOCTYPE html>
                    <html>
                    <head>
                      meta
                       style
                    </head>
                    <body>
                   <table border = '1px solid'; style='border-collapse:collapse;'>
                    <tbody>
                    <tr>
                    <td>qr</td>
                    <td>
                    <p><b>Heat Number:number</b></p>
                    <p><b> Cylinder Type Name: cylindername</b></p>
                   <p><b> Color: colorname</b></p>
                    </td>
                    </tr>
                    </tbody>
                    </table>
                    </body>
                    </html>
                    ";
          Print(_htmlSource);

        
     

  public void Print(string _htmlSource)
        
            _printUWPService.Print( _htmlSource);
        

共享项目中的接口:

public interface IPrintUWPService
    
        void Print(string html);
    

UWP 项目服务:

 public class PrintUWPService : IPrintUWPService
    
        PrintManager printmgr = PrintManager.GetForCurrentView();
        PrintDocument PrintDoc;
        PrintDocument printDoc;
        PrintTask Task;
        private Windows.UI.Xaml.Controls.WebView ViewToPrint = new Windows.UI.Xaml.Controls.WebView();
        private DeviceInformationCollection deviceCollection;
        private Windows.UI.Xaml.Shapes.Rectangle rectangle = new Windows.UI.Xaml.Shapes.Rectangle();


        public PrintUWPService()
        
            printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
        

        public async void Print(Xamarin.Forms.WebView viewToPrint, string html)
        


            ViewToPrint.NavigateToString(html);
            //MakePage();


            if (PrintDoc != null)
            
                printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
                printDoc.Paginate -= PrintDoc_Paginate;
                printDoc.AddPages -= PrintDoc_AddPages;
            

            printDoc = new PrintDocument();

            try
            
                printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
                printDoc.Paginate += PrintDoc_Paginate;
                printDoc.AddPages += PrintDoc_AddPages;

                var showprint = PrintManager.ShowPrintUIAsync();

            
            catch (Exception e)
            
                Debug.WriteLine(e.ToString());
            

            PrintDoc = null;
            GC.Collect();
        

        private void MakePage()
        
            var brush = new WebViewBrush
            
                Stretch = (Windows.UI.Xaml.Media.Stretch)Windows.UI.Xaml.Media.Stretch.Uniform
            ;
            
            brush.SetSource(ViewToPrint);
            brush.Redraw();

            using (var waitHandle = new System.Threading.ManualResetEventSlim(initialState: false))
                waitHandle.Wait(TimeSpan.FromMilliseconds(5000));

            rectangle.Width = 200;
            rectangle.Height = 200;
            rectangle.Fill = brush;
            brush.Stretch = (Windows.UI.Xaml.Media.Stretch)Windows.UI.Xaml.Media.Stretch.UniformToFill;
            brush.AlignmentY = AlignmentY.Top;
            rectangle.Name = "MyWebViewRectangle";

            rectangle.Visibility = Windows.UI.Xaml.Visibility.Visible;
        

        private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
        
            var deff = args.Request.GetDeferral();
            Task = args.Request.CreatePrintTask($"Card Stock  DateTime.Now", OnPrintTaskSourceRequested);

            deff.Complete();

        
        async void OnPrintTaskSourceRequested(PrintTaskSourceRequestedArgs args)
        

            var def = args.GetDeferral();
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            
                args.SetSource(printDoc.DocumentSource);
            );
            def.Complete();
        

        private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
        
            printDoc.AddPage(rectangle);
            printDoc.AddPagesComplete();
        

        private async void PrintDoc_Paginate(object sender, PaginateEventArgs e)
        
            PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);
            deviceCollection =  await DeviceInformation.FindAllAsync("System.Devices.InterfaceClassGuid:=\"0ecef634-6ef0-472a-8085-5ad023ecbccd\"");
           var rolloPrinter = deviceCollection.Where(x => x.Name.Contains("Rollo")).SingleOrDefault();

            // Get the page description to deterimine how big the page is
            PrintPageDescription pageDescription = printingOptions.GetPageDescription(0);

            PrintTaskOptions opt = Task.Options;

            printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
        

        private  void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
        
            printDoc.SetPreviewPage(e.PageNumber, rectangle);
        

      
    

【问题讨论】:

【参考方案1】:

用 WebView 数据填充矩形

根据您的描述,在调用 print api 之前,您似乎没有在 xaml 中渲染矩形。并将其插入printDoc 页面。请参考这个案例reply,先渲染矩形。

Rectangle page = (Rectangle)this.FindName("MyWebViewRectangle");
printDoc.AddPage(page);
printDoc.AddPagesComplete();

更新

在检查你的代码时,我找到了原因,问题是你没有在视觉树中渲染你的 WebView 使得 WebViewBrush 不起作用。 通常需要为在 XAML 中声明的 WebViewBrush 在与 WebView 源相同的 UI 中调用 Redraw。 有关更多信息,请参阅 this。

您可以使用以下行来验证这一点。

public void Print(string html)

    // render current ViewToPrint
    Window.Current.Content = ViewToPrint;
    ViewToPrint.NavigateToString(html);

    if (PrintDoc != null)
    
        printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
        printDoc.Paginate -= PrintDoc_Paginate;
        printDoc.AddPages -= PrintDoc_AddPages;
    

    printDoc = new PrintDocument();

    try
    
        printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
        printDoc.Paginate += PrintDoc_Paginate;
        printDoc.AddPages += PrintDoc_AddPages;

        var showprint = PrintManager.ShowPrintUIAsync();

    
    catch (Exception e)
    
        Debug.WriteLine(e.ToString());
    

    //PrintDoc = null;
    //GC.Collect();

  

【讨论】:

我没有在服务上使用 XAML。所以我不能使用“this.FindName”,这就是我使用矩形作为全局变量的原因。所以我尝试:Windows.UI.Xaml.Shapes.Rectangle page = (Windows.UI.Xaml.Shapes.Rectangle)rectangle; printDoc.SetPreviewPage(e.PageNumber, page); 但是是一样的。空白页 它是否呈现在您当前的内容中? 如果我直接使用ViewToPrint.NavigateToString(html); 为:printDoc.SetPreviewPage(e.PageNumber, ViewToPrint); 它可以正常工作,我可以正确获得打印视图但存在模糊问题,所以我想将其转换为矩形来解决它 我认为矩形需要在打印之前渲染。 但是在调用服务时会渲染矩形,因为它是全局变量还是我错了?

以上是关于打印以编程方式创建的矩形的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式为 Windows 创建空打印机?

当内部按钮触摸时,如何从 Superview 中删除以编程方式创建的子视图?

以编程方式从网页或单个 DIV 创建图像

如何获取在 Xamarin MacOS 中以编程方式创建的 NSTextField 的值?

在 OpenOffice Calc 中以编程方式更改打印区域

在 SwiftUI 中,如何为条形图创建动态矩形?