PrintDialog.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / PrintDialog.cs / 1 / PrintDialog.cs

                            /*++ 

    Copyright (C) 2004 - 2005 Microsoft Corporation.
    All rights reserved.
 
    Module Name:
        PrintDialog.cs 
 
    Abstract:
        This file contains the implementation of the PrintDialog class 
        and its supporting enums.

    Author:
        [....] ([....]) 9-May-2005 

--*/ 
 
using System;
using System.Collections; 
using System.Collections.Generic;
using System.ComponentModel;
using System.Printing;
using System.Security; 
using System.Security.Permissions;
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Interop;
using System.Windows.Media; 
using System.Windows.Shapes;
using System.Windows.Xps;
using System.Xml;
using MS.Internal.Printing; 
using MS.Internal;
using System.Windows.Xps.Serialization; 
using System.Windows.Documents; 
using System.Windows.Documents.Serialization;  // WritingCompletedEventArgs
using System.Drawing.Printing; 


using MS.Internal.PresentationFramework;
 
namespace System.Windows.Controls
{ 
    ///  
    /// This class is used to show a print which will configure a
    /// user PrintTicket and Printer based on user input.  This 
    /// PrintTicket and Printer is then used to perform a print job.
    /// 
    public class PrintDialog
    { 
        #region Constructors
 
        ///  
        /// Instantiates an instance of the Print Dialog.
        ///  
        /// 
        ///     Critical:    - setting critical data (_printQueue, _printTicket, _dialogInvoked)
        ///     PublicOk:    - We are setting these to "known" values of null.  There
        ///                    is no data exposure here. 
        /// 
        [SecurityCritical] 
        public 
        PrintDialog(
            ) 
        {
            _dialogInvoked = false;

            _printQueue = null; 
            _printTicket = null;
 
            _isPrintableAreaWidthUpdated  = false; 
            _isPrintableAreaHeightUpdated = false;
 
            _pageRangeSelection = PageRangeSelection.AllPages;
            _minPage = 1;
            _maxPage = 9999;
            _userPageRangeEnabled = false; 
        }
 
        #endregion Constructors 

        #region Public properties 

        /// 
        /// Gets or Sets the PageRangeSelection option for the print dialog.
        ///  
        public PageRangeSelection PageRangeSelection
        { 
            get 
            {
                return _pageRangeSelection; 
            }
            set
            {
                _pageRangeSelection = value; 
            }
        } 
 
        /// 
        /// Gets or sets a PageRange objects used when the PageRangeSelection 
        /// option is set to UserPages.
        /// 
        public PageRange PageRange
        { 
            get
            { 
                return _pageRange; 
            }
            set 
            {
                if ((value.PageTo <= 0) || (value.PageFrom <= 0))
                {
                    throw new System.ArgumentException(SR.Get(SRID.PrintDialogInvalidPageRange), "PageRange"); 
                }
 
                _pageRange = value; 

                if (_pageRange.PageFrom > _pageRange.PageTo) 
                {
                    int temp = _pageRange.PageFrom;
                    _pageRange.PageFrom = _pageRange.PageTo;
                    _pageRange.PageTo = temp; 
                }
            } 
        } 

        ///  
        /// Gets or a sets a flag to enable/disable the user page range support on
        /// the print dialog.
        /// 
        public bool UserPageRangeEnabled 
        {
            get 
            { 
                return _userPageRangeEnabled;
            } 
            set
            {
                _userPageRangeEnabled = value;
            } 
        }
 
        // the following two properties return non CLS-compliant type UInt32 (bug 1788246) 
        #pragma warning disable 3003
 
        /// 
        /// Gets or sets the minimum page number allowed in the page ranges.
        /// 
        public UInt32 MinPage 
        {
            get 
            { 
                return _minPage;
            } 
            set
            {
                if (_minPage <= 0)
                { 
                    throw new System.ArgumentException(SR.Get(SRID.PrintDialogZeroNotAllowed, "MinPage"));
                } 
 
                _minPage = value;
            } 
        }

        /// 
        /// Gets or sets the maximum page number allowed in the page ranges. 
        /// 
        public UInt32 MaxPage 
        { 
            get
            { 
                return _maxPage;
            }
            set
            { 
                if (_maxPage <= 0)
                { 
                    throw new System.ArgumentException(SR.Get(SRID.PrintDialogZeroNotAllowed, "MaxPage")); 
                }
 
                _maxPage = value;
            }
        }
 
        #pragma warning restore 3003
 
        ///  
        /// Gets or sets the printer selection.
        ///  
        /// 
        ///     Critical:    - The getter is critical since it accesses critical data in web application mode.
        ///                  - The getter is calling critical code (AcquireDefaultPrintQueue).
        ///                  - The setter is critical since it is returning critical data. 
        ///     PublicOk:    - A demand is made for default printing before returning the print queue.  This
        ///                    would be the same permission required to get the print queue in the first place. 
        ///                  - We also demand before setting the print queue object.  If they can satisfy the 
        ///                    the demand then they are safe to print anyways.
        ///  
        public PrintQueue PrintQueue
        {
            [SecurityCritical]
            get 
            {
                SecurityHelper.DemandPrintDialogPermissions(); 
 
                if (_printQueue == null)
                { 
                    _printQueue = AcquireDefaultPrintQueue();
                }

                return _printQueue; 
            }
            [SecurityCritical] 
            set 
            {
                SecurityHelper.DemandPrintDialogPermissions(); 

                _printQueue = value;
            }
        } 

        ///  
        /// Get or sets the current PrintTicket object. 
        /// 
        ///  
        ///     Critical:    - The getter is critical since it accesses critical data.
        ///                  - The getter is calling critical code (AcquireDefaultPrintTicket).
        ///                  - The setter is critical since it is returning critical data.
        ///     PublicOk:    - A demand is made for default printing before returning the print ticket.  This 
        ///                    would be the same permission required to get the print ticket in the first place.
        ///                  - We also demand before setting the print ticket object.  If they can satisfy the 
        ///                    the demand then they are safe to print anyways. 
        /// 
        public PrintTicket PrintTicket 
        {
            [SecurityCritical]
            get
            { 
                SecurityHelper.DemandPrintDialogPermissions();
 
                if (_printTicket == null) 
                {
                    _printTicket = AcquireDefaultPrintTicket(this.PrintQueue); 
                }

                return _printTicket;
            } 
            [SecurityCritical]
            set 
            { 
                SecurityHelper.DemandPrintDialogPermissions();
 
                _printTicket = value;
            }
        }
 
        /// 
        /// Get the Width of the area on paper to which the application can print 
        ///  
        public
        double 
        PrintableAreaWidth
        {
            get
            { 
                if( ((_isPrintableAreaWidthUpdated == false) && (_isPrintableAreaHeightUpdated == false)) ||
                    ((_isPrintableAreaWidthUpdated == true)  && (_isPrintableAreaHeightUpdated == false))) 
                { 
                    _isPrintableAreaWidthUpdated  = true;
                    _isPrintableAreaHeightUpdated = false; 

                    UpdatePrintableAreaSize();
                }
 
                return _printableAreaWidth;
            } 
        } 

        ///  
        /// Get the Height of the area on paper to which the application can print
        /// 
        public
        double 
        PrintableAreaHeight
        { 
            get 
            {
                if( ((_isPrintableAreaWidthUpdated == false) && (_isPrintableAreaHeightUpdated == false)) || 
                    ((_isPrintableAreaWidthUpdated == false)  && (_isPrintableAreaHeightUpdated == true)))
                {
                    _isPrintableAreaWidthUpdated  = false;
                    _isPrintableAreaHeightUpdated = true; 

                    UpdatePrintableAreaSize(); 
                } 
                return _printableAreaHeight;
            } 
        }


