Publié dimanche 8 juin 2008 20:43 par Audrey

[WPF] Après le XPS, un petit lecteur de DOC et de PDF

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 Wink). 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 :

Comparaison DOC - WPF

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 Smile.

(Pour l'exemple de document et de pdf, j'ai pris un ebook de William Shakespeare trouvé ici)

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Classé sous , , ,

Les 10 derniers blogs postés

- Silverlight 3 : Communication et multicast par Kévin Gosse le il y a 8 heures et 6 minutes

- [Perso] Découvertes estivales : Linux (Part I) par Le blog de FremyCompany le il y a 10 heures et 48 minutes

- [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le 07-04-2009, 00:50

- [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le 07-03-2009, 23:36

- SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le 07-03-2009, 09:56

- [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le 07-03-2009, 09:00

- MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le 07-03-2009, 08:45

- Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

- C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

- Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15