7

在我的 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;
}

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

请问有什么建议吗?

4

8 回答 8

6

这对我有用:

将文档的打印控制器设置为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));
        }
    }
于 2009-09-01T08:22:05.567 回答
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

于 2014-10-17T18:04:28.430 回答
3

我想我做到了。使用此类而不是 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());
        }
    }
}
于 2016-12-16T16:03:09.517 回答
2

我讨厌回答我自己的问题,但解决方案正盯着我看。

由于我已经编写了打印交货单的功能,我的下一步是提供屏幕副本(即不打算打印硬拷贝)。打印预览对话框似乎是一个简单的出路。

最后,我只是创建了一个自定义表单并直接在上面绘制,看不到打印预览控件。

不幸的是,我太专注于试图让打印预览对话按照我的意愿行事,而不是着眼于更大的问题。

于 2009-10-11T09:55:15.403 回答
1

使用PreviewPrintController而不是 StandardPrintController可能会有一些运气。

于 2009-08-31T13:48:08.220 回答
1

对我有用的解决方案是使用Harmony (v1.2) 并修补上述ComputePreview功能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;
    }
}

要应用补丁,您需要在应用程序的启动中包含以下 2 行:

var harmony = Harmony.HarmonyInstance.Create("Application.Namespace.Reversed");
harmony.PatchAll(Assembly.GetExecutingAssembly());
于 2018-10-16T06:27:21.590 回答
0

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

如果您知道窗口的标题,以下是使用 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); 

}
于 2009-08-31T14:46:36.590 回答
0

似乎PrintPreviewControlused byPrintPreviewDialog将替换 the PrintControllerPrintDocument以便PrintControllerWithStatusDialog在预览渲染过程中使用 a 。Print操作完成后,将恢复PrintController到之前的值。似乎无法自定义PrintPreviewControl使用任何其他PrintController.

于 2012-05-24T09:34:31.040 回答