Advertisement
Guest User

Untitled

a guest
Sep 30th, 2009
5,710
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 26.69 KB | None | 0 0
  1. /// <summary>
  2. /// Replacement class for System.Windows.PrintDialog
  3. /// </summary>
  4. public class PrintDialog
  5. {
  6.     #region Fields
  7.  
  8.     double mPrintableHeight;
  9.     double mPrintableWidth;
  10.  
  11.     bool mHeightUpdated = false;
  12.     bool mWidthUpdated = false;
  13.  
  14.     PrintQueue mPrintQueue = null;
  15.     PrintTicket mPrintTicket = null;
  16.  
  17.     PageRangeSelection mPageRangeSelection = PageRangeSelection.AllPages;
  18.     PageRange mPageRange;
  19.    
  20.     #endregion
  21.  
  22.     #region Private Methods
  23.     /// <summary>
  24.     /// Ensure Queue and Ticket prepared
  25.     /// </summary>
  26.     private void VerifyPrintSettings()
  27.     {
  28.         if (mPrintQueue == null)
  29.             mPrintQueue = DefaultPrintQueue();
  30.  
  31.         if (mPrintTicket == null)
  32.             mPrintTicket = DefaultPrintTicket();
  33.     }
  34.  
  35.     /// <summary>
  36.     /// PrintQueue
  37.     /// </summary>
  38.     /// <returns></returns>
  39.     private PrintQueue DefaultPrintQueue()
  40.     {
  41.         new PrintingPermission(PrintingPermissionLevel.DefaultPrinting).Assert();
  42.         PrintQueue queue = null;
  43.  
  44.         try
  45.         {
  46.             queue = new LocalPrintServer().DefaultPrintQueue;
  47.         }
  48.         catch (PrintSystemException)
  49.         {
  50.             queue = null;
  51.         }
  52.         finally
  53.         {
  54.             CodeAccessPermission.RevertAssert();
  55.         }
  56.  
  57.         return queue;
  58.     }
  59.  
  60.     /// <summary>
  61.     /// PrintTicket
  62.     /// </summary>
  63.     /// <param name="printQueue"></param>
  64.     /// <returns></returns>
  65.     private PrintTicket DefaultPrintTicket()
  66.     {
  67.         new PrintingPermission(PrintingPermissionLevel.DefaultPrinting).Assert();
  68.         PrintTicket ticket = null;
  69.  
  70.         try
  71.         {
  72.             if (mPrintQueue != null)
  73.             {
  74.                 ticket = mPrintQueue.UserPrintTicket;
  75.                 if (ticket == null)
  76.                     ticket = mPrintQueue.DefaultPrintTicket;
  77.             }
  78.         }
  79.         catch (PrintSystemException)
  80.         {
  81.             ticket = null;
  82.         }
  83.         finally
  84.         {
  85.             CodeAccessPermission.RevertAssert();
  86.         }
  87.  
  88.         if (ticket == null)
  89.             ticket = new PrintTicket();
  90.  
  91.         return ticket;
  92.     }
  93.  
  94.     /// <summary>
  95.     /// Set Print Area
  96.     /// </summary>
  97.     private void UpdateArea()
  98.     {
  99.         VerifyPrintSettings();
  100.  
  101.         PrintCapabilities caps = null;
  102.  
  103.         if (mPrintQueue != null)
  104.             caps = mPrintQueue.GetPrintCapabilities(mPrintTicket);
  105.  
  106.         if (((caps != null) && caps.OrientedPageMediaWidth.HasValue) && caps.OrientedPageMediaHeight.HasValue)
  107.         {
  108.             mPrintableWidth = caps.OrientedPageMediaWidth.Value;
  109.             mPrintableHeight = caps.OrientedPageMediaHeight.Value;
  110.         }
  111.         else
  112.         {
  113.             mPrintableWidth = 816.0;
  114.             mPrintableHeight = 1056.0;
  115.  
  116.             if (((mPrintTicket.PageMediaSize != null) && mPrintTicket.PageMediaSize.Width.HasValue) && mPrintTicket.PageMediaSize.Height.HasValue)
  117.             {
  118.                 mPrintableWidth = mPrintTicket.PageMediaSize.Width.Value;
  119.                 mPrintableHeight = mPrintTicket.PageMediaSize.Height.Value;
  120.             }
  121.  
  122.             if (mPrintTicket.PageOrientation.HasValue)
  123.             {
  124.                 if(mPrintTicket.PageOrientation.Value == PageOrientation.Landscape || mPrintTicket.PageOrientation.Value == PageOrientation.ReverseLandscape)
  125.                 {
  126.                     double swap = mPrintableWidth;
  127.                     mPrintableWidth = mPrintableHeight;
  128.                     mPrintableHeight = swap;
  129.                 }
  130.             }
  131.         }
  132.     }
  133.  
  134.     #endregion
  135.  
  136.     #region Public Methods
  137.  
  138.     /// <summary>
  139.     /// Actually print an Xps Document with previously setup params
  140.     /// </summary>
  141.     /// <param name="paginator">Document to print</param>
  142.     /// <param name="description">Description</param>
  143.     public void PrintDocument(DocumentPaginator paginator, string description)
  144.     {
  145.         if (paginator == null)
  146.             throw new ArgumentNullException("paginator", "No DocumentPaginator to print");
  147.  
  148.         VerifyPrintSettings();
  149.  
  150.         //Handle XPS ourself, as their document writer hates our thread
  151.         if (mPrintQueue.FullName.Contains("XPS"))
  152.         {
  153.             System.Windows.Forms.SaveFileDialog sfd = new System.Windows.Forms.SaveFileDialog();
  154.             sfd.Filter = "Xps Document (*.xps) | *.xps";
  155.  
  156.             if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  157.             {
  158.                 XpsDocument document = new XpsDocument(sfd.FileName, System.IO.FileAccess.Write);
  159.                 XpsPackagingPolicy packagePolicy = new XpsPackagingPolicy(document);
  160.                 XpsSerializationManager serializationMgr = new XpsSerializationManager(packagePolicy, false);
  161.                 serializationMgr.SaveAsXaml(paginator);
  162.  
  163.                 document.Close();
  164.             }
  165.  
  166.             return;
  167.         }
  168.  
  169.         XpsDocumentWriter writer = null;
  170.         new PrintingPermission(PrintingPermissionLevel.DefaultPrinting).Assert();
  171.  
  172.         try
  173.         {
  174.             mPrintQueue.CurrentJobSettings.Description = description;
  175.             writer = PrintQueue.CreateXpsDocumentWriter(mPrintQueue);
  176.  
  177.             TicketEventHandler handler = new TicketEventHandler(mPrintTicket);
  178.             writer.WritingPrintTicketRequired += new WritingPrintTicketRequiredEventHandler(handler.SetPrintTicket);
  179.         }
  180.         finally
  181.         {
  182.             CodeAccessPermission.RevertAssert();
  183.         }
  184.  
  185.         writer.Write(paginator);
  186.  
  187.         //Reset
  188.         mPrintableWidth = 0.0;
  189.         mPrintableHeight = 0.0;
  190.         mWidthUpdated = false;
  191.         mHeightUpdated = false;
  192.     }
  193.  
  194.     /// <summary>
  195.     /// Show Dialog to allow user to adjust printer/settings
  196.     /// </summary>
  197.     /// <param name="window">Window owner</param>
  198.     /// <returns>True is user was ready to print</returns>
  199.     public bool ShowDialog(Window window)
  200.     {
  201.         NativePrintDialog dlg = new NativePrintDialog()
  202.             {
  203.                 PrintTicket = mPrintTicket,
  204.                 PrintQueue = mPrintQueue,
  205.                 MinPage = 1,
  206.                 MaxPage = 200,
  207.                 PageRangeEnabled = false,
  208.                 PageRange = new PageRange(Math.Max(1, mPageRange.PageFrom), Math.Min(200, mPageRange.PageTo)),
  209.                 PageRangeSelection = mPageRangeSelection
  210.             };
  211.  
  212.         uint result = dlg.ShowDialog(window);
  213.         if(result == 1 || result == 2)
  214.         {
  215.             mPrintQueue  = dlg.PrintQueue;
  216.             mPrintTicket = dlg.PrintTicket;
  217.             mPageRange   = dlg.PageRange;
  218.             mPageRangeSelection = dlg.PageRangeSelection;
  219.         }
  220.  
  221.         return (result == 1);
  222.     }
  223.  
  224.     #endregion
  225.  
  226.     #region Properties
  227.  
  228.     public PageRange PageRange
  229.     {
  230.         get { return mPageRange; }
  231.         set
  232.         {
  233.             if (value.PageTo <= 0 || value.PageFrom <= 0)
  234.                 throw new ArgumentException("PageRange", "PageRange is not valid.");
  235.  
  236.             mPageRange = value;
  237.  
  238.             //Switch around if needed
  239.             if (mPageRange.PageFrom > mPageRange.PageTo)
  240.             {
  241.                 int swap = mPageRange.PageFrom;
  242.                 mPageRange.PageFrom = mPageRange.PageTo;
  243.                 mPageRange.PageTo = swap;
  244.             }
  245.         }
  246.     }
  247.  
  248.     public PageRangeSelection PageRangeSelection
  249.     {
  250.         get { return mPageRangeSelection; }
  251.         set { mPageRangeSelection = value; }
  252.     }
  253.  
  254.     public double PrintableAreaHeight
  255.     {
  256.         get
  257.         {
  258.             if ((!mWidthUpdated && !mHeightUpdated) || (!mWidthUpdated && mHeightUpdated))
  259.             {
  260.                 mWidthUpdated = false;
  261.                 mHeightUpdated = true;
  262.                 UpdateArea();
  263.             }
  264.  
  265.             return mPrintableHeight;
  266.         }
  267.     }
  268.  
  269.     public double PrintableAreaWidth
  270.     {
  271.         get
  272.         {
  273.             if ((!mWidthUpdated && !mHeightUpdated) || (mWidthUpdated && !mHeightUpdated))
  274.             {
  275.                 mWidthUpdated = true;
  276.                 mHeightUpdated = false;
  277.                 UpdateArea();
  278.             }
  279.  
  280.             return mPrintableWidth;
  281.         }
  282.     }
  283.  
  284.     public PrintQueue PrintQueue
  285.     {
  286.         get
  287.         {
  288.             VerifyPrintSettings();
  289.             return mPrintQueue;
  290.         }
  291.         set { mPrintQueue = value; }
  292.     }
  293.  
  294.     public PrintTicket PrintTicket
  295.     {
  296.         get
  297.         {
  298.             VerifyPrintSettings();
  299.             return mPrintTicket;
  300.         }
  301.         set { mPrintTicket = value; }
  302.     }
  303.  
  304.     #endregion
  305.  
  306.     #region Internal
  307.     class TicketEventHandler
  308.     {
  309.         private PrintTicket mPrintTicket;
  310.  
  311.         public TicketEventHandler(PrintTicket printTicket)
  312.         {
  313.             mPrintTicket = printTicket;
  314.         }
  315.  
  316.         public void SetPrintTicket(object sender, WritingPrintTicketRequiredEventArgs args)
  317.         {
  318.             if (args.CurrentPrintTicketLevel == PrintTicketLevel.FixedDocumentSequencePrintTicket)
  319.                 args.CurrentPrintTicket = mPrintTicket;
  320.         }
  321.     }
  322.     #endregion
  323. }
  324.  
  325. /// <summary>
  326. /// Native Printing class wrapper. Calls Window's PrinatDlgEx
  327. /// </summary>
  328. internal class NativePrintDialog
  329. {
  330.     #region Fields
  331.     private PrintQueue mPrintQueue = null;
  332.     private PrintTicket mPrintTicket = null;
  333.     private uint mMaxPage = 0x270f;
  334.     private uint mMinPage = 1;
  335.     private PageRange mPageRange;
  336.     private bool mPageRangeEnabled;
  337.     private PageRangeSelection mPageRangeSelection = PageRangeSelection.AllPages;
  338.     #endregion
  339.  
  340.     #region Public Methods
  341.     /// <summary>
  342.     /// Show Dialog
  343.     /// </summary>
  344.     /// <param name="window"></param>
  345.     /// <returns></returns>
  346.     internal uint ShowDialog(Window window)
  347.     {
  348.         WindowInteropHelper helper = new WindowInteropHelper(window);
  349.         using (PrintDlgEx dlg = new PrintDlgEx(helper.Handle, this))
  350.         {
  351.             return dlg.ShowPrintDlgEx();
  352.         }
  353.     }
  354.  
  355.     #endregion
  356.  
  357.     #region Properties
  358.     internal PrintQueue PrintQueue
  359.     {
  360.         get { return mPrintQueue; }
  361.         set { mPrintQueue = value; }
  362.     }
  363.  
  364.     internal PrintTicket PrintTicket
  365.     {
  366.         get { return mPrintTicket; }
  367.         set { mPrintTicket = value; }
  368.     }
  369.  
  370.     internal uint MinPage
  371.     {
  372.         get { return mMinPage; }
  373.         set { mMinPage = value; }
  374.     }
  375.  
  376.     internal uint MaxPage
  377.     {
  378.         get { return mMaxPage; }
  379.         set { mMaxPage = value; }
  380.     }
  381.  
  382.     internal bool PageRangeEnabled
  383.     {
  384.         get { return mPageRangeEnabled; }
  385.         set { mPageRangeEnabled = value; }
  386.     }
  387.  
  388.     internal PageRange PageRange
  389.     {
  390.         get { return mPageRange; }
  391.         set { mPageRange = value; }
  392.     }
  393.  
  394.     internal PageRangeSelection PageRangeSelection
  395.     {
  396.         get { return mPageRangeSelection; }
  397.         set { mPageRangeSelection = value; }
  398.     }
  399.  
  400.     #endregion
  401.  
  402.     #region Native Class Wrapper
  403.     class PrintDlgEx : IDisposable
  404.     {
  405.         #region Fields
  406.         private IntPtr mPrintDlgExHnd;
  407.         private NativePrintDialog mDialogOwner;
  408.         private IntPtr mWinHandle;
  409.         #endregion
  410.  
  411.         #region Public/Internal Methods
  412.         /// <summary>
  413.         /// Constructor
  414.         /// </summary>
  415.         /// <param name="owner">The Owner Handle we will attach to</param>
  416.         /// <param name="dialog"></param>
  417.         internal PrintDlgEx(IntPtr owner, NativePrintDialog dialog)
  418.         {
  419.             mWinHandle = owner;
  420.             mDialogOwner = dialog;
  421.             mPrintDlgExHnd = AllocatePrintDlgExStruct();
  422.         }
  423.  
  424.         /// <summary>
  425.         /// Show dialg and return result
  426.         /// </summary>
  427.         /// <returns></returns>
  428.         internal uint ShowPrintDlgEx()
  429.         {
  430.             if (NativeMethods.PrintDlgEx(mPrintDlgExHnd) == 0)
  431.                 return GetResult();
  432.             else
  433.                 return 0;
  434.         }
  435.  
  436.         /// <summary>
  437.         /// Clean up
  438.         /// </summary>
  439.         ~PrintDlgEx()
  440.         {
  441.             //Make sure object is Disposed
  442.             Dispose(true);
  443.         }
  444.  
  445.         #endregion
  446.  
  447.         #region Private Methods
  448.         /// <summary>
  449.         /// Helper method to determine CPU mode
  450.         /// </summary>
  451.         /// <returns></returns>
  452.         bool Is64Bits()
  453.         {
  454.             return (Marshal.SizeOf(IntPtr.Zero) == 8);
  455.         }
  456.  
  457.         /// <summary>
  458.         /// Allocate memory associated with PRINTDLGEX32 or PRINTDLGEX64 structures
  459.         /// </summary>
  460.         IntPtr AllocatePrintDlgExStruct()
  461.         {
  462.             NativeMethods.PRINTPAGERANGE pageRange;
  463.             IntPtr ptr          = IntPtr.Zero;
  464.             pageRange.nToPage   = (uint)mDialogOwner.PageRange.PageTo;
  465.             pageRange.nFromPage = (uint)mDialogOwner.PageRange.PageFrom;
  466.  
  467.             try
  468.             {
  469.                 //Handle 32 bit case first
  470.                 if (!Is64Bits())
  471.                 {
  472.                     NativeMethods.PRINTDLGEX32 pDlg = new NativeMethods.PRINTDLGEX32();
  473.                     pDlg.hwndOwner = mWinHandle;
  474.                     pDlg.nMinPage  = mDialogOwner.MinPage;
  475.                     pDlg.nMaxPage  = mDialogOwner.MaxPage;
  476.                     pDlg.Flags     = 0x9c0004;
  477.  
  478.                     if (mDialogOwner.PageRangeEnabled)
  479.                     {
  480.                         pDlg.lpPageRanges = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.PRINTPAGERANGE)));
  481.                         pDlg.nMaxPageRanges = 1;
  482.  
  483.                         if (mDialogOwner.PageRangeSelection == PageRangeSelection.UserPages)
  484.                         {
  485.                             pDlg.nPageRanges = 1;
  486.                             Marshal.StructureToPtr(pageRange, pDlg.lpPageRanges, false);
  487.                             pDlg.Flags |= 2;
  488.                         }
  489.                         else
  490.                         {
  491.                             pDlg.nPageRanges = 0;
  492.                         }
  493.                     }
  494.                     else
  495.                     {
  496.                         pDlg.lpPageRanges = IntPtr.Zero;
  497.                         pDlg.nMaxPageRanges = 0;
  498.                         pDlg.Flags |= 8;
  499.                     }
  500.  
  501.                     if (mDialogOwner.PrintQueue != null)
  502.                     {
  503.                         pDlg.hDevNames = InitializeDevNames(mDialogOwner.PrintQueue.FullName);
  504.                         if (mDialogOwner.PrintTicket != null)
  505.                             pDlg.hDevMode = InitializeDevMode(mDialogOwner.PrintQueue.FullName, mDialogOwner.PrintTicket);
  506.                     }
  507.  
  508.                     ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.PRINTDLGEX32)));
  509.                     Marshal.StructureToPtr(pDlg, ptr, false);
  510.                     return ptr;
  511.                 }
  512.  
  513.                 //Go with 64 bit structure
  514.                 NativeMethods.PRINTDLGEX64 pDlg64 = new NativeMethods.PRINTDLGEX64();
  515.                 pDlg64.hwndOwner = mWinHandle;
  516.                 pDlg64.nMinPage  = mDialogOwner.MinPage;
  517.                 pDlg64.nMaxPage  = mDialogOwner.MaxPage;
  518.                 pDlg64.Flags     = 0x9c0004;
  519.  
  520.                 if (mDialogOwner.PageRangeEnabled)
  521.                 {
  522.                     pDlg64.lpPageRanges   = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.PRINTPAGERANGE)));
  523.                     pDlg64.nMaxPageRanges = 1;
  524.  
  525.                     if (mDialogOwner.PageRangeSelection == PageRangeSelection.UserPages)
  526.                     {
  527.                         pDlg64.nPageRanges = 1;
  528.                         Marshal.StructureToPtr(pageRange, pDlg64.lpPageRanges, false);
  529.                         pDlg64.Flags |= 2;
  530.                     }
  531.                     else
  532.                     {
  533.                         pDlg64.nPageRanges = 0;
  534.                     }
  535.                 }
  536.                 else
  537.                 {
  538.                     pDlg64.lpPageRanges   = IntPtr.Zero;
  539.                     pDlg64.nMaxPageRanges = 0;
  540.                     pDlg64.Flags         |= 8;
  541.                 }
  542.  
  543.                 if (mDialogOwner.PrintQueue != null)
  544.                 {
  545.                     pDlg64.hDevNames = InitializeDevNames(mDialogOwner.PrintQueue.FullName);
  546.  
  547.                     if (mDialogOwner.PrintTicket != null)
  548.                         pDlg64.hDevMode = InitializeDevMode(mDialogOwner.PrintQueue.FullName, mDialogOwner.PrintTicket);
  549.                 }
  550.  
  551.                 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NativeMethods.PRINTDLGEX64)));
  552.                 Marshal.StructureToPtr(pDlg64, ptr, false);
  553.                 return ptr;
  554.             }
  555.             catch (Exception)
  556.             {   //Free buffer on error
  557.                 DeallocatePrintDlgExStruct(ptr);
  558.                 throw;
  559.             }
  560.         }
  561.  
  562.         /// <summary>
  563.         /// Frees memory associated with PRINTDLGEX32 or PRINTDLGEX64 structures
  564.         /// </summary>
  565.         /// <param name="ptr"></param>
  566.         void DeallocatePrintDlgExStruct(IntPtr ptr)
  567.         {
  568.             if (ptr != IntPtr.Zero)
  569.             {
  570.                 IntPtr hMode       = IntPtr.Zero;
  571.                 IntPtr hNames      = IntPtr.Zero;
  572.                 IntPtr hPageRanges = IntPtr.Zero;
  573.  
  574.                 if (Is64Bits())
  575.                 {
  576.                     NativeMethods.PRINTDLGEX64 pDlg = (NativeMethods.PRINTDLGEX64)Marshal.PtrToStructure(ptr, typeof(NativeMethods.PRINTDLGEX64));
  577.                     hMode = pDlg.hDevMode;
  578.                     hNames = pDlg.hDevNames;
  579.                     hPageRanges = pDlg.lpPageRanges;
  580.                 }
  581.                 else
  582.                 {
  583.                     NativeMethods.PRINTDLGEX32 pDlg = (NativeMethods.PRINTDLGEX32)Marshal.PtrToStructure(ptr, typeof(NativeMethods.PRINTDLGEX32));
  584.                     hMode       = pDlg.hDevMode;
  585.                     hNames      = pDlg.hDevNames;
  586.                     hPageRanges = pDlg.lpPageRanges;
  587.                 }
  588.  
  589.                 if (hMode != IntPtr.Zero)
  590.                     NativeMethods.GlobalFree(hMode);
  591.  
  592.                 if (hNames != IntPtr.Zero)
  593.                     NativeMethods.GlobalFree(hNames);
  594.  
  595.                 if (hPageRanges != IntPtr.Zero)
  596.                     NativeMethods.GlobalFree(hPageRanges);
  597.  
  598.                 Marshal.FreeHGlobal(ptr);
  599.             }
  600.         }
  601.        
  602.         /// <summary>
  603.         /// Get the PrintQueue from the PrinterName
  604.         /// </summary>
  605.         /// <param name="printerName"></param>
  606.         /// <returns></returns>
  607.         PrintQueue FindPrintQueue(string printerName)
  608.         {
  609.             EnumeratedPrintQueueTypes[] flag = new EnumeratedPrintQueueTypes[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections };
  610.             PrintQueueIndexedProperty[] pArray = new PrintQueueIndexedProperty[2];
  611.             pArray[1] = PrintQueueIndexedProperty.QueueAttributes;
  612.  
  613.             new PrintingPermission(PrintingPermissionLevel.DefaultPrinting).Assert();
  614.            
  615.             try
  616.             {
  617.                 using (LocalPrintServer s = new LocalPrintServer())
  618.                 {
  619.                     foreach (PrintQueue q in s.GetPrintQueues(pArray, flag))
  620.                     {
  621.                         if (printerName.Equals(q.FullName, StringComparison.OrdinalIgnoreCase))
  622.                         {
  623.                             q.InPartialTrust = true;
  624.                             return q;
  625.                         }
  626.                     }
  627.                 }                      
  628.             }
  629.             finally
  630.             {
  631.                 CodeAccessPermission.RevertAssert();
  632.             }
  633.  
  634.             return null;
  635.         }
  636.  
  637.         /// <summary>
  638.         /// Find the PrintTicket for the queue
  639.         /// </summary>
  640.         /// <param name="dModeHnd"></param>
  641.         /// <param name="printQueueName"></param>
  642.         /// <returns></returns>
  643.         PrintTicket FindPrintTicket(IntPtr dModeHnd, string printQueueName)
  644.         {
  645.             byte[] dModeBytes = null;
  646.             IntPtr ptr = IntPtr.Zero;
  647.  
  648.             try
  649.             {
  650.                 //Convert the native DevMode to a managed array of bytes
  651.                 ptr = NativeMethods.GlobalLock(dModeHnd);
  652.                 NativeMethods.DEVMODE dmode = (NativeMethods.DEVMODE)Marshal.PtrToStructure(ptr, typeof(NativeMethods.DEVMODE));
  653.                 dModeBytes = new byte[dmode.dmSize + dmode.dmDriverExtra];
  654.                 Marshal.Copy(ptr, dModeBytes, 0, dModeBytes.Length);
  655.             }
  656.             finally
  657.             {
  658.                 if (ptr != IntPtr.Zero)
  659.                     NativeMethods.GlobalUnlock(dModeHnd);
  660.             }
  661.  
  662.             new PrintingPermission(PrintingPermissionLevel.DefaultPrinting).Assert();
  663.            
  664.             try
  665.             {
  666.                 //Convert the bytes to a native PrintTicket
  667.                 using (PrintTicketConverter converter = new PrintTicketConverter(printQueueName, PrintTicketConverter.MaxPrintSchemaVersion))
  668.                 {
  669.                     return converter.ConvertDevModeToPrintTicket(dModeBytes);
  670.                 }
  671.             }
  672.             finally
  673.             {
  674.                 CodeAccessPermission.RevertAssert();
  675.             }
  676.         }
  677.  
  678.         /// <summary>
  679.         /// Creates DevMode structure from Ticket
  680.         /// </summary>
  681.         /// <param name="printerName"></param>
  682.         /// <param name="printTicket"></param>
  683.         /// <returns></returns>
  684.         IntPtr InitializeDevMode(string printerName, PrintTicket printTicket)
  685.         {
  686.             new PrintingPermission(PrintingPermissionLevel.DefaultPrinting).Assert();
  687.             byte[] dMode = null;
  688.            
  689.             try
  690.             {
  691.                 using (PrintTicketConverter converter = new PrintTicketConverter(printerName, PrintTicketConverter.MaxPrintSchemaVersion))
  692.                 {
  693.                     dMode = converter.ConvertPrintTicketToDevMode(printTicket, BaseDevModeType.UserDefault);
  694.                 }
  695.             }
  696.             finally
  697.             {
  698.                 CodeAccessPermission.RevertAssert();
  699.             }
  700.  
  701.             IntPtr ptrDevMode = Marshal.AllocHGlobal(dMode.Length);
  702.             Marshal.Copy(dMode, 0, ptrDevMode, dMode.Length);
  703.             return ptrDevMode;
  704.         }
  705.  
  706.         /// <summary>
  707.         /// Set DevName structure memory
  708.         /// </summary>
  709.         /// <param name="printerName"></param>
  710.         /// <returns></returns>
  711.         IntPtr InitializeDevNames(string printerName)
  712.         {
  713.             IntPtr ptrDevModeNames = IntPtr.Zero;
  714.             char[] strPrintName = printerName.ToCharArray();
  715.  
  716.             //Allocate native mem
  717.             ptrDevModeNames = Marshal.AllocHGlobal(((strPrintName.Length + 3) * Marshal.SystemDefaultCharSize) + Marshal.SizeOf(typeof(NativeMethods.DEVNAMES)));
  718.            
  719.             ushort sizeOfDevNames = (ushort)Marshal.SizeOf(typeof(NativeMethods.DEVNAMES));
  720.  
  721.             //Setup structure
  722.             NativeMethods.DEVNAMES names;
  723.             names.wDeviceOffset = (ushort)(sizeOfDevNames / Marshal.SystemDefaultCharSize);
  724.             names.wDriverOffset = (ushort)((names.wDeviceOffset + strPrintName.Length) + 1);
  725.             names.wOutputOffset = (ushort)(names.wDriverOffset + 1);
  726.             names.wDefault = 0;
  727.  
  728.             //Convert to native
  729.             Marshal.StructureToPtr(names, ptrDevModeNames, false);
  730.             IntPtr dst = (IntPtr)(((long)ptrDevModeNames) + sizeOfDevNames);
  731.             IntPtr dstOffset = (IntPtr)(((long)dst) + (strPrintName.Length * Marshal.SystemDefaultCharSize));
  732.            
  733.             byte[] array = new byte[3 * Marshal.SystemDefaultCharSize];
  734.             Array.Clear(array, 0, array.Length);
  735.  
  736.             //Copy strings
  737.             Marshal.Copy(strPrintName, 0, dst, strPrintName.Length);
  738.             Marshal.Copy(array, 0, dstOffset, array.Length);
  739.  
  740.             return ptrDevModeNames;
  741.         }
  742.  
  743.         /// <summary>
  744.         /// Get dwResultAction from Dlg
  745.         /// </summary>
  746.         /// <param name="ptrPrintDlg"></param>
  747.         /// <returns></returns>
  748.         uint GetResultPrintDlgExHnd(IntPtr ptrPrintDlg)
  749.         {
  750.             if (Is64Bits())
  751.             {
  752.                 NativeMethods.PRINTDLGEX64 dlg = (NativeMethods.PRINTDLGEX64)Marshal.PtrToStructure(ptrPrintDlg, typeof(NativeMethods.PRINTDLGEX64));
  753.                 return dlg.dwResultAction;
  754.             }
  755.             else
  756.             {
  757.                 NativeMethods.PRINTDLGEX32 dlg = (NativeMethods.PRINTDLGEX32)Marshal.PtrToStructure(ptrPrintDlg, typeof(NativeMethods.PRINTDLGEX32));
  758.                 return dlg.dwResultAction;
  759.             }
  760.         }
  761.  
  762.         /// <summary>
  763.         /// Get various settings
  764.         /// </summary>
  765.         /// <param name="nativeBuffer"></param>
  766.         /// <param name="printerName"></param>
  767.         /// <param name="flags"></param>
  768.         /// <param name="pageRange"></param>
  769.         /// <param name="dModeHnd"></param>
  770.         void GetSettings(IntPtr nativeBuffer, out string printerName, out uint flags, out PageRange pageRange, out IntPtr dModeHnd)
  771.         {
  772.             IntPtr dNames = IntPtr.Zero;
  773.             IntPtr pRanges = IntPtr.Zero;
  774.  
  775.             if (Is64Bits())
  776.             {
  777.                 NativeMethods.PRINTDLGEX64 dlg = (NativeMethods.PRINTDLGEX64)Marshal.PtrToStructure(nativeBuffer, typeof(NativeMethods.PRINTDLGEX64));
  778.                 dModeHnd = dlg.hDevMode;
  779.                 dNames = dlg.hDevNames;
  780.                 flags = dlg.Flags;
  781.                 pRanges = dlg.lpPageRanges;
  782.             }
  783.             else
  784.             {
  785.                 NativeMethods.PRINTDLGEX32 dlg = (NativeMethods.PRINTDLGEX32)Marshal.PtrToStructure(nativeBuffer, typeof(NativeMethods.PRINTDLGEX32));
  786.                 dModeHnd = dlg.hDevMode;
  787.                 dNames = dlg.hDevNames;
  788.                 flags = dlg.Flags;
  789.                 pRanges = dlg.lpPageRanges;
  790.             }
  791.  
  792.             if (((flags & 2) == 2) && (pRanges != IntPtr.Zero))
  793.             {
  794.                 NativeMethods.PRINTPAGERANGE printRange = (NativeMethods.PRINTPAGERANGE)Marshal.PtrToStructure(pRanges, typeof(NativeMethods.PRINTPAGERANGE));
  795.                 pageRange = new PageRange((int)printRange.nFromPage, (int)printRange.nToPage);
  796.             }
  797.             else
  798.             {
  799.                 pageRange = new PageRange(1);
  800.             }
  801.  
  802.             if (dNames != IntPtr.Zero)
  803.             {
  804.                 IntPtr ptrDevNames = IntPtr.Zero;
  805.                 try
  806.                 {
  807.                     ptrDevNames = NativeMethods.GlobalLock(dNames);
  808.                     NativeMethods.DEVNAMES devnames = (NativeMethods.DEVNAMES)Marshal.PtrToStructure(ptrDevNames, typeof(NativeMethods.DEVNAMES));
  809.                     printerName = Marshal.PtrToStringAuto((IntPtr)(((int)ptrDevNames) + (devnames.wDeviceOffset * Marshal.SystemDefaultCharSize)));
  810.                 }
  811.                 finally
  812.                 {
  813.                     if (ptrDevNames != IntPtr.Zero)
  814.                         NativeMethods.GlobalUnlock(dNames);
  815.                 }
  816.             }
  817.             else
  818.             {
  819.                 printerName = string.Empty;
  820.             }
  821.         }
  822.  
  823.         /// <summary>
  824.         /// Get's the result from the dialog
  825.         /// </summary>
  826.         /// <returns></returns>
  827.         uint GetResult()
  828.         {
  829.             if (mPrintDlgExHnd == IntPtr.Zero)
  830.                 return 0;
  831.  
  832.             uint result = GetResultPrintDlgExHnd(mPrintDlgExHnd);
  833.             if (result == 1 || result == 2)
  834.             {
  835.                 IntPtr dModePtr;
  836.                 string printerName;
  837.                 uint flags;
  838.                 PageRange range;
  839.  
  840.                 GetSettings(mPrintDlgExHnd, out printerName, out flags, out range, out dModePtr);
  841.  
  842.                 mDialogOwner.PrintQueue = FindPrintQueue(printerName);
  843.                 mDialogOwner.PrintTicket = FindPrintTicket(dModePtr, printerName);
  844.  
  845.                 if ((flags & 2) == 2)
  846.                 {
  847.                     if (range.PageFrom > range.PageTo)
  848.                     {
  849.                         int pageTo = range.PageTo;
  850.                         range.PageTo = range.PageFrom;
  851.                         range.PageFrom = pageTo;
  852.                     }
  853.  
  854.                     mDialogOwner.PageRangeSelection = PageRangeSelection.UserPages;
  855.                     mDialogOwner.PageRange = range;
  856.  
  857.                     return result;
  858.                 }
  859.  
  860.                 mDialogOwner.PageRangeSelection = PageRangeSelection.AllPages;
  861.             }
  862.  
  863.             return result;
  864.         }
  865.  
  866.         #endregion
  867.  
  868.         #region IDisposable
  869.         public void Dispose()
  870.         {
  871.             Dispose(true);
  872.             GC.SuppressFinalize(this);
  873.         }
  874.  
  875.         private void Dispose(bool disposing)
  876.         {
  877.             if (disposing && mPrintDlgExHnd != IntPtr.Zero)
  878.             {
  879.                 DeallocatePrintDlgExStruct(mPrintDlgExHnd);
  880.                 mPrintDlgExHnd = IntPtr.Zero;
  881.             }
  882.         }
  883.         #endregion
  884.     }
  885.     #endregion
  886. }
  887.  
  888. #region Native Method Wrappers
  889. /// <summary>
  890. /// Wrap PInvoke calls & structs
  891. /// </summary>
  892. internal static class NativeMethods
  893. {
  894.     #region Native Method Wrappers
  895.  
  896.     [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("kernel32.dll")]
  897.     internal static extern IntPtr GlobalFree(IntPtr hMem);
  898.  
  899.     [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("kernel32.dll")]
  900.     internal static extern IntPtr GlobalLock(IntPtr hMem);
  901.  
  902.     [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("kernel32.dll")]
  903.     internal static extern bool GlobalUnlock(IntPtr hMem);
  904.  
  905.     [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("comdlg32.dll", CharSet = CharSet.Auto)]
  906.     internal static extern int PrintDlgEx(IntPtr pdex);
  907.  
  908.     #endregion
  909.  
  910.     #region Native Type Wrappers
  911.  
  912.     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
  913.     internal struct DEVMODE
  914.     {
  915.         private const int CCHDEVICENAME = 0x20;
  916.         private const int CCHFORMNAME = 0x20;
  917.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
  918.         public string dmDeviceName;
  919.         public short dmSpecVersion;
  920.         public short dmDriverVersion;
  921.         public short dmSize;
  922.         public short dmDriverExtra;
  923.         public int dmFields;
  924.         public int dmPositionX;
  925.         public int dmPositionY;
  926.         public int dmDisplayOrientation;
  927.         public int dmDisplayFixedOutput;
  928.         public short dmColor;
  929.         public short dmDuplex;
  930.         public short dmYResolution;
  931.         public short dmTTOption;
  932.         public short dmCollate;
  933.         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
  934.         public string dmFormName;
  935.         public short dmLogPixels;
  936.         public int dmBitsPerPel;
  937.         public int dmPelsWidth;
  938.         public int dmPelsHeight;
  939.         public int dmDisplayFlags;
  940.         public int dmDisplayFrequency;
  941.         public int dmICMMethod;
  942.         public int dmICMIntent;
  943.         public int dmMediaType;
  944.         public int dmDitherType;
  945.         public int dmReserved1;
  946.         public int dmReserved2;
  947.         public int dmPanningWidth;
  948.         public int dmPanningHeight;
  949.     }
  950.  
  951.     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
  952.     internal struct DEVNAMES
  953.     {
  954.         public ushort wDriverOffset;
  955.         public ushort wDeviceOffset;
  956.         public ushort wOutputOffset;
  957.         public ushort wDefault;
  958.     }
  959.  
  960.     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
  961.     internal class PRINTDLGEX32
  962.     {
  963.         public int lStructSize = Marshal.SizeOf(typeof(NativeMethods.PRINTDLGEX32));
  964.         public IntPtr hwndOwner = IntPtr.Zero;
  965.         public IntPtr hDevMode = IntPtr.Zero;
  966.         public IntPtr hDevNames = IntPtr.Zero;
  967.         public IntPtr hDC = IntPtr.Zero;
  968.         public uint Flags;
  969.         public uint Flags2;
  970.         public uint ExclusionFlags;
  971.         public uint nPageRanges;
  972.         public uint nMaxPageRanges;
  973.         public IntPtr lpPageRanges = IntPtr.Zero;
  974.         public uint nMinPage;
  975.         public uint nMaxPage;
  976.         public uint nCopies;
  977.         public IntPtr hInstance = IntPtr.Zero;
  978.         public IntPtr lpPrintTemplateName = IntPtr.Zero;
  979.         public IntPtr lpCallback = IntPtr.Zero;
  980.         public uint nPropertyPages;
  981.         public IntPtr lphPropertyPages = IntPtr.Zero;
  982.         public uint nStartPage = uint.MaxValue;
  983.         public uint dwResultAction;
  984.     }
  985.  
  986.     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 8)]
  987.     internal class PRINTDLGEX64
  988.     {
  989.         public int lStructSize = Marshal.SizeOf(typeof(NativeMethods.PRINTDLGEX64));
  990.         public IntPtr hwndOwner = IntPtr.Zero;
  991.         public IntPtr hDevMode = IntPtr.Zero;
  992.         public IntPtr hDevNames = IntPtr.Zero;
  993.         public IntPtr hDC = IntPtr.Zero;
  994.         public uint Flags;
  995.         public uint Flags2;
  996.         public uint ExclusionFlags;
  997.         public uint nPageRanges;
  998.         public uint nMaxPageRanges;
  999.         public IntPtr lpPageRanges = IntPtr.Zero;
  1000.         public uint nMinPage;
  1001.         public uint nMaxPage;
  1002.         public uint nCopies;
  1003.         public IntPtr hInstance = IntPtr.Zero;
  1004.         public IntPtr lpPrintTemplateName = IntPtr.Zero;
  1005.         public IntPtr lpCallback = IntPtr.Zero;
  1006.         public uint nPropertyPages;
  1007.         public IntPtr lphPropertyPages = IntPtr.Zero;
  1008.         public uint nStartPage = uint.MaxValue;
  1009.         public uint dwResultAction;
  1010.     }
  1011.  
  1012.     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
  1013.     internal struct PRINTPAGERANGE
  1014.     {
  1015.         public uint nFromPage;
  1016.         public uint nToPage;
  1017.     }
  1018.  
  1019.     #endregion
  1020. }
  1021. #endregion
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement