2010-06-04 5 views
5

PrintCapabilities printCapabilites = SelectedPrinter.GetPrintCapabilities(); IEnumerable pagesizeList = printCapabilites.PageMediaSizeCapability;GetPrintCapabilities ne retournera pas toutes les tailles de page

Le code ci-dessus ne répertorie pas toutes les tailles de page prises en charge par le pilote d'imprimante et c'est mon problème. Par exemple, si vous utilisez le pilote d'imprimante Microsoft XPS, vous remarquerez qu'il manque des tailles de page à pagesizeList (ci-dessus). "Letter Small" est l'une des tailles de page manquantes (MS Word listera avec succès cette taille de page).

En tant que vérification rapide J'ai vidé les capacités de l'imprimante au format XML comme ci-dessous:

long gpCLen = _selectedPrinter.GetPrintCapabilitiesAsXml().Length; 
FileStream fs = File.OpenWrite(@"c:\test.txt"); 
MemoryStream ms = _selectedPrinter.GetPrintCapabilitiesAsXml(); 
byte[] b = new byte[gpCLen]; 
ms.Read(b, 0, (int)gpCLen); 
fs.Write(b, 0, (int)gpCLen); 
fs.Close(); 

Le nœud PageMediaSize dans le fichier xml produit a en effet toutes les tailles de page et les disparus.

pages affichées semblent avoir leur départ nom psk:

<psf:Option name="psk:ISOA4" constrained="psk:None"> 

mais les pages non affichées semblent avoir:

<psf:Option name="ns0000:LETTERSMALL" constrained="psk:None"> 

Undisplayed pages du pilote d'impression Epson sont similaires:

<psf:Option name="epns200:IndexCard5x8" constrained="psk:None"> 

Fondamentalement, une page dont le nom commence 'psk' affiche PageMediaSizeCapability, mais si c'est la fabrication personnalisé c'est-à-dire epns200, ns0000, il ne liste pas. Des idées pourquoi et comment résoudre ce problème s'il vous plaît? Les nœuds/Pages sont là mais PageMediaSizeCapability ne l'aime pas!

Merci à l'avance

EDIT:

Comme état MS 'Un objet PrintCapabilities est un outil facile à travailler avec la représentation d'un certain type de document XML appelé un document PrintCapabilities.' Mais le document contient plus d'informations que l'objet Full description

Répondre

3

vous devez enregistrer le nom de papier que vous avez lu dans PrintCapabilities xml, et l'utiliser pour créer un printTicket xml (PrintTicket a un constructeur qui accepte un flux xml), et Ensuite, utilisez le PrintTicket. Voici un exemple de XML PrintTicket (ns0000: User0000000257 est le nom de hte d'un format de papier personnalisé que j'ai créé):

<psf:PrintTicket xmlns:psf="http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      xmlns:psk="http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords" 
      xmlns:ns0000="http://schemas.microsoft.com/windows/printing/oemdriverpt/Samsung_CLP-310 Series/5.1.2600.2180/" version="1"> 
    <psf:Feature name="psk:PageMediaSize"> 
    <psf:Option name="ns0000:User0000000257"></psf:Option> 
    </psf:Feature> 
</psf:PrintTicket> 
+0

+1: cela fonctionne et devrait être accepté comme réponse. –

1

Même si c'était un fil plus, il a été utile en nous pointant dans la bonne direction nous avions besoin de lire et de mettre à jour les propriétés personnalisées.

Le code ci-dessous a été adapté à partir de ce fil: Impression XPS, Sélection de bacs et InputBinCapability (InputBin) = Problème: http://www.windows-tech.info/14/29c7cf575646cb39.php. La réponse de Jo0815 en bas contenait la plupart de ce que vous voyez ci-dessous, en particulier les expressions XPath qui nous indiquaient la bonne direction.

De même, mettez à jour PrintQueue.UserPrintTicket avec vos modifications, PAS le DefaultPrintTicket.

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Printing; 
using System.Text; 
using System.Windows; 
using System.Xml; 

// Adapted 
// From: XPS Printing, Tray selection and InputBinCapability (InputBin) = Problem 
// Link: http://www.windows-tech.info/14/29c7cf575646cb39.php - last answer at bottom by Jo0815 

namespace WpfApplication1 
{ 
    public static class WpfPrinterUtilities 
    { 
     #region GetPrintQueues 

     /// <summary> 
     /// Gets a dictionary of print queues where Key = print queue name 
     /// and Value = the print queue object. 
     /// </summary> 
     /// <param name="printQueueTypes">EnumeratedPrintQueueTypes params array of the types of print queues being requested.</param> 
     /// <returns>Dictionary of requested print queues where Key = print queue name and Value = the print queue object itself.</returns> 
     public static Dictionary<string, PrintQueue> GetPrintQueues(params EnumeratedPrintQueueTypes[] printQueueTypes) 
     { 
      var server = new PrintServer(); 
      return server.GetPrintQueues(printQueueTypes).ToDictionary(pq => pq.ShareName != null ? pq.ShareName : pq.Name); 
     } 

     #endregion 

     #region GetInputBins 

