c# 呼叫Microsoft XPS Document Writer印表機,將Pdf檔案轉換成Xps檔案
阿新 • • 發佈:2019-02-15
最近碰到個專案,其中有個需要將pdf檔案轉換成xps檔案的功能,xps檔案還算是新東西,所以基本沒啥瞭解,通過一段時間的調查,
本人算是找到了2個方法:
1)通過PDFNet第三發開發元件即可很容易的完成轉換功能,並且還有其他針對pdf檔案操作的功能,還是很強大的。當然啦,這個東
西是要買的,可以先下一個試用版先體驗體驗。
2)通過“Microsoft XPS Document Writer”印表機,將pdf列印成本地的xps檔案,以此來完成轉換功能。
這個印表機的驅動在WIN7的系統上裝Office2007的時候會自動裝上,如果是XP系統的話,可能沒有,可以去微軟官網下載個
“SaveAsPDFandXPS.exe”,裝上後,就會有這個印表機。
印表機也有了,那麼接下來的問題就是怎麼呼叫這個印表機了,淡然了,可以通過一系列的API的配合去呼叫這個印表機,但我覺得
Windows的印表機呼叫起來實在是太麻煩了,通過一番調查,可以直接使用Adobe acro Reader或Foxit Reader這兩個軟體的打
印功能,將檔案打出,下面的列出了程式碼供參考。
開發環境:VS2010,.Net FrameWork4.0,C#,WPF
窗體程式碼:
窗體的後臺關鍵程式碼:<Window x:Class="TestPdfToXps1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button Click="Button_Click">PDF TO XPS</Button> </Grid> </Window>
*注:如果是使用Adobe Read進行列印,可以參考下列的部分程式碼using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.ComponentModel; using System.Runtime.InteropServices; namespace TestPdfToXps1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { //Win32 Api定義 [DllImport("user32.dll")] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfeter, string lpszClass, string lpszWindow); [DllImport("user32.dll")] static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, String lParam); [DllImport("user32.dll")] static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); //Win32訊息定義 const uint WM_SETTEXT = 0x000c; const uint WM_IME_KEYDOWN = 0x0290; const uint WM_LBUTTONDOWN = 0x0201; const uint WM_LBUTTONUP = 0x0202; public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { PrintWithFoxitReader(); } void PrintWithFoxitReader() { string pdf_filepath = @"d:\原檔案.pdf"; // 需要轉換的PDF檔案 string xps_filepath = @"d:\目標檔案.xps"; // 目標XPS檔案 /***** 呼叫Foxit Reader.exe的列印功能,並且制定印表機為Microsoft XPS Document Writer *****/ System.Diagnostics.ProcessStartInfo psInfo = new System.Diagnostics.ProcessStartInfo(); psInfo.FileName = @"D:\Tools\Reader\Foxit Reader\Foxit Reader.exe"; //Foxit Reader.exe的全路徑 psInfo.Arguments = String.Format(@" -t {0} ""Microsoft XPS Document Writer""", pdf_filepath); psInfo.CreateNoWindow = true; psInfo.UseShellExecute = false; System.Diagnostics.Process ps = new System.Diagnostics.Process(); ps.StartInfo = psInfo; ps.Start(); // 等待 System.Threading.Thread.Sleep(5 * 1000); /***** 啟動Foxit Reader後,會彈出檔案另存為對話方塊********************************/ /***** 因此使用Win32Api找到檔案另存為對話方塊中的檔名輸入框,並且通過給輸入******/ /***** 框發訊息在輸入框中自動填入目標xps檔名,最後通過給儲存按鈕發訊息來*******/ /***** 最後通過給儲存按鈕發訊息來按下對話方塊中的儲存按鈕**************************/ // 找到檔案另存為對話方塊的視窗控制代碼 IntPtr hWnd = FindWindow("#32770", "檔案另存為"); IntPtr hChild; // 由於輸入框被多個控制元件巢狀,因此需要一級一級的往控制元件內找到輸入框 hChild = FindWindowEx(hWnd, IntPtr.Zero, "DUIViewWndClassName", String.Empty); hChild = FindWindowEx(hChild, IntPtr.Zero, "DirectUIHWND", String.Empty); hChild = FindWindowEx(hChild, IntPtr.Zero, "FloatNotifySink", String.Empty); hChild = FindWindowEx(hChild, IntPtr.Zero, "ComboBox", String.Empty); hChild = FindWindowEx(hChild, IntPtr.Zero, "Edit", String.Empty); // File name edit control // 向輸入框傳送訊息,填充目標xps檔名 SendMessage(hChild, WM_SETTEXT, IntPtr.Zero, xps_filepath); // 等待1秒鐘 System.Threading.Thread.Sleep(1000); // 找到對話方塊內的儲存按鈕 hChild = IntPtr.Zero; hChild = FindWindowEx(hWnd, IntPtr.Zero, "Button", "儲存(&S)"); // 向儲存按鈕傳送2個訊息,以模擬click訊息,藉此來按下儲存按鈕 PostMessage(hChild, WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero); PostMessage(hChild, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero); /***** 跟蹤印表機佇列中的檔案列印狀況,知道檔案列印完成為止 *****/ // 呼叫本地印表機佇列 System.Printing.LocalPrintServer prtSrv = new System.Printing.LocalPrintServer(); System.Printing.PrintQueue queue = prtSrv.GetPrintQueue("Microsoft XPS Document Writer"); //一直監視列印佇列,知道列印佇列中沒有列印任務時結束 do { // 等待處理 System.Threading.Thread.Sleep(1000); // 讀取佇列的最新資訊 queue.Refresh(); } while (queue.NumberOfJobs > 0); MessageBox.Show("完成"); } } }
使用Adcro Readr的相關程式碼:
//將前面的兩行程式碼換成一下程式碼
psInfo.FileName = @"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe";
psInfo.Arguments = String.Format(@" /s /h /t {0} ""Microsoft XPS Document Writer""", pdf_filepath);