Как мога да предотвратя показването на диалоговия прозорец за напредък на печата при извършване на визуализация за печат

В моето 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;
}

Визуализацията на печат работи точно както искам, с изключение на факта, че се показва диалоговият прозорец за напредъка на визуализацията на печат.

Моля за предложения?


person Bryan    schedule 31.08.2009    source източник
comment
PrintDeliveryNotes е клас, който отпечатва масив от бележки за доставка. В този случай обаче аз не извиквам метода Print(), вместо това просто извличам свойството PrintDocument и го предавам на моя PrintPreviewControl на потребителски формуляр.   -  person Bryan    schedule 31.08.2009


Отговори (8)


Това работи за мен:

Задайте контролера за печат на вашия документ на 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));
        }
    }
person Matt Jacobsen    schedule 01.09.2009
comment
Това работи за мен, въпреки че не правя предварителен преглед. Вижте забележките тук за различните налични PrintControllers: msdn. microsoft.com/en-us/library/. PrintController е PrintControllerWithStatusDialog по подразбиране. - person AceJordin; 17.11.2011

Само за да потвърдя отговора от Pooven. Имах същия проблем и се опитах да разреша, решението от Стефан също не работи от мен. След това най-накрая погледнах в изходния код и разбрах, че той е твърдо кодиран, така че не може да бъде променен. Ако трябва да скриете диалоговия прозорец за състояние, потърсете друго решение освен 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

person darpet    schedule 17.10.2014
comment
Тъй като Winforms вече е с отворен код, е възможно да се извлече кодът на PrintPreviewControl и неговите зависимости, за да се промени неговия контролер за печат. - person Xam; 22.07.2020

Мисля, че успях. Използвайте този клас вместо 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());
        }
    }
}
person Leszek Masłowski    schedule 16.12.2016

Мразя да отговарям на собствения си въпрос, но решението ме гледаше в очите.

Тъй като вече кодирах възможността за отпечатване на бележка за доставка, следващата ми стъпка беше да осигуря екранно копие (т.е. нямам намерение да отпечатвам хартиено копие). Диалоговият прозорец за визуализация на печат изглеждаше лесен изход.

В крайна сметка току-що създадох персонализиран формуляр и рисувах директно върху него, без да виждам контрол за предварителен преглед на печат.

За съжаление се съсредоточих твърде много върху опитите си да накарам диалоговия прозорец за предварителен преглед да се държи както искам, вместо да гледам по-големия проблем.

person Bryan    schedule 11.10.2009

Може да имате късмет с PreviewPrintController вместо StandardPrintController.

person Matt Jacobsen    schedule 31.08.2009
comment
Да, но вече опитах това и все още показва диалоговия прозорец за напредъка. - person Bryan; 31.08.2009
comment
Актуализирах примерния код, за да включва целия клас, както е в момента. - person Bryan; 31.08.2009

Решение, което работи за мен, е да използвам 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());
person FObermaier    schedule 16.10.2018

Заобиколно решение би било да се използва 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); 

}
person Stefan    schedule 31.08.2009

Изглежда, че PrintPreviewControl, използвано от PrintPreviewDialog, ще замени PrintController на PrintDocument, така че да използва PrintControllerWithStatusDialog по време на процеса на изобразяване на предварителен преглед. След като операцията Print бъде извършена, PrintController се възстановява до предишната си стойност. Изглежда, че няма да е възможно да персонализирате PrintPreviewControl да използва друг PrintController.

person Pooven    schedule 24.05.2012