- 論壇徽章:
- 0
|
(轉(zhuǎn))
Windows App支持將UI界面進(jìn)行打印的功能,這與瀏覽器中的打印網(wǎng)頁(yè)的用途相近,其好處就是“所見即所得”,直接把界面上呈現(xiàn)的內(nèi)容打印下來(lái),比重新創(chuàng)建打印圖像方便得多。
要在通用App中實(shí)現(xiàn)打印,主要依靠以下幾個(gè)類型:
PrintManager:位于Windows.Graphics.Printing命名空間,主要負(fù)責(zé)顯示打印對(duì)話框,設(shè)置打印源等操作。在使用時(shí),首先調(diào)用GetForCurrentView靜態(tài)方法得到一個(gè)PrintManager實(shí)例;隨后處理它的PrintTaskRequested,當(dāng)要進(jìn)行打印時(shí)就會(huì)發(fā)生該事件。
PrintTask:表示一個(gè)打印任務(wù)。在PrintManager對(duì)象的PrintTaskRequested事件處理中創(chuàng)建打印任務(wù)。
PrintDocument:這個(gè)類比較關(guān)鍵(位于Windows.UI.Xaml.Printing命名空間)。通過(guò)它可以將UI元素轉(zhuǎn)換為待打印的文檔邏輯。a、處理Paginate事件,以計(jì)算打印的分頁(yè),計(jì)算后可以調(diào)用PrintDocument.SetPreviewPageCount方法來(lái)設(shè)置預(yù)覽頁(yè)面的總數(shù)。b、處理GetPreviewPage事件,當(dāng)請(qǐng)求預(yù)覽單個(gè)頁(yè)面時(shí)會(huì)發(fā)生該事件,在處理過(guò)程中,可以調(diào)用PrintDocument.SetPreviewPage方法來(lái)設(shè)置要預(yù)覽的特定頁(yè)面。c、當(dāng)開始打印時(shí),會(huì)發(fā)生AddPages事件,此時(shí)調(diào)用PrintDocument.AddPage方法向打印文檔邏輯添加頁(yè)面,當(dāng)所有要打印的頁(yè)面都添加完畢后,請(qǐng)調(diào)用AddPagesComplete方法通知系統(tǒng)可以提交打印了。
當(dāng)你剛剛接觸打印時(shí),你會(huì)覺得它好像很復(fù)雜,其實(shí),當(dāng)你動(dòng)手做過(guò)實(shí)驗(yàn)后,你就會(huì)發(fā)現(xiàn),其實(shí)也沒什么。我們作為新時(shí)代的開發(fā)者,應(yīng)當(dāng)有迎難而上的精神。
下面咱們來(lái)做個(gè)例子,把頁(yè)面上的一個(gè)RichTextBlock控件中的內(nèi)容打印出來(lái)。
頁(yè)面上的XAML大致如下,老周直接貼出來(lái),不作解釋了,我相信你能看懂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/>
- 低頭思故鄉(xiāng)。
- </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>
復(fù)制代碼 咱們這例子要打印的內(nèi)容,就是那個(gè)名為tb的家伙。
進(jìn)入頁(yè)面的代碼文件,在頁(yè)面類中聲明以下字段:- PrintManager printmgr = PrintManager.GetForCurrentView();
- PrintDocument printDic = null;
- RotateTransform rottrf =null;
- PrintTask task = null;
復(fù)制代碼 RotateTransform變量的作用是把tb進(jìn)行旋轉(zhuǎn)變換,這是為了處理打印頁(yè)面的方向,如果頁(yè)面是橫向,我就把tb轉(zhuǎn)90度。
處理PrintManager的PrintTaskRequested事件,創(chuàng)建打印任務(wù),并設(shè)置打印源。- printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
- ……
- private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
- {
- var def = args.Request.GetDeferral();
- // 創(chuàng)建打印任務(wù)
- task = args.Request.CreatePrintTask("打印測(cè)試", OnPrintTaskSourceRequrested);
- task.Completed += Task_Completed;
- def.Complete();
- }
復(fù)制代碼 在調(diào)用CreatePrintTask方法創(chuàng)建打印任務(wù)時(shí),有一個(gè)參數(shù)需要通過(guò)一個(gè)委托來(lái)設(shè)置打印源。所謂打印源,就是我們要打印的文檔。- private async void OnPrintTaskSourceRequrested(PrintTaskSourceRequestedArgs args)
- {
- var def = args.GetDeferral();
- await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
- () =>
- {
- // 設(shè)置打印源
- args.SetSource(printDic?.DocumentSource);
- });
- def.Complete();
- }
復(fù)制代碼 我們這里要打印的其實(shí)就是PrintDocument對(duì)象,我們變量命名好像錯(cuò)了,叫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;
- // 顯示打印對(duì)話框
- bool b=await PrintManager.ShowPrintUIAsync();
- }
復(fù)制代碼 在實(shí)例化PrintDocument后,要處理它的幾個(gè)事件。
先處理AddPages事件,這個(gè)事件是在開始執(zhí)行打印時(shí)才會(huì)發(fā)生,在事件處理中要向打印文檔添加頁(yè)面,每個(gè)頁(yè)面的內(nèi)容就是我們要打印的UI元素,為了簡(jiǎn)單,老周只打印一頁(yè)。- private void PrintDic_AddPages(object sender, AddPagesEventArgs e)
- {
- // 添加要打印的頁(yè)
- printDic.AddPage(tb);
- // 報(bào)告添加完成
- printDic.AddPagesComplete();
- }
復(fù)制代碼 處理Paginate事件,這個(gè)事件在打開打印對(duì)話框時(shí)發(fā)生,并且如果用戶調(diào)整了打印對(duì)話框中的參數(shù)后也會(huì)發(fā)生(比如修改了頁(yè)面方向),目的是重新計(jì)算頁(yè)面的預(yù)覽。- private void PrintDic_Paginate(object sender, PaginateEventArgs e)
- {
- PrintTaskOptions opt = task.Options;
- // 根據(jù)頁(yè)面的方向來(lái)調(diào)整打印內(nèi)容的旋轉(zhuǎn)方向
- switch (opt.Orientation)
- {
- case PrintOrientation.Default:
- rottrf.Angle = 0d;
- break;
- case PrintOrientation.Portrait:
- rottrf.Angle = 0d;
- break;
- case PrintOrientation.Landscape:
- rottrf.Angle = 90d;
- break;
- }
- // 設(shè)置預(yù)覽頁(yè)面的總頁(yè)數(shù)
- printDic.SetPreviewPageCount(1, PreviewPageCountType.Final);
- }
復(fù)制代碼 下面代碼添加特定頁(yè)面的預(yù)覽。- private void OnGetPreviewPage(object sender, GetPreviewPageEventArgs e)
- {
- // 設(shè)置要預(yù)覽的頁(yè)面
- printDic.SetPreviewPage(e.PageNumber, this.tb);
- }
復(fù)制代碼 大家要注意,頁(yè)面預(yù)覽和實(shí)際打印是兩回事,因此SetPreviewPage只是設(shè)置要預(yù)覽的UI元素,而實(shí)際打印是要在AddPages事件中通過(guò)AddPage方法來(lái)添加頁(yè)面。
當(dāng)示例完成之時(shí),大家可能又遇到問(wèn)題了,我沒有打印機(jī),怎么辦? 沒事,老周很窮,也沒有打印機(jī),但不要忘記,系統(tǒng)里面有這些功能:
1.png (12.43 KB, 下載次數(shù): 88)
下載附件
2015-06-16 09:50 上傳
是啊,有它們就行,搜索“設(shè)備與打印機(jī)”就能找到它們,所以在運(yùn)行示例后,直接把內(nèi)容打印為.pdf文檔就可以了,打印完后,.pdf文件存到“文檔”目錄中。
現(xiàn)在運(yùn)行應(yīng)用程序,然后點(diǎn)擊“開始打印”按鈕。
1.png (79.07 KB, 下載次數(shù): 88)
下載附件
2015-06-16 09:50 上傳
然后會(huì)彈出打印對(duì)話框。
1.png (66.95 KB, 下載次數(shù): 95)
下載附件
2015-06-16 09:51 上傳
確認(rèn)開始打印,點(diǎn)擊“打印”按鈕。打印完成后系統(tǒng)會(huì)以Toast通知來(lái)提醒你。下圖所示是打印出來(lái)的.pdf文件。
1.png (68.92 KB, 下載次數(shù): 80)
下載附件
2015-06-16 09:52 上傳
好了,是不是有點(diǎn)高大上的感覺呢? |
|