天天看點

【Win 10 應用開發】列印UI元素

Windows App支援将UI界面進行列印的功能,這與浏覽器中的列印網頁的用途相近,其好處就是“所見即所得”,直接把界面上呈現的内容列印下來,比重新建立列印圖像友善得多。

要在通用App中實作列印,主要依靠以下幾個類型:

PrintManager:位于Windows.Graphics.Printing命名空間,主要負責顯示列印對話框,設定列印源等操作。在使用時,首先調用GetForCurrentView靜态方法得到一個PrintManager執行個體;随後處理它的PrintTaskRequested,當要進行列印時就會發生該事件。

PrintTask:表示一個列印任務。在PrintManager對象的PrintTaskRequested事件進行中建立列印任務。

PrintDocument:這個類比較關鍵(位于Windows.UI.Xaml.Printing命名空間)。通過它可以将UI元素轉換為待列印的文檔邏輯。a、處理Paginate事件,以計算列印的分頁,計算後可以調用PrintDocument.SetPreviewPageCount方法來設定預覽頁面的總數。b、處理GetPreviewPage事件,當請求預覽單個頁面時會發生該事件,在處理過程中,可以調用PrintDocument.SetPreviewPage方法來設定要預覽的特定頁面。c、當開始列印時,會發生AddPages事件,此時調用PrintDocument.AddPage方法向列印文檔邏輯添加頁面,當所有要列印的頁面都添加完畢後,請調用AddPagesComplete方法通知系統可以送出列印了。

當你剛剛接觸列印時,你會覺得它好像很複雜,其實,當你動手做過實驗後,你就會發現,其實也沒什麼。我們作為新時代的開發者,應當有迎難而上的精神。

下面咱們來做個例子,把頁面上的一個RichTextBlock控件中的内容列印出來。

頁面上的XAML大緻如下,老周直接貼出來,不作解釋了,我相信你能看懂XAML,如果看不懂,那就算了。

<Border Padding="30" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>
            <StackPanel Margin="0,15" Orientation="Horizontal">
                <Button Content="開始列印" Click="OnClick"/>
            </StackPanel>
            <RichTextBlock Name="tb" Grid.Row="1" Width="300" >
                <Paragraph FontSize="36" TextAlignment="Center" FontFamily="楷體">
                    床前明月光,
                    <LineBreak/>
                    疑是地上霜。
                    <LineBreak/>
                    舉頭望明月,
                    <LineBreak/>
                    低頭思故鄉。
                </Paragraph>
                <Paragraph TextAlignment="Center">
                    <InlineUIContainer>
                        <Image Height="200" Source="http://img155.poco.cn/mypoco/myphoto/20110305/15/20110305154657_366496406.gif"/>
                    </InlineUIContainer>
                </Paragraph>
            </RichTextBlock>
            
            ……
        </Grid>
    </Border>      

咱們這例子要列印的内容,就是那個名為tb的家夥。

進入頁面的代碼檔案,在頁面類中聲明以下字段:

PrintManager printmgr = PrintManager.GetForCurrentView();
        PrintDocument printDic = null;
        RotateTransform rottrf =null;
        PrintTask task = null;      

RotateTransform變量的作用是把tb進行旋轉變換,這是為了處理列印頁面的方向,如果頁面是橫向,我就把tb轉90度。

處理PrintManager的PrintTaskRequested事件,建立列印任務,并設定列印源。

printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
       ……
        private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
        {
            var def = args.Request.GetDeferral();
            // 建立列印任務
            task = args.Request.CreatePrintTask("列印測試", OnPrintTaskSourceRequrested);
            task.Completed += Task_Completed;
            def.Complete();
        }      

在調用CreatePrintTask方法建立列印任務時,有一個參數需要通過一個委托來設定列印源。所謂列印源,就是我們要列印的文檔。

private async void OnPrintTaskSourceRequrested(PrintTaskSourceRequestedArgs args)
        {
            var def = args.GetDeferral();
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                () =>
                {
                    // 設定列印源
                    args.SetSource(printDic?.DocumentSource);
                });
            def.Complete();
        }      

我們這裡要列印的其實就是PrintDocument對象,我們變量命名好像錯了,叫printDoc合理一些,我打成了printDic。沒事,大家知道就OK了。

下面代碼處理按鈕的單擊事件:

private async void OnClick(object sender, RoutedEventArgs e)
        {
            if (printDic != null)
            {
                printDic.GetPreviewPage -= OnGetPreviewPage;
                printDic.Paginate -= PrintDic_Paginate;
                printDic.AddPages -= PrintDic_AddPages;
            }
            this.printDic = new PrintDocument();
            printDic.GetPreviewPage += OnGetPreviewPage;
            printDic.Paginate += PrintDic_Paginate;
            printDic.AddPages += PrintDic_AddPages;

            // 顯示列印對話框
            bool b=await PrintManager.ShowPrintUIAsync();
        }      

在執行個體化PrintDocument後,要處理它的幾個事件。

先處理AddPages事件,這個事件是在開始執行列印時才會發生,在事件進行中要向列印文檔添加頁面,每個頁面的内容就是我們要列印的UI元素,為了簡單,老周隻列印一頁。

private void PrintDic_AddPages(object sender, AddPagesEventArgs e)
        {
            // 添加要列印的頁
            printDic.AddPage(tb);
            // 報告添加完成
            printDic.AddPagesComplete();
        }      

處理Paginate事件,這個事件在打開列印對話框時發生,并且如果使用者調整了列印對話框中的參數後也會發生(比如修改了頁面方向),目的是重新計算頁面的預覽。

private void PrintDic_Paginate(object sender, PaginateEventArgs e)
        {
            PrintTaskOptions opt = task.Options;
            // 根據頁面的方向來調整列印内容的旋轉方向
            switch (opt.Orientation)
            {
                case PrintOrientation.Default:
                    rottrf.Angle = 0d;
                    break;
                case PrintOrientation.Portrait:
                    rottrf.Angle = 0d;
                    break;
                case PrintOrientation.Landscape:
                    rottrf.Angle = 90d;
                    break;
            }

            // 設定預覽頁面的總頁數
            printDic.SetPreviewPageCount(1, PreviewPageCountType.Final);
        }      

下面代碼添加特定頁面的預覽。

private void OnGetPreviewPage(object sender, GetPreviewPageEventArgs e)
        {
            // 設定要預覽的頁面
            printDic.SetPreviewPage(e.PageNumber, this.tb);
        }      

大家要注意,頁面預覽和實際列印是兩回事,是以SetPreviewPage隻是設定要預覽的UI元素,而實際列印是要在AddPages事件中通過AddPage方法來添加頁面。

當示例完成之時,大家可能又遇到問題了,我沒有列印機,怎麼辦? 沒事,老周很窮,也沒有列印機,但不要忘記,系統裡面有這些功能:

【Win 10 應用開發】列印UI元素

是啊,有它們就行,搜尋“裝置與列印機”就能找到它們,是以在運作示例後,直接把内容列印為.pdf文檔就可以了,列印完後,.pdf檔案存到“文檔”目錄中。

現在運作應用程式,然後點選“開始列印”按鈕。

【Win 10 應用開發】列印UI元素

然後會彈出列印對話框。

【Win 10 應用開發】列印UI元素

确認開始列印,點選“列印”按鈕。列印完成後系統會以Toast通知來提醒你。下圖所示是列印出來的.pdf檔案。

【Win 10 應用開發】列印UI元素

好了,是不是有點高大上的感覺呢?

示例代碼下載下傳:https://files.cnblogs.com/files/tcjiaan/printSample.zip

繼續閱讀