How can I prevent the Print Progress dialog appearing when performing a print preview

12,184

Solution 1

I hate to answer my own question, but the solution was staring me in the face.

As I've already coded the ability to print a delivery note, my next step was to provide an on screen copy (i.e. no intention of printing a hard copy). The print preview dialog seemed like an easy way out.

In the end, I just created a custom form and painted directly on to it with no print preview control in sight.

Unfortunately, I got too focused on trying to get the print preview dialogue to behave as I wanted, rather than looking at the bigger problem.

Solution 2

This works for me:

Set the printcontroller of your document to a StandardPrintController.

static class Program
    {

        static void Main()
        {
            PrintDocument doc = new PrintDocument();
            doc.PrintController = new StandardPrintController();
            doc.PrintPage += new PrintPageEventHandler(doc_PrintPage);

            doc.Print();
        }

        static void doc_PrintPage(object sender, PrintPageEventArgs e)
        {
            e.Graphics.DrawString("xxx", Control.DefaultFont, Brushes.Black, new PointF(e.PageBounds.Width / 2, e.PageBounds.Height / 2));
        }
    }

Solution 3

Just to confirm the answer from Pooven. I had the same problem and tried to solve, the solution from Stefan also did not worked from me. Then I finally looked in the source code and find out that it is hard coded so it cannot be changed. If you need to hide the status dialog, then seek for another solution than PrintPreviewControl. Here is the source code of the PrintPreviewControl.

 private void ComputePreview() {
        int oldStart = StartPage;

        if (document == null)
            pageInfo = new PreviewPageInfo[0];
        else {
            IntSecurity.SafePrinting.Demand();

            PrintController oldController = document.PrintController;

// --> HERE they have hardcoded it! Why they do this!

            PreviewPrintController previewController = new PreviewPrintController();
            previewController.UseAntiAlias = UseAntiAlias;
            document.PrintController = new PrintControllerWithStatusDialog(previewController,
                                                                           SR.GetString(SR.PrintControllerWithStatusDialog_DialogTitlePreview));

            // Want to make sure we've reverted any security asserts before we call Print -- that calls into user code
            document.Print();
            pageInfo = previewController.GetPreviewPageInfo();
            Debug.Assert(pageInfo != null, "ReviewPrintController did not give us preview info");

// --> and then swap the old one
            document.PrintController = oldController;
        }

        if (oldStart != StartPage) {
            OnStartPageChanged(EventArgs.Empty);
        }
    }

Source http://reflector.webtropy.com/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/fx/src/WinForms/Managed/System/WinForms/Printing/PrintPreviewControl@cs/1305376/PrintPreviewControl@cs

Solution 4

I think I did it. Use this class instead of PrintPreviewControl:

public class PrintPreviewControlSilent : PrintPreviewControl
{
    public new PrintDocument Document
    {
        get { return base.Document; }
        set
        {
            base.Document = value;

            PreviewPrintController ppc = new PreviewPrintController();

            Document.PrintController = ppc;
            Document.Print();

            FieldInfo fi = typeof(PrintPreviewControl).GetField("pageInfo", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            fi.SetValue(this, ppc.GetPreviewPageInfo());
        }
    }
}

Solution 5

A solution that works for me is to use Harmony (v1.2) and patch the ComputePreview function of the PrintPreviewControl mentioned above:

The patch class looks like this

[Harmony.HarmonyPatch(typeof(System.Windows.Forms.PrintPreviewControl))]
[Harmony.HarmonyPatch("ComputePreview")]
class PrintPreviewControlPatch
{
    static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
    {
        var cis = new List<CodeInstruction>(instructions);
        // the codes 26 to 28 deal with creating the
        // progress reporting preview generator that
        // we don't want. We replace them with No-Operation
        // code instructions. 
        cis[26] = new CodeInstruction(OpCodes.Nop);
        cis[27] = new CodeInstruction(OpCodes.Nop);
        cis[28] = new CodeInstruction(OpCodes.Nop);
        return cis;
    }
}

To apply the patch you need to include the following 2 lines in the startup of your application:

var harmony = Harmony.HarmonyInstance.Create("Application.Namespace.Reversed");
harmony.PatchAll(Assembly.GetExecutingAssembly());
Share:
12,184
Bryan
Author by

Bryan

Developer, Systems Admin, Geek, Gadget lover, etc. etc. I started programming in BASIC at the age of 11 on a Sinclair ZX81, advanced to a BBC Model B, where I learned 6502 assembly language programming. I never really worked with PCs until the early 90s. In the late 90s, I joined a higher educational institution as a desktop technician, a quickly got promoted to be a systems admin, working predominantly on Windows systems, but also had a keen interest in Linux systems. I later got involved in software development, working in C#, PHP, C. In my current employment, I'm the manager of the company's Information Systems department. The primary focus of our business is industrial control systems (mostly legacy systems). The work isn't exclusively legacy/control systems though, as we also support modern systems for a number of business customers. We're always on the lookout for staff who are interested in working with legacy/control systems. Experience or qualifications might help, but aren't always important. A geeky persona is essential though. If you think this would be interested please get in touch with me via our web site, or twitter.

Updated on June 15, 2022

Comments

  • Bryan
    Bryan almost 2 years

    In my C# application, I'm attempting to generate a print preview without the progress dialog appearing on screen.

    I believe you can use PrintDocument.PrintController to prevent this when printing for real (i.e. not a print preview), however it doesn't seem to work when performing a print preview.

    My code is as follows:

    public FrmDeliveryNotePrintPreview(DeliveryNote deliveryNote)
    {
        InitializeComponent();
    
        this.Text = "Delivery Note #" + deliveryNote.Id.ToString();
    
    
        // The print preview window should occupy about 90% of the
        // total screen height
    
        int height = (int) (Screen.PrimaryScreen.Bounds.Height * 0.9);
    
    
        // Making an assumption that we are printing to A4 landscape,
        // then adjust the width to give the correct height:width ratio
        // for A4 landscape.
    
        int width = (int) (height / 1.415);
    
    
        // Set the bounds of this form. The PrintPreviewControl is
        // docked, so it should just do the right thing
    
        this.SetBounds(0, 0, width, height);
    
        PrinterSettings printerSettings = new PrinterSettings();
        PrintDeliveryNotes pdn = new PrintDeliveryNotes(
            new DeliveryNote[] { deliveryNote },
            printerSettings);
        PrintDocument printDocument = pdn.PrintDocument;
        printDocument.PrintController = new PreviewPrintController();
        ppcDeliveryNote.Document = printDocument;
    }
    

    The print preview works exactly as I want, apart from the fact that the print preview progress dialog is displayed.

    Suggestions please?

  • Bryan
    Bryan over 14 years
    Yeah, however I've already tried that, and it still produces the progress dialog.
  • Bryan
    Bryan over 14 years
    I've updated the code sample to include the entire class as it currently stands.
  • AceJordin
    AceJordin over 12 years
    This worked for me, though I'm not doing a preview. See the Remarks here for the different PrintControllers available: msdn.microsoft.com/en-us/library/…. PrintController is a PrintControllerWithStatusDialog by default.
  • Xam
    Xam almost 4 years
    Since Winforms is now open source, it's possible to extract the code of the PrintPreviewControl and its dependencies to change its print controller.