Après le format XPS, voici la version DOC et PDF. Pour pouvoir générer des images à partir de ces types de documents, j'ai testé plusieurs bibliothéques gratuites et libres que l'on peut trouver en cherchant sur Internet. Après plusieurs tests infructueux, j'ai opté pour l'utilisation des composants COM de l'outil PDFCreator. Cette solution est un peu moins intuitive que celle utilisée pour les XPS, peu de documentation existe malheureusement pour manipuler au mieux ces objets COM, un petit exemple ici de documentation sur cet objet COM.
Voici le code que j'ai utilisé afin de pouvoir traiter les documents DOC et les PDF.
Tout d'abord, l'activation d'une instance de l'objet COM de PDFCreator :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
string parameters; pErr = new PDFCreator.clsPDFCreatorError();
_PDFCreator = new PDFCreator.clsPDFCreator(); _PDFCreator.eError += new PDFCreator.__clsPDFCreator_eErrorEventHandler(_PDFCreator_eError); _PDFCreator.eReady += new PDFCreator.__clsPDFCreator_eReadyEventHandler(_PDFCreator_eReady);
parameters = "/NoProcessingAtStartup";
// ouverture de l'objet COM PDFCreator if (!_PDFCreator.cStart(parameters, false)) { System.Windows.MessageBox.Show("Attention", "PDFCreator est déjà ouvert !"); this.Close(); }
|
Ensuite, les options d'impression sont définies :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// option d'impression opt = _PDFCreator.cOptions; opt.UseAutosave = 1; opt.UseAutosaveDirectory = 1; opt.AutosaveDirectory = fi.DirectoryName; opt.AutosaveFormat = FileTyp; opt.AutosaveStartStandardProgram = 1; opt.PNGColorscount = 1; opt.OptionsVisible = 0; opt.NoProcessingAtStartup = 1; opt.AutosaveFilename = fname; _PDFCreator.cOptions = opt;
_PDFCreator.cClearCache(); |
Puis, l'imprimante PDFCreator est définie comme l'imprimante par défaut :
1 2 3 |
// définition de l'imprimante par défaut DefaultPrinter = _PDFCreator.cDefaultPrinter; _PDFCreator.cDefaultPrinter = "PDFCreator"; |
Le seul problème majeur que j'ai rencontré concerne les fichiers PDF. Lors du lancement de l'impression, la méthode d'impression de l'objet COM ouvre une instance du document PDF avec le logiciel approprié (dans mon cas il s'agit d'Adobe Reader). Et tant que l'utilisateur ne ferme pas manuellement le logiciel, le traitement du document est bloqué. J'ai identifié d'où venait le problème mais il faudrait que je modifie le code du composant COM et je n'en ai pas le temps et/ou les compétences pour le faire. Pour palier à cela, j'ai utilisé un pop-up pour avertir l'utilisateur de bien vouloir fermer le lecteur de PDF. Je sais que ce n'est pas la manière la plus élégante, et la plus transparente pour l'utilisateur, mais pour moi c'est celle qui fournira le moins de problèmes une fois mon projet fini (bientôt j'espère
). Si certains d'entre vous ont une solution je suis preneuse !
Ensuite l'impression peut commencer :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// impression _PDFCreator.cPrintFile(fi.FullName);
ReadyState = false; _PDFCreator.cPrinterStop = false;
// attente jusqu'à la fin de l'impression do { System.Windows.Forms.Application.DoEvents(); } while (!ReadyState && _PDFCreator.cProgramIsRunning);
_PDFCreator.cPrinterStop = true;
// retour de l'imprimante par défaut du départ _PDFCreator.cDefaultPrinter = DefaultPrinter;
|
Enfin la méthode qui permet de fermer l'objet COM, lorsque l'impression est terminée :
1 2 3 4 5 6 7 8 9 10 11 12 |
private void ClosePDFCreator() { // fermeture de l'objet COM PDFCreator _PDFCreator.cClose(); System.Runtime.InteropServices.Marshal.ReleaseComObject(_PDFCreator); System.Runtime.InteropServices.Marshal.ReleaseComObject(pErr); pErr = null; GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } |
Pour l'affichage des images, j'ai utilisé le même WPFControlBook de Mitsu et le même user control UCBitmap qui m'avait permis d'afficher un Bitmap dans un control Image dans un application WPF, dont j'avais parlé dans un post précédent, sauf qu'ici ce sont des PNG que j'affiche :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
private void Window_Loaded(object sender, RoutedEventArgs e) { object itemPage;
try { // génération des images PNG SaveDocPageToPng();
// ajout des images comme item du user control for (int i = 1; i < pageCount; i++) { string source = FileName + i + ".png"; UCPng bt = new UCPng(source);
itemPage = (object)bt; myBook.Items.Add(itemPage); } } catch { ClosePDFCreator(); } }
|
Voici la comparaison de disposition des pages, entre une lecture par défilement, et une lecture au format codex :

Dans cet exemple, j'ai utilisé le format PNG pour la génération d'images, qui permet une plus grande compression des images que le BMP et donc les fichiers générés tiennent moins de place sur le disque dur. Par exemple, pour un document de 111 pages, en les générant en BMP j'obtiens un dossier pesant 690 Mo et en PNG seulement 5 Mo !
Pour conclure, le traitement avec des objets COM est un peu plus contraignant car il faut s'appuyer sur une application externe, en l'occurence PDFCreator, et il faut que l'utilisateur est cette application d'installée sur sa machine. Malgré tout je suis arrivée au but que je recherchais
.
(Pour l'exemple de document et de pdf, j'ai pris un ebook de William Shakespeare trouvé ici)