        #endregion Public properties 

        #region Public methods 
 
        /// 
        /// Pops the dialog up to the user in a modal form. 
        /// 
        /// 
        ///     Critical:    - Accesses and sets critical data.
        ///     PublicOk:    - Data is internal to this dialog and can only be retrieved 
        ///                    by other critical code.  No information leaves this method.
        ///  
        [SecurityCritical] 
        public
        Nullable 
        ShowDialog()
        {
            //
            // Reset this flag as we have not displayed the dialog yet. 
            //
            _dialogInvoked = false; 
 
            Win32PrintDialog dlg = new Win32PrintDialog();
 
            //
            // Setup the old values if any exist.
            //
            dlg.PrintTicket = _printTicket; 
            dlg.PrintQueue = _printQueue;
            dlg.MinPage = Math.Max(1, Math.Min(_minPage, _maxPage)); 
            dlg.MaxPage = Math.Max(dlg.MinPage, Math.Max(_minPage, _maxPage)); 
            dlg.PageRangeEnabled = _userPageRangeEnabled;
            dlg.PageRange = new PageRange( 
                Math.Max((int)dlg.MinPage, _pageRange.PageFrom),
                Math.Min((int)dlg.MaxPage, _pageRange.PageTo));
            dlg.PageRangeSelection = _pageRangeSelection;
 
            //
            // Invoke the Win32 dialog 
            // 
            UInt32 dialogResult = dlg.ShowDialog();
 
            if ((dialogResult == MS.Internal.Printing.NativeMethods.PD_RESULT_APPLY) ||
                (dialogResult == MS.Internal.Printing.NativeMethods.PD_RESULT_PRINT))
            {
                _printTicket = dlg.PrintTicket; 
                _printQueue = dlg.PrintQueue;
                _pageRange = dlg.PageRange; 
                _pageRangeSelection = dlg.PageRangeSelection; 
                _dialogInvoked = true;
            } 

            return (dialogResult == MS.Internal.Printing.NativeMethods.PD_RESULT_PRINT);
        }
 
        /// 
        /// Prints a Visual to the currently selected Print Queue. 
        ///  
        /// 
        /// The visual to be printed. 
        /// 
        /// 
        /// Description of the job to be printed. This shows in the Printer UI
        ///  
        /// 
        ///     Critical:    - Sets a critical data property. 
        ///     PublicOk:    - The critical data is a flag that needs to be reset for each print 
        ///                    job to enforce the dialog invocation on every print operation.  Without
        ///                    this method resetting this flag we would not be honoring the security 
        ///                    goal of displaying the dialog once per print job.
        /// 
        [SecurityCritical]
        public 
        void
        PrintVisual( 
            Visual visual, 
            String description
            ) 
        {
            if (visual == null)
            {
                throw new ArgumentNullException("visual"); 
            }
 
            XpsDocumentWriter writer = CreateWriter(description); 

            writer.Write(visual); 

            _printableAreaWidth             = 0;
            _printableAreaHeight            = 0;
            _isPrintableAreaWidthUpdated    = false; 
            _isPrintableAreaHeightUpdated   = false;
            _dialogInvoked                  = false; 
        } 

 
        /// 
        /// Prints an DocumentPaginator based document to the currently selected Print Queue.
        /// 
        ///  
        /// The DocumentPaginator to be printed.
        ///  
        ///  
        /// Description of the job to be printed. This shows in the Printer UI
        ///  
        /// 
        ///     Critical:    - Sets a critical data property.
        ///     PublicOk:    - The critical data is a flag that needs to be reset for each print
        ///                    job to enforce the dialog invocation on every print operation.  Without 
        ///                    this method resetting this flag we would not be honoring the security
        ///                    goal of displaying the dialog once per print job. 
        ///  
        [SecurityCritical]
        public 
        void
        PrintDocument(
            DocumentPaginator  documentPaginator,
            String             description 
            )
        { 
            if (documentPaginator == null) 
            {
                throw new ArgumentNullException("documentPaginator"); 
            }

            XpsDocumentWriter writer = CreateWriter(description);
 
            writer.Write(documentPaginator);
 
            _printableAreaWidth = 0; 
            _printableAreaHeight = 0;
            _isPrintableAreaWidthUpdated = false; 
            _isPrintableAreaHeightUpdated = false;
            _dialogInvoked = false;
        }
 
