[C#] Impression PDF

Impression PDF [C#] - C#/.NET managed - Programmation

Marsh Posté le 10-02-2016 à 09:48:40    

Bonjour les amis,  [:disturbed angel:2]  
 
Je cherche, via un code C#, à lancer l’impression d’un PDF via l’imprimante « Adobe PDF » tout en la paramétrant notamment avec un format de papier personnalisé.
Ceci dans le but d’automatiser la génération de PDF dans le logiciel Revit.
 
Je cherche depuis un moment des solutions pour :

  • Interagir avec l’imprimante adobe PDF.
  • Créer un format de papier personnalisé.


J’ai regardé aussi du côté des librairies C# pour générer mon PDF directement depuis le code sans passé par l’imprimante Adobe PDF mais je n’ai rien trouvé.
 
Si je suis pas assez clair hésitez pas a me le dire  :D


---------------
≡ Diablo III ≡ Steam ≡ DotaBuff ≡ Figurines ≡ Ach & Vds
Reply

Marsh Posté le 10-02-2016 à 09:48:40   

Reply

Marsh Posté le 10-02-2016 à 11:38:14    

Pas très clair pour moi désolé.
Tu veux générer un nouveau fichier .PDF à partir d'un *quelque chose* ? Si oui de quoi ?
Tu veux imprimer un PDF existant ?
C'est quoi Revit, comment ton code s'y intègre ?
C'est quoi "Adobe PDF", une imprimante listée parmi celles de la machine ? Si oui il y a en C# des objets pour déclencher une impression : PrintDocument, PrintDialog et cie.
Je suppose que tu dois pouvoir par programmation chercher et préselectionner une imprimante par son nom et donner quelques consignes sur ce qui doit être généré, c'est peut être ta solution.


Message édité par TotalRecall le 10-02-2016 à 11:38:49

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 10-02-2016 à 12:37:31    

Oui je me doutais un peu que j'étais pas des plus claire désolé  :sarcastic:  
 
Tu veux générer un nouveau fichier .PDF à partir d'un *quelque chose* ? Si oui de quoi ?
Je veux générer un PDF a partir d'une feuille d'un projet Revit. Revit est un logiciel de BIM (Building Information Modeling) destiné aux architectes et servant à modéliser des bâtiments en trois dimensions. Les feuilles sont comme des découpe, calques ou vue et peuvent être "exporter" en PDF en lançant une impression de cette dernière et en sélectionnant l'imprimante qui s'appelle Adobe PDF.
 
Tu veux imprimer un PDF existant ?  
Non je veux générer le PDF.
 
C'est quoi Revit, comment ton code s'y intègre ?  
Revit permet l'ajout d'Addin (dll). Je créer donc sous Visual Studio un projet de bibliothèque de classe.
 
C'est quoi "Adobe PDF", une imprimante listée parmi celles de la machine ?  
Oui l'imprimante Adobe PDF apparaît dans la liste parmi les autres imprimantes car Adobe Acrobate est installé sur la machine.
 
Si oui il y a en C# des objets pour déclencher une impression : PrintDocument, PrintDialog et cie. Je suppose que tu dois pouvoir par programmation chercher et présélectionner une imprimante par son nom et donner quelques consignes sur ce qui doit être généré, c'est peut être ta solution.  
Oui j'ai vu cela, c'est d’ailleurs la piste que je creuse. Mais je ne parviens pas a créer de format personnalisé.
 
Merci de ta réponse et de ton aide  :jap:  


---------------
≡ Diablo III ≡ Steam ≡ DotaBuff ≡ Figurines ≡ Ach & Vds
Reply

Marsh Posté le 10-02-2016 à 14:14:57    

Ok merci, c'est beaucoup plus clair avec ces précisions. Tu me confirmes que j'avais bien compris l'objet de ta demande et tu combles les quelques manques.
 
Donc on peut passer à la partie implémentation maintenant la question clairement définie.
 
Afin de poursuivre :
Qu'est ce qui te pose souci, l'exploitation des données sur le document fournie par les API du modèle d'addIn de Revit, ou bien l'implémentation en C# de l'impression ?
Dans le premier cas je doute que tu trouves facilement quelqu'un d'autre qui connaisse ce logiciel et son système d'extensibilité, mais dans le deuxième cas on devrait pouvoir t'aider...
Qu'as tu déjà déjà fait ?
 
Note que je ne suis pas un spécialiste de l'impression en .Net donc je ne pourrai que te donner des généralités comme ci-dessus !


---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 10-02-2016 à 17:17:01    

TotalRecall a écrit :

[...]
Qu'est ce qui te pose souci, l'exploitation des données sur le document fournie par les API du modèle d'addIn de Revit, ou bien l'implémentation en C# de l'impression ?
Dans le premier cas je doute que tu trouves facilement quelqu'un d'autre qui connaisse ce logiciel et son système d'extensibilité, mais dans le deuxième cas on devrait pouvoir t'aider...
Qu'as tu déjà déjà fait ?[...]


Plus l'implémentation en C# de l'impression.  :D  
Avec PrintDocument, PrintSetting j'ai déjà réussi a :

  • Afficher les imprimante et en sélectionner une.
  • Afficher les différents format de papier (PaperSize)


J'ai tenté de créer un nouveau format de papier, mais je ne la retrouve pas par la suite dans les options de l'imprimante. Ce qui me porte à croire que le nouveau format de papier n'existe qu'avec l'objet et qu'il faut ensuite l'appliquer au moment d'imprimer.

Code :
  1. PaperSize test = new PaperSize();
  2. Console.WriteLine("Saisir le nom du nouveau format de papier" );
  3. test.PaperName = Console.ReadLine();
  4. test.RawKind = PaperKind.Custom.GetHashCode();
  5. Console.WriteLine("Saisir la hauteur du papier" );
  6. test.Height = Convert.ToInt32(Console.ReadLine());
  7. Console.WriteLine("Saisir la largeur du papier" );
  8. test.Width = Convert.ToInt32(Console.ReadLine());


 
Mon problème est vraiment de parvenir a créer un format de papier personnalisé pour ensuite le retrouver dans les paramètres d'impression généraux.
Je ne peut pas interagir directement avec les paramètres d'impression de l'imprimante Adobe PDF mais Revit permet sélectionner des paramètres d'impression dont la taille de papier mais il faut que je parvienne à la créer au préalable.
 
Pour être un peut plus claire je vais expliquer la manip' manuelle que j'essaie de rendre automatique via mon code.
 
http://reho.st/medium/self/7359189419cb01aba773ad78ee0c540ed31a214f.png
 
Dans Revit une fois sur la feuille du projet que l'on souhaite imprimer en PDF. On lance l'impression comme dans n'importe quel logiciel. La première fenêtre de gauche apparaît, on sélectionne notre imprimante, ici Adobe PDF.
Puis on clic sur "propriétés" qui nous donne les propriétés propre a l'imprimante, ici la fenêtre de droite pour Adobe PDF. Habituellement on clic sur ajouter un format papier, on rentre nos dimensions et c'est partis.
d'après mes recherche il semblerai que l'on ne puisse pas interagir avec le code sur cette fenêtre.
 
Pour contourner le problème je cherche à entrer le format dans la fenêtre de droite ci-dessous. Je peut interagir dans le code puisque ce sont les paramètres d'impression de Revit.
Mais comme on peut le voir la création de format personnalisé n'est pas possible, il faut donc qu'il y soit avant.
 
http://reho.st/medium/self/daca815ff3b5afb13b18bdb3f0890fe6e7c168a9.png
 
Voilà encore merci de ton aide.  [:bakk21]  


---------------
≡ Diablo III ≡ Steam ≡ DotaBuff ≡ Figurines ≡ Ach & Vds
Reply

Marsh Posté le 11-02-2016 à 09:52:39    

Ah ouais [:gratgrat]
Là comme ça je ne sais pas [:vizera]  
J'ai très peu fait joujou avec l'impression et c'est déjà assez pointu.
N'hésite pas à poster un lien vers ton topic dans le topic en lien (:o ) dans ma signature, pour amener du monde ici...


---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 11-02-2016 à 10:43:47    

C'est sur que la on dépasse un peu la simple impression.
Merci du conseil je vais faire un p'tit message dans ton topic voir si une âme perdu a une idée.  :o

 

Sinon de mon coté, je suis parti vers une nouvelle piste en essayant "d'attaquer" par le code le serveur d'impression
http://reho.st/medium/self/325358150cdbd9e91be6f4b4ec36de5623cd4a10.png
J'ai déjà réussi a récupérée les infos des onglet ports et pilotes, je peu donc sélectionner l'imprimante que je souhaite.
Dans l'onglet formulaire on peu créer un nouveau format de papier (Géniale c'est ce qu'il me faut) mais je ne parviens pas à atteindre cette partie [:bakk39]


Message édité par moriquendi le 11-02-2016 à 11:00:10

---------------
≡ Diablo III ≡ Steam ≡ DotaBuff ≡ Figurines ≡ Ach & Vds
Reply

Marsh Posté le 11-02-2016 à 11:31:57    

Petite question :
tu as déjà créé ta "PaperSize", maintenant  si tu as une instance de PrintDocument, est-ce que tu as essayé quelque chose comme ça (très simplifié) ?
 

Code :
  1. var test = new PaperSize();
  2. var printDoc = new PrintDocument();
  3. printDoc.PrinterSettings.DefaultPageSettings.PaperSize = test;


 
T'as peut-être déjà regardé cette page de la msdn ?
C'est pas tout à fait ce que tu demandes, mais il y a pas mal d'infos qui devraient te servir...
 
Edith
me dit que tu pourrais aussi regarder par ou


Message édité par deliriumtremens le 11-02-2016 à 11:37:15
Reply

Marsh Posté le 11-02-2016 à 15:27:00    

Bonjour Deliriumtremens  :hello:

 

Merci pour ton coup de main.

 

En effet j'avais déjà exploré la piste du PaperSize et de PrintDocument.
Le problème est que pour l'impression PrintDocument ne prend qu'un chemin de fichier ou un flux (Stream) en entrée.
Or je lance l'impression depuis Revit et une feuille du projet qui n'est n'y un objet n'y un flux.
J'utilise donc des fonctions propre à Revit pour le lancement de l'impression.
Ces dernières prenant des éléments Revit en entrée, mais ces fonctions d'impression ne permette que la sélection d'un format de papier pas d'en créer un à la volé.
D'où mon désir de créer un format de papier "en avance" pour que je puisse le sélectionner par la suite.

 

J'ai finalement trouvé la solution à mon problème ce midi  [:viscere musc] grâce à ces liens (en autre) ici et ici

 

Encore merci pour votre aide. :jap:

 

Voici le code si jamais une âme perdu est bloquée par le même problème  :D  :

Code :
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Security;
  4. using System.Text;
  5. namespace Gestion_Imprimante_Windows
  6. {
  7.     class CreationFormPapier
  8.     {
  9.         #region winspool.Drv
  10.         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  11.         internal struct structPrinterDefaults
  12.         {
  13.             [MarshalAs(UnmanagedType.LPTStr)]
  14.             public String pDatatype;
  15.             public IntPtr pDevMode;
  16.             [MarshalAs(UnmanagedType.I4)]
  17.             public int DesiredAccess;
  18.         };
  19.         [DllImport("winspool.Drv", EntryPoint = "OpenPrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  20.         internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPTStr)] string printerName, out IntPtr phPrinter, ref structPrinterDefaults pd);
  21.         [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  22.         internal static extern bool ClosePrinter(IntPtr phPrinter);
  23.         [DllImport("winspool.Drv", EntryPoint = "DeleteForm", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  24.         internal static extern bool DeleteForm( IntPtr phPrinter, [MarshalAs(UnmanagedType.LPTStr)] string pName);
  25.         [DllImport("winspool.Drv", EntryPoint = "AddFormW", SetLastError = true,  CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  26.         internal static extern bool AddForm( IntPtr phPrinter, [MarshalAs(UnmanagedType.I4)] int level, ref FormInfo1 form);
  27.         [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
  28.         internal static extern Int32 GetLastError();
  29.         [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
  30.         internal struct FormInfo1
  31.         {
  32.             [FieldOffset(0), MarshalAs(UnmanagedType.I4)]
  33.             public uint Flags;
  34.             [FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)]
  35.             public String pName;
  36.             [FieldOffset(8)]
  37.             public structSize Size;
  38.             [FieldOffset(16)]
  39.             public structRect ImageableArea;
  40.         };
  41.         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  42.         internal struct structSize
  43.         {
  44.             public Int32 width;
  45.             public Int32 height;
  46.         }
  47.         [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  48.         internal struct structRect
  49.         {
  50.             public Int32 left;
  51.             public Int32 top;
  52.             public Int32 right;
  53.             public Int32 bottom;
  54.         }
  55.         #endregion
  56.         public static void AddCustomPaperSize(string printerName, string paperName, float widthMm, float heightMm)
  57.         {
  58.             if (PlatformID.Win32NT == Environment.OSVersion.Platform)
  59.             {
  60.                 // The code to add a custom paper size is different for Windows NT then it is
  61.                 // for previous versions of windows
  62.                 const int PRINTER_ACCESS_USE = 0x00000008;
  63.                 const int PRINTER_ACCESS_ADMINISTER = 0x00000004;
  64.                 structPrinterDefaults defaults = new structPrinterDefaults();
  65.                 defaults.pDatatype = null;
  66.                 defaults.pDevMode = IntPtr.Zero;
  67.                 defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
  68.                 IntPtr hPrinter = IntPtr.Zero;
  69.                 // Open the printer.
  70.                 if (OpenPrinter(printerName, out hPrinter, ref defaults))
  71.                 {
  72.                     try
  73.                     {
  74.                         // delete the form incase it already exists
  75.                         DeleteForm(hPrinter, paperName);
  76.                         // create and initialize the FORM_INFO_1 structure
  77.                         FormInfo1 formInfo = new FormInfo1();
  78.                         formInfo.Flags = 0;
  79.                         formInfo.pName = paperName;
  80.                         // all sizes in 1000ths of millimeters
  81.                         formInfo.Size.width = (int)(widthMm * 1000.0);
  82.                         formInfo.Size.height = (int)(heightMm * 1000.0);
  83.                         // gestion de marges zones d'impression
  84.                         formInfo.ImageableArea.left = 0;
  85.                         formInfo.ImageableArea.right = formInfo.Size.width;
  86.                         formInfo.ImageableArea.top = 0;
  87.                         formInfo.ImageableArea.bottom = formInfo.Size.height;
  88.                         if (!AddForm(hPrinter, 1, ref formInfo))
  89.                         {
  90.                             StringBuilder strBuilder = new StringBuilder();
  91.                             strBuilder.AppendFormat("Failed to add the custom paper size {0} to the printer {1}, System error number: {2}",
  92.                                 paperName, printerName, GetLastError());
  93.                             throw new ApplicationException(strBuilder.ToString());
  94.                         }
  95.                     }
  96.                     finally
  97.                     {
  98.                         ClosePrinter(hPrinter);
  99.                     }
  100.                 }
  101.                 else
  102.                 {
  103.                     StringBuilder strBuilder = new StringBuilder();
  104.                     strBuilder.AppendFormat("Failed to open the {0} printer, System error number: {1}", printerName, GetLastError());
  105.                     throw new ApplicationException(strBuilder.ToString());
  106.                 }
  107.             }
  108.             else
  109.             {
  110.                 StringBuilder strBuilder = new StringBuilder();
  111.                 strBuilder.AppendFormat(" windows version prior to windows 2000 error" );
  112.                 throw new ApplicationException(strBuilder.ToString());
  113.             }
  114.         }
  115.     }
  116. }


Message édité par moriquendi le 11-02-2016 à 15:28:10

---------------
≡ Diablo III ≡ Steam ≡ DotaBuff ≡ Figurines ≡ Ach & Vds
Reply

Marsh Posté le 11-02-2016 à 15:30:59    

Oh ce beau bordel à base d'APIs Windows et de tests cracra :love:
Reste à voir si ça fonctionne aussi bien sur les postes clients avec des OS verrouillés et des comptes sans privilèges [:rhetorie du chaos]


---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 11-02-2016 à 15:30:59   

Reply

Marsh Posté le 11-02-2016 à 15:40:46    

Pour l'instant ça fonctionne, casse pas tous mes espoirs juste 2h après :o
Par contre, je suis ouvert à toutes propositions d'optimisation !
Si tu as des idées je prend  :jap:


Message édité par moriquendi le 11-02-2016 à 15:41:13

---------------
≡ Diablo III ≡ Steam ≡ DotaBuff ≡ Figurines ≡ Ach & Vds
Reply

Marsh Posté le 11-02-2016 à 15:42:27    

Ah non du tout, moi mon truc c'est la critique stérile :o


---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 11-02-2016 à 15:44:00    

Ah si quand même, j'ai envie de dire qu'utiliser un StringBuilder pour écrire une seule ligne c'est un peu dommage [:pseudoman]  
Mais ça ne fait pas avancer le reste  [:bluelightneon]


---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 11-02-2016 à 15:53:38    

TotalRecall a écrit :

Ah non du tout, moi mon truc c'est la critique stérile :o


C'est constructif du coup  :o  

TotalRecall a écrit :

Ah si quand même, j'ai envie de dire qu'utiliser un StringBuilder pour écrire une seule ligne c'est un peu dommage [:pseudoman]  
Mais ça ne fait pas avancer le reste  [:bluelightneon]


Le StringBuilder vient du code que j'ai repris sur le premier lien. :ange:  
Il va dégager vite fait, j'ai une classe log dans mon projet final.
En plus c'est un la première fois que je vois ça, habituellement j'utilise plus des MessageBox pour mes test perso. :whistle:


---------------
≡ Diablo III ≡ Steam ≡ DotaBuff ≡ Figurines ≡ Ach & Vds
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed