如何在执行打印预览时阻止出现“打印进度”对话框

时间:2009-08-31 12:39:52

标签: c# .net printing system.drawing

在我的C#应用​​程序中,我正在尝试生成打印预览而屏幕上没有显示进度对话框。

我相信你可以使用PrintDocument.PrintController来打印真实的(即不是打印预览版),但是在执行打印预览时它似乎不起作用。

我的代码如下:

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;
}

除了显示打印预览进度对话框之外,打印预览完全按照我的要求工作。

建议吗?

8 个答案:

答案 0 :(得分:6)

这对我有用:

将文档的printcontroller设置为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));
        }
    }

答案 1 :(得分:3)

只是为了确认Pooven的答案。我有同样的问题并试图解决,Stefan的解决方案也没有对我有用。然后我终于查看了源代码并发现它是硬编码的,因此无法更改。如果需要隐藏状态对话框,请寻找除PrintPreviewControl之外的其他解决方案。这是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);
        }
    }

来源 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

答案 2 :(得分:2)

我不想回答我自己的问题,但是解决方案正在盯着我。

由于我已经编码了打印交货单的能力,我的下一步是提供屏幕上的复印件(即无意打印硬拷贝)。打印预览对话框似乎很简单。

最后,我刚创建了一个自定义表单并直接在其上绘制,没有打印预览控件。

不幸的是,我过于专注于尝试让打印预览对话按照我的意愿行事,而不是考虑更大的问题。

答案 3 :(得分:2)

我想我做到了。使用此类而不是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());
        }
    }
}

答案 4 :(得分:1)

您可能会对PreviewPrintController而不是StandardPrintController感到幸运。

答案 5 :(得分:0)

解决方法是使用EnumChildWindows API查找窗口的句柄,如果找到,请使用ShowWindow API和SW_HIDE标志来隐藏窗口。

如果你知道窗口的标题,这是一个使用FindWindow的例子:

#region Constants 

private const int SW_HIDE = 0;

private const int SW_SHOWNORMAL = 1;

private const int SW_SHOW = 5;

#endregion Constants

#region APIs

[System.Runtime.InteropServices.DllImport("user32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)] 

private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

[System.Runtime.InteropServices.DllImport("user32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)] 

private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow); 

[System.Runtime.InteropServices.DllImport("user32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)] 

private static extern bool EnableWindow(IntPtr hwnd, bool enabled);

#endregion APIs

public static void ShowProgress()

{

IntPtr h = FindWindow(null, "titleofprogresswindow");

ShowWindow(h, SW_SHOW); 

EnableWindow(h, true); 

}

public static void HideProgress()

{

IntPtr h = FindWindow(null, "titleofprogresswindow");

ShowWindow(h, SW_HIDE); 

EnableWindow(h, false); 

}

答案 6 :(得分:0)

似乎PrintPreviewControl使用的PrintPreviewDialog将替换PrintController的{​​{1}},以便在预览呈现过程中使用PrintDocument。完成PrintControllerWithStatusDialog操作后,Print将恢复为之前的值。似乎无法自定义PrintController以使用任何其他PrintPreviewControl

答案 7 :(得分:0)

一个对我有用的解决方案是使用Harmony(v1.2)并修补上述ComputePreview的{​​{1}}函数:

补丁类如下

PrintPreviewControl

要应用补丁,您需要在应用程序启动时包括以下两行:

[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;
    }
}