        #endregion Public methods
 
        #region Private methods 

        ///  
        ///     Critical:    - Asserts to obtain the default print queue from the local server.
        /// 
        [SecurityCritical]
        private 
        PrintQueue
        AcquireDefaultPrintQueue() 
        { 
            PrintQueue printQueue = null;
 
            (new PrintingPermission(PrintingPermissionLevel.DefaultPrinting)).Assert(); //BlessedAssert
            try
            {
                try 
                {
                    LocalPrintServer server = new LocalPrintServer(); 
                    printQueue = server.DefaultPrintQueue; 
                }
                catch (PrintSystemException) 
                {
                    //
                    // It is entirely possible for there to be no "default" printer.  In this case,
                    // the printing system throws an exception.  We do not want this to propagate 
                    // up.  Instead, returning null is fine.
                    // 
                    printQueue = null; 
                }
            } 
            finally
            {
                PrintingPermission.RevertAssert();
            } 

            return printQueue; 
        } 

        ///  
        ///     Critical:    - Asserts to obtain the PrintTicket from the specified PrintQueue
        ///                    object or create a blank PrintTicket object (i.e. PrintTicket::ctor).
        /// 
        [SecurityCritical] 
        private
        PrintTicket 
        AcquireDefaultPrintTicket( 
            PrintQueue printQueue
            ) 
        {
            PrintTicket printTicket = null;

            (new PrintingPermission(PrintingPermissionLevel.DefaultPrinting)).Assert(); //BlessedAssert 
            try
            { 
                try 
                {
                    if (printQueue != null) 
                    {
                        printTicket = printQueue.UserPrintTicket;
                        if (printTicket == null)
                        { 
                            printTicket = printQueue.DefaultPrintTicket;
                        } 
                    } 
                }
                catch (PrintSystemException) 
                {
                    //
                    // The printing subsystem can throw an exception in certain cases when
                    // the print ticket is unavailable.  If it does we will handle this 
                    // below.  There is no real need to bubble this up to the application.
                    // 
                    printTicket = null; 
                }
            } 
            finally
            {
                PrintingPermission.RevertAssert();
            } 

            // 
            // If the printing subsystem could not give us a print ticket either due to 
            // a failure or because a user/system default was not available, then just
            // create a blank/empty one. 
            //
            if (printTicket == null)
            {
                printTicket = new PrintTicket(); 
            }
 
            return printTicket; 
        }
 
        /// 
        ///     Critical:    - Invokes a critical method (PickCorrectPrintingEnvironment).
        ///     TreatAsSafe: - Critical data returned from above method is internal and does
        ///                    not leave the scope of this method.  It is only used to calculate 
        ///                    non-critical values.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private
        void 
        UpdatePrintableAreaSize(
            )
        {
            PrintQueue  printQueue  = null; 
            PrintTicket printTicket = null;
 
            PickCorrectPrintingEnvironment(ref printQueue, ref printTicket); 

            PrintCapabilities printCap = null; 
            if (printQueue != null)
            {
                printCap = printQueue.GetPrintCapabilities(printTicket);
            } 

            // PrintCapabilities OrientedPageMediaWidth/Height are Nullable 
            if ((printCap != null) && 
                (printCap.OrientedPageMediaWidth != null) &&
                (printCap.OrientedPageMediaHeight != null)) 
            {
                _printableAreaWidth  = (double)printCap.OrientedPageMediaWidth;
                _printableAreaHeight = (double)printCap.OrientedPageMediaHeight;
            } 
            else
            { 
                // Initialize page size to portrait Letter size. 
                // This is our fallback if PrintTicket doesn't specify the page size.
                _printableAreaWidth = 816; 
                _printableAreaHeight = 1056;

                // PrintTicket's PageMediaSize could be null and PageMediaSize Width/Height are Nullable
 
                if ((printTicket.PageMediaSize != null) &&
                    (printTicket.PageMediaSize.Width != null) && 
                    (printTicket.PageMediaSize.Height != null)) 
                {
                    _printableAreaWidth  = (double)printTicket.PageMediaSize.Width; 
                    _printableAreaHeight = (double)printTicket.PageMediaSize.Height;
                }

                // If we are using PrintTicket's PageMediaSize dimensions to populate the widht/height values, 
                // we need to adjust them based on current orientation. PrintTicket's PageOrientation is Nullable.
                if (printTicket.PageOrientation != null) 
                { 
                    PageOrientation orientation = (PageOrientation)printTicket.PageOrientation;
 
                    // need to swap width/height in landscape orientation
                    if ((orientation == PageOrientation.Landscape) ||
                        (orientation == PageOrientation.ReverseLandscape))
                    { 
                        double t = _printableAreaWidth;
                        _printableAreaWidth  = _printableAreaHeight; 
                        _printableAreaHeight = t; 
                    }
                } 
            }
        }

        ///  
        ///     Critical:    - Asserts for PrintingPermissionLevel.DefaultPrinting
        ///                    to be able to use the printQueue to create the 
        ///                    XpsDocumentWriter. 
        ///     TreatAsSafe: - The assert is only done after ensuring that the user
        ///                    has conciously made a decision to print by successfully 
        ///                    dismissing the Print Dialog.  This logic of a dialog
        ///                    being required is only needed for partial trust applications.
        ///                    The logic of checking this criteria is contained within the
        ///                    PickCorrectPrintingEnvironment method. 
        ///                  - The XpsDocumentWriter instance returned from this method
        ///                    is not unsafe since the application is either full trust 
        ///                    or the user chose to print.  It is okay for the application 
        ///                    to use the XpsDocumentWriter to print at this point.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private
        XpsDocumentWriter
        CreateWriter( 
            String  description
            ) 
        { 
            PrintQueue        printQueue  = null;
            PrintTicket       printTicket = null; 
            XpsDocumentWriter writer      = null;

            PickCorrectPrintingEnvironment(ref printQueue, ref printTicket);
 
            (new PrintingPermission(PrintingPermissionLevel.DefaultPrinting)).Assert(); //BlessedAssert
            try 
            { 
                if(printQueue != null)
                { 
                    printQueue.CurrentJobSettings.Description = description;
                }

                writer = PrintQueue.CreateXpsDocumentWriter(printQueue); 

                PrintDlgPrintTicketEventHandler eventHandler = new PrintDlgPrintTicketEventHandler(printTicket); 
 
                writer.WritingPrintTicketRequired +=
                new WritingPrintTicketRequiredEventHandler(eventHandler.SetPrintTicket); 
            }
            finally
            {
                PrintingPermission.RevertAssert(); 
            }
 
            return writer; 
        }
 
        /// 
        ///     Critical:    - Accesses critical data and returns it to the caller.
        ///                  - Calls critical code (AcquireDefaultPrintQueue/AcquireDefaultPrintTicket)
        ///                  - Detects whether a caller is allowed to acquire this data 
        ///                    based on a demand.  This demand is only performed if the
        ///                    dialog was not invoked already.  It is fine to return the 
        ///                    data if the dialog was invoked, however, the data is still 
        ///                    critical.
        /// 
        /// NOTE:  This method validates that a dialog was invoked prior to returning the
        ///        PrintQueue and PrintTicket for the case of web applications.  If the
        ///        dialog was not invoked then an exception is thrown.
        ///  
        [SecurityCritical]
        private 
        void 
        PickCorrectPrintingEnvironment(
            ref PrintQueue  printQueue, 
            ref PrintTicket printTicket
            )
        {
            if (_dialogInvoked == false) 
            {
                // 
                // If the dialog has not been invoked then the user needs printing permissions. 
                // If the demand succeeds then they can print.  If the demand fails, then we
                // tell them that the print dialog must be displayed first by throwing a dialog 
                // exception.
                //
                try
                { 
                    SecurityHelper.DemandPrintDialogPermissions();
                } 
                catch (SecurityException) 
                {
                    throw new PrintDialogException(SR.Get(SRID.PartialTrustPrintDialogMustBeInvoked)); 
                }
            }

            // 
            // If the default print queue and print ticket have not already
            // been selected then update them now since we need them. 
            // 
            // NOTE:  If this code gets called then we know the dialog has never
            //        been invoked but the above demand was satisfied.  In this 
            //        case we want to just pickup the user defaults.
            //
            if (_printQueue == null)
            { 
                _printQueue = AcquireDefaultPrintQueue();
            } 
            if (_printTicket == null) 
            {
                _printTicket = AcquireDefaultPrintTicket(_printQueue); 
            }

            //
            // We should have valid print queue and print ticket objects to 
            // return now.  As a note, a null PrintQueue is valid for this
            // since the dialog will automatically pick up the user default 
            // printer for us. 
            //
            printQueue = _printQueue; 
            printTicket = _printTicket;
        }

        #endregion Private methods 

        #region Private data 
 
        /// 
        /// The PrintTicket is critical and not obtainable from a partial 
        /// trust application unless they can satisfy a printing permission
        /// demand.
        /// 
        [SecurityCritical] 
        private
        PrintTicket                 _printTicket; 
 
        /// 
        /// The PrintQueue is critical and not obtainable from a partial 
        /// trust application unless they can satisfy a printing permission
        /// demand.
        /// 
        [SecurityCritical] 
        private
        PrintQueue                  _printQueue; 
 
        /// 
        /// This variable is used to determine whether a user actually invoked 
        /// and dismissed the dialog prior to printing.  In a partial trust app,
        /// we can safely perform the necessary asserts to print as long as the
        /// user said printing was okay.
        ///  
        [SecurityCritical]
        private 
        bool                        _dialogInvoked; 

        private 
        PageRangeSelection          _pageRangeSelection;

        private
        PageRange                   _pageRange; 

        private 
        bool                        _userPageRangeEnabled; 

        private 
        UInt32                      _minPage;

        private
        UInt32                      _maxPage; 

        private 
        double                      _printableAreaWidth; 

        private 
        double                      _printableAreaHeight;

        private
        bool                        _isPrintableAreaWidthUpdated; 

        private 
        bool                        _isPrintableAreaHeightUpdated; 

        #endregion Private data 

        #region Internal classes

        internal class PrintDlgPrintTicketEventHandler 
        {
            #region Constructor 
 
            public
            PrintDlgPrintTicketEventHandler( 
                PrintTicket printTicket
                )
            {
                _printTicket = printTicket; 
            }
 
            #endregion Constructor 

            #region Public Methods 

            public
            void
            SetPrintTicket( 
                Object sender,
                WritingPrintTicketRequiredEventArgs args 
                ) 
            {
                if (args.CurrentPrintTicketLevel == PrintTicketLevel.FixedDocumentSequencePrintTicket) 
                {
                    args.CurrentPrintTicket = _printTicket;
                }
            } 

            #endregion Public Methods 
 
            #region Private Data
 
            private
            PrintTicket _printTicket;

            #endregion Private Data 
        };
 
        #endregion Internal classes 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK