Comparing Printer.PageSettings

Posted on 2008-11-10
Last Modified: 2012-08-14
Hello, Experts,

I have an application in which I have created a customized "Page Setup" form, but I have run into a performance issue.  When closing this form I want to compare the final PageSettings with the original PageSettings (saved when the form was opened).

I find that getting the various PageSettings properties to make this comparison is VERY slow.  The time required seems to depend on the particular property and also the selected printer, but runs into tenths of seconds per property, which is unacceptably long.

I have attached a snippet that illustrates the problem.

Any ideas on how I can improve the speed of these comparisons (or some other technique for making the comparison) will be greatly appreciated.

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        Dim prdTest As New PrintDocument()

        Debug.WriteLine(Now.ToString("HH:mm:ss.fff") & ": 1 (start)")

        Dim pgsTest As PageSettings = prdTest.DefaultPageSettings

        Dim strPrinterName As String = prdTest.PrinterSettings.PrinterName

        Dim datStart As Date = Now

        Dim intMyKind0 As Integer = pgsTest.PaperSource.RawKind

        Dim strMySourceName As String = pgsTest.PaperSource.SourceName

        Dim ppsMyPaperSource As PaperSource = pgsTest.PaperSource

        Dim intMyKind1 As Integer = ppsMyPaperSource.RawKind

        Dim prkMyKind As PrinterResolutionKind = pgsTest.PrinterResolution.Kind

        Dim datStop As Date = Now

        Debug.WriteLine("Time difference for " & strPrinterName & " = " & datStop.Subtract(datStart).ToString)

        ' Setting the Printer Name to itself improves speed slightly (~30%).

        prdTest.PrinterSettings.PrinterName = prdTest.PrinterSettings.PrinterName

        Dim datStart1 As Date = Now

        Dim intMyKind01 As Integer = pgsTest.PaperSource.RawKind

        Dim strMySourceName1 As String = pgsTest.PaperSource.SourceName

        Dim ppsMyPaperSource1 As PaperSource = pgsTest.PaperSource

        Dim intMyKind11 As Integer = ppsMyPaperSource.RawKind

        Dim prkMyKind1 As PrinterResolutionKind = pgsTest.PrinterResolution.Kind

        Dim datStop1 As Date = Now

        Debug.WriteLine("Time difference for " & strPrinterName & " = " & datStop1.Subtract(datStart1).ToString)

    End Sub

Open in new window

Question by:omegaomega
    LVL 96

    Expert Comment

    by:Bob Learned
    What kind of "comparison" are you talking about?  You might be able to create a custom print settings class that implements IComparable.
    LVL 12

    Author Comment

    Hi, Bob,

    Originally I thought that I wanted to do a "value equals" comparison (or Not Equals, actually) on the PageSettings properties that might be modified by the user through the Options/Printer Properties dialog that is accessed via the DocumentProperties API.  In particular, the following properties: Color, Landscape, Margins, PaperSize, PaperSource, PrinterResolution.  I also wanted to compare the modifiable properties of the PrinterSettings property, but this didn't seem to cause a performance problem.

    But now I see that each printer can also have its own specialized properties, and I should also be checking these.

    At the moment, I'm thinking that if I could compare the buffers returned by the PrinterSettings' GetHdevmode method that might provide a fast and complete comparison.  The two problems I am having with that are:
         - I don't know the final size of the buffers.
         - VB doesn't really seem to give me a convenient way to translate the pointer that is returned to a type (such as a byte array) that I can easily compare.
    I think that I can get the buffer's size from the DocumentProperties API.  Do you have any suggestions about how I can best compare the buffers in VB (when all I have are the pointers)?

    LVL 12

    Author Comment

    Hello, Experts,

    I believe that I have a workable solution using the techniques outlined in my previous post.   I have shown the essence of the solution in the attached snippet (untested).  

    CompareBuffers is a simple (unsafe) comparison function that I added to a pre-existing DLL used by the application.  I imagine that there must be some convenient API that would do this.  But I had trouble locating it and found it easier just to write my own.  If anyone can point me to that API, I'll allocate the question points for the reference.

        Private Declare Auto Function GlobalFree Lib "kernel32.dll" (ByVal handle As IntPtr) As IntPtr
        Private Declare Auto Function DocumentProperties Lib "winspool.drv" _
                        (ByVal hWnd As IntPtr, ByVal hPrinter As IntPtr, ByVal pDeviceName As String, _
                         ByVal pDevModeOutput As IntPtr, ByVal pDevModeInput As IntPtr, _
                         ByVal fMode As Int32) As Integer
        Private Function EquivalentPrinterSettings(ByVal PrinterSettings1 As PrinterSettings, _
                                                    ByVal PrinterSettings2 As PrinterSettings) As Boolean
            If (PrinterSettings1.PrinterName <> PrinterSettings2.PrinterName) Then Return False
            Dim iptDM1 As IntPtr
            Dim iptDM2 As IntPtr
                iptDM1 = PrinterSettings1.GetHdevmode(PrinterSettings1.DefaultPageSettings)
                iptDM2 = PrinterSettings2.GetHdevmode(PrinterSettings2.DefaultPageSettings)
                Dim BufferSize As Integer = DocumentProperties(IntPtr.Zero, IntPtr.Zero, _
                                                               PrinterSettings1.PrinterName, _
                                                               IntPtr.Zero, IntPtr.Zero, 0)
                Dim booEquivalent As Boolean = CompareBuffers(iptDM1, iptDM2, BufferSize)
                Return booEquivalent
            End Try
        End Function

    Open in new window

    LVL 96

    Accepted Solution

    If that works, go with it, because I don't have anything better, and I don't think any one will join in now.
    LVL 12

    Author Closing Comment

    Right again!  Thanks and cheers,

    Featured Post

    How to run any project with ease

    Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
    - Combine task lists, docs, spreadsheets, and chat in one
    - View and edit from mobile/offline
    - Cut down on emails

    Join & Write a Comment

    This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
    More often than not, we developers are confronted with a need: a need to make some kind of magic happen via code. Whether it is for a client, for the boss, or for our own personal projects, the need must be satisfied. Most of the time, the Framework…
    It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
    In this sixth video of the Xpdf series, we discuss and demonstrate the PDFtoPNG utility, which converts a multi-page PDF file to separate color, grayscale, or monochrome PNG files, creating one PNG file for each page in the PDF. It does this via a c…

    746 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    15 Experts available now in Live!

    Get 1:1 Help Now