Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

[WPF] XPS Reader

Suite à mes bouts de code sur la conversion de documents XPS en BMP (ici) pour les afficher dans le control WPFControlBook de Mitsu, j'ai réalisé cette petite application en WPF, qui permet de lire un document XPS dans une interface lui permettant de tourner les pages.

Cette fois-ci, les pages du document XPS sont générées en PNG, qui tiennent beaucoup moins d'espace, donc plus pratique à stocker Smile. J'ai rajouté des boutons, pour pouvoir naviguer de pages en pages, et il est possible de double-cliquer sur les pages pour les tourner. Les images PNG sont générées mais ne sont pas effacées à la fermeture, et lors de la ré-ouverture du document XPS, elles seront ré-utilisées.

Pour en savoir plus, le code source est disponible sur Codeplex : http://www.codeplex.com/XPSReader

Voici quelques captures d'écran de l'application :

XPSReader - Open document         XPSReader - Loading

XPSReader - Reader

Ceci est la version 0.1 du projet XPS Reader, d'autres versions devraient voir le jour au fur et à mesure Smile.

Posté le par Audrey | 3 commentaire(s)
Classé sous : ,

[Silverlight] Comment bien débuter avec Silverlight 2.0 ?

C'est la question que je me suis posée lorsque j'ai voulu m'initier à Silverlight 2.0. Voici les pistes que j'ai suivi.

Tout d'abord le coach Silverlight présent sur le site MSDN :

Coach Silverlight

J'ai choisi de suivre la formation pour la version 2.0, le fait de pouvoir coder en C# dans un projet Silverlight est la partie qui m'intéresse le plus.

3 liens sont proposés pour parcourir et apprendre les bases de cette technologie :

  • Le premier est une rapide présentation, qui pose bien les bases de la technologie, et avec une vidéo de Pierre Lagarde qui montre un petit exemple en Silverlight 2.0 qui met l'eau à la bouche.
  • Le deuxième est la liste de ce qu'il faut installer pour pouvoir développer avec Silverlight 2.0, avec tous les liens qui vont bien.
  • Et enfin le troisième est une série de 7 travaux pratiques qui permettent d'apprendre les bases de Silverlight 2.0.

(Les mêmes infos sont aussi disponible pour Silverlight 1.0)

Ensuite, j'ai cherché d'autres cours ou tutoriaux sur Silverlight 2.0 mais il en existe peu, voici un exemple assez complet écrit par Benjamin Roux : http://broux.developpez.com/articles/csharp/introduction-silverlight-2/

Des webcasts existent, je vous conseille la série Silverlight Academy animé par Eric Ambrosi, que vous pourrez trouver ici. Elle se compose de 14 webcasts.

De plus 2 sites existent concernant Silverlight :

      http://silverlight.net/

      http://www.microsoft.com/silverlight

Maintenant que je connais les bases de Silverlight 2.0, je vais pouvoir m'amuser à faire des petits projets qui bougent dans tous les sens Wink

Petite note de fin, après avoir réalisé en WPF un control BookControls (dont je me suis servi ici et ), Mitsu l'a maintenant réalisé en Silverlight, pour plus d'infos c'est par ici !

Enjoy !

Posté le par Audrey | 4 commentaire(s)
Classé sous :

[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)

Posté le par Audrey | 0 commentaire(s)
Classé sous : , ,

[WPF] Application.DoEvents()

Pendant que je codais la suite du projet (un premier bout ici) sur lequel je bosse actuellement (et qui fera l'objet d'un prochain post Wink), j'ai voulu utiliser la méthode suivante :

Application.DoEvents()

Or cette méthode n'existe pas dans WPF. Pour palier à cela j'ai effectué quelques recherches sur Internet et voici 2 différentes solutions que j'ai trouvées et ensuite testées, et qui peuvent remplacer cette méthode.

La première consiste à faire référence à System.Windows.Form.dll et à utiliser Application.DoEvents() qui est disponible dans cette assembly.

Le seconde consiste en deux méthodes qui permettent de remplacer la méthode souhaitée (je copie les méthodes pour ceux qui aurait la flemme de cliquer sur le lien, et pour les autres c'est par ici) :

using System;
using System.Windows;
using System.Windows.Threading;

namespace Sheva.Windows
{

/// <summary>
/// Designates a Windows Presentation Foundation application model with added functionalities.
/// </summary>

public class WpfApplication : Application
{
   private static DispatcherOperationCallback exitFrameCallback = new

   DispatcherOperationCallback(ExitFrame);

   /// <summary> 
   /// Processes all UI messages currently in the message queue.
   /// </summary>

   public static void DoEvents()
   {
      // Create new nested message pump.

      DispatcherFrame nestedFrame = new DispatcherFrame();

      // Dispatch a callback to the current message queue, when getting called,
      // this callback will end the nested message loop.
      // note that the priority of this callback should be lower than the that of UI event messages.

      DispatcherOperation exitOperation = Dispatcher.CurrentDispatcher.BeginInvoke(
      DispatcherPriority.Background, exitFrameCallback, nestedFrame);

      // pump the nested message loop, the nested message loop will
      // immediately process the messages left inside the message queue.

      Dispatcher.PushFrame(nestedFrame);

      // If the "exitFrame" callback doesn't get finished, Abort it.

      if (exitOperation.Status != DispatcherOperationStatus.Completed)
      {
         exitOperation.Abort();
      }
   }

   private static Object ExitFrame(Object state)
   {
      DispatcherFrame frame = state as DispatcherFrame;

      // Exit the nested message loop.

      frame.Continue = false;
      return null;
   }

}
}


 

J'aurai tendance à dire que la première méthode est la plus simple à mettre en place et la plus compréhensible pour quelqu'un qui devrait maintenir le code de l'application. La seconde permet de ne pas faire référence à une autre assembly, et de pouvoir modifier au besoin le travail du DoEvents().

Et vous qu'en pensez-vous ? Toutes les suggestions sont les bienvenues ! Smile

Posté le par Audrey | 2 commentaire(s)
Classé sous :

[WPF] Un petit lecteur de XPS

Après une soirée à coder, voici ma première petite application WPF. En utilisant le control WPFControlBook que Mitsu avait développé (ici) j'ai créé un petit lecteur de fichiers XPS. Le document XPS est ouvert et on peut le lire en tournant les pages à la souris. Voici une capture d'écran pour illustrer un peu mieux c'est que j'ai essayé de faire :

Pour réaliser cela, il suffit simplement de déposer le control Book (WPFBookControl) dans la form pour pouvoir s'en servir.

Ensuite il restait à résoudre le problème du lecteur XPS, il existe un control DocumentViewer qui permet de lire un document XPS, mais je voulais pouvoir traiter chaque page séparement afin de pouvoir les associer au control Book. Pour cela, j'ai inclus un petit morceau de code trouvé sur le forum MSDN US (ici) qui permet de générer chaque page du fichier XPS en fichier BMP :

public void SaveXpsPageToBitmap(string xpsFileName)
{
   XpsDocument xpsDoc = new XpsDocument(xpsFileName, System.IO.FileAccess.Read);
   FixedDocumentSequence docSeq = xpsDoc.GetFixedDocumentSequence();

   int pageCount = docSeq.References[0].GetDocument(false).Pages.Count;

   for (int pageNum = 0; pageNum < pageCount; pageNum++)
   {
      DocumentPage docPage = docSeq.DocumentPaginator.GetPage(pageNum);
      BitmapImage bitmap = new BitmapImage();
      RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)docPage.Size.Width,
                                            (int)docPage.Size.Height,96,96,
                                            System.Windows.Media.PixelFormats.Pbgra32);
      renderTarget.Render(docPage.Visual);

      BitmapEncoder encoder = new BmpBitmapEncoder();
      encoder.Frames.Add(BitmapFrame.Create(renderTarget));

      FileStream pageOutStream = new FileStream(xpsFileName + ".Page" + pageNum + ".bmp", FileMode.Create, FileAccess.Write);
      encoder.Save(pageOutStream);
      pageOutStream.Close();
   }
}

J'ai ensuite créé un user control UCBitmap qui permet d'afficher un Bitmap dans un control Image.

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
   Stream imageStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read);
   BitmapImage myImageStream = new BitmapImage();
   myImageStream.BeginInit();
   myImageStream.StreamSource = imageStream;
   myImageStream.EndInit();
   imagePage.Source = myImageStream;
}

Et avec une boucle permettant de passer chaque page du document XPS, je récupère le fichier Bitmap généré plus tôt et je l'affiche dans une instance de mon user control UCBitmap que j'associe ensuite au control Book de ma form principale, tout cela lorsque l'application est chargée.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
   object itemPage;

   SaveXpsPageToBitmap(FileName);

   for (int i = 0; i < pageCount; i++)
   {
      string source = FileName + ".Page" + i + ".bmp";
      UCBitmap bt = new UCBitmap(source);

      itemPage = (object)bt;
      myBook.Items.Add(itemPage);
   }
}

Et enfin lorsque l'application est lancée, le fichier XPS s'affiche et grâce à la souris, on peut facilement feuilleter ce document XPS Smile  

Lecteur XPS 2

 

 

 

 

 

 

 

 

 

 

 

Ce code n'est pas spécialement optimisé, il est le fruit de mes recherches d'une soirée. Tous les commentaires sont les bienvenus Wink

Ces bouts de codes sont les prémices d'une application un peu plus compléte que je souhaite réaliser en WPF et qui fera l'objet de plusieurs posts d'ici quelques temps.

Posté le par Audrey | 4 commentaire(s)
Classé sous : ,

[WPF / Linq] Deux livres à lire !

Pour me lancer dans WPF et Linq, j'ai cherché quelques livres pour apprendre les bases et j'ai trouvé 2 livres que je conseille particulièrement à tous ceux qui veulent en apprendre plus sur ces 2 technos.

Tout d'abord pour WPF, "Programming WPF" que vous pouvez trouver ici

Programming WPF

Ce gros pavé commence par un "Hello World" classique en WPF pour continuer sur tous les éléments essentiels pour savoir programmer en avec WPF, les différents contrôles, le binding, la 2D, la 3D, etc... Ce qui est très appréciable aussi sont les parties annexes comme celle sur le XAML par exemple.

Et pour Linq, "Linq in Action" que vous pouvez trouver ici

Linq in Action

Beaucoup de monde dit du bien de ce livre c'est pourquoi je l'ai choisi pour débuter et je le conseille à toute personne voulant monter en compétences sur Linq. Ce bouquin est à la fois clair tout en abordant tous les sujets essentiels (Linq to SQL, Linq to XML, Linq to Objects) et en incluant beaucoup d'exemples de codes. Pour moi une référence !

Bonne lecture ! Smile

Posté le par Audrey | 0 commentaire(s)
Classé sous : , ,

Et encore un nouveau blog sur Codes-Sources !

Bonjour à tous !

Et voici enfin mon blog technique, je tiens à remercier Matthieu et Cyril pour m'avoir aider à ouvrir ce blog. Je travaille à Winwise depuis un peu plus d'un an maintenant et je fais partie du pôle Rich Internet & Desktop Applications. Actuellement je me concentre sur WPF, Silverlight et Linq, donc la plupart de mes posts devraient tourner autour de ces 3 thèmes pour essayer de vous faire partager mes découvertes et interrogations à leurs sujets.

A très bientôt !

Posté le par Audrey | 12 commentaire(s)
Classé sous :


Les 10 derniers blogs postés

- Un outil pour réaliser des animations WPF basées sur des équations de Bézier par Perspective le il y a 2 heures et 17 minutes

- Sandcastle et CodePlex : le verdict par CoqBlog le il y a 3 heures et 8 minutes

- Webcasts sur le Parallel Framework disponibles par Matthieu MEZIL le il y a 6 heures et 36 minutes

- [Silverlight] - Comprendre et Débuter avec Silverlight par Danuz le il y a 11 heures et 21 minutes

- SharePoint : Nouvel article sur l'exportation et Importation de sites SharePoint par Blog Technique de Romelard Fabrice le il y a 23 heures et 2 minutes

- ImagineCup 2008 Final in Paris: Day 1 par Richard Clark le 07-03-2008, 22:48

- PowerShell : Comment utiliser un ENUM .NET dans un script PowerShell par Blog Technique de Romelard Fabrice le 07-03-2008, 18:09

- OU SONT LES VISITEURS DE MON SITE ? par Nix's Blog le 07-03-2008, 15:07

- PowerShell : Quelques outils de développement adaptés par Blog Technique de Romelard Fabrice le 07-03-2008, 14:50

- [DevWeb] "FireFox est lent quand je developpe en local ?" par The diary of EBArtSoft le 07-03-2008, 14:47