     /// <summary> 
     /// Reads print queue configuration xml to retrieve the current list of input bins. 
     /// </summary> 
     /// <param name="printQueue">The print queue to query.</param> 
     /// <returns></returns> 
     public static Dictionary<string, string> GetInputBins(PrintQueue printQueue) 
     { 
      Dictionary<string, string> inputBins = new Dictionary<string, string>(); 

      // Get the print queue PrintCapabilities. 
      XmlDocument xmlDoc = null; 
      using (MemoryStream stream = printQueue.GetPrintCapabilitiesAsXml()) 
      { 
       // Read the JobInputBins out of the PrintCapabilities. 
       xmlDoc = new XmlDocument(); 
       xmlDoc.Load(stream); 
      } 

      // Create NamespaceManager and add PrintSchemaFrameWork-Namespace (should be on DocumentElement of the PrintTicket). 
      // Prefix: psf NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" 
      XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable); 
      manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI); 

      // Select all job input bins. 
      XmlNodeList nodeList = xmlDoc.SelectNodes("//psf:Feature[@name='psk:JobInputBin']/psf:Option/psf:Property", manager); 

      // Load the Dictionary with the bin values and names. The names will be used to modify the print ticket if necessary. 
      foreach (XmlNode node in nodeList) 
      { 
       inputBins.Add(node.LastChild.InnerText, node.ParentNode.Attributes[0].Value); 
      } 

      return inputBins; 
     } 

     #endregion 

     #region ModifyPrintTicket 

     /// <summary> 
     /// Modifes a print ticket xml after updating a feature value. 
     /// 
     /// Sample usage: 
     /// Get Dictionary with Inputbins by calling the other method 
     /// and get "value" for the desired inputbin you'd like to use... 
     /// ... 
     /// desiredTray is then something like "NS0000:SurpriseOption7" for example. 
     /// defaultPrintTicket is the (Default)PrintTicket you want to modify from the PrintQueue for example 
     /// PrintTicket myPrintTicket = WpfPrinterUtils.ModifyPrintTicket(defaultPrintTicket, "psk:JobInputBin", desiredTray); 
     /// </summary> 
     /// <param name="ticket"></param> 
     /// <param name="featureName"></param> 
     /// <param name="newValue"></param> 
     /// <param name="printQueueName">Optional - If provided, a file is created with the print ticket xml. Useful for debugging.</param> 
     /// <param name="folder">Optional - If provided, the path for a file is created with the print ticket xml. Defaults to c:\. Useful for debugging.</param> 
     /// <param name="displayMessage">Optional - True to display a dialog with changes. Defaults to false. Useful for debugging.</param> 
     /// <returns></returns> 
     public static PrintTicket ModifyPrintTicket(PrintTicket ticket, string featureName, string newValue, string printQueueName = null, string folder = null, bool displayMessage = false) 
     { 
      if (ticket == null) 
      { 
       throw new ArgumentNullException("ticket"); 
      } 

      // Read Xml of the PrintTicket xml. 
      XmlDocument xmlDoc = new XmlDocument(); 
      xmlDoc.Load(ticket.GetXmlStream()); 

      // Create NamespaceManager and add PrintSchemaFrameWork-Namespace hinzufugen (should be on DocumentElement of the PrintTicket). 
      // Prefix: psf NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" 
      XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable); 
      manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI); 

      // Search node with desired feature we're looking for and set newValue for it 
      string xpath = string.Format("//psf:Feature[@name='{0}']/psf:Option", featureName); 
      XmlNode node = xmlDoc.SelectSingleNode(xpath, manager); 
      if (node != null) 
      { 
       if (node.Attributes["name"].Value != newValue) 
       { 
        if (displayMessage) 
        { 
         System.Windows.MessageBox.Show(string.Format("OldValue: {0}, NewValue: {1}", node.Attributes["name"].Value, newValue), "Input Bin"); 
        } 
        node.Attributes["name"].Value = newValue; 
       } 
      } 

      // Create a new PrintTicket out of the XML. 
      PrintTicket modifiedPrintTicket = null; 
      using (MemoryStream stream = new MemoryStream()) 
      { 
       xmlDoc.Save(stream); 
       stream.Position = 0; 
       modifiedPrintTicket = new PrintTicket(stream); 
      } 

      // For testing purpose save the print ticket to a file. 
      if (!string.IsNullOrWhiteSpace(printQueueName)) 
      { 
       if (string.IsNullOrWhiteSpace(folder)) 
       { 
        folder = "c:\\"; 
       } 
       // Colons are not valid in a file name. 
       newValue = newValue.Replace(':', ';'); 
       printQueueName = string.Format("{0} PrintTicket {1}.xml", Path.Combine(folder, printQueueName), newValue); 
       if (File.Exists(printQueueName)) 
       { 
        File.Delete(printQueueName); 
       } 
       if (!Directory.Exists(Path.GetDirectoryName(printQueueName))) 
       { 
        Directory.CreateDirectory(Path.GetDirectoryName(printQueueName)); 
       } 
       using (FileStream stream = new FileStream(printQueueName, FileMode.CreateNew, FileAccess.ReadWrite)) 
       { 
        modifiedPrintTicket.GetXmlStream().WriteTo(stream); 
       } 
      } 

      return modifiedPrintTicket; 
     } 

     #endregion 
    } 
} 
Questions connexes