Как предотвратить появление диалогового окна «Ход печати» при предварительном просмотре печати - PullRequest
5 голосов
/ 31 августа 2009

В моем приложении 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 ]

6 голосов
/ 01 сентября 2009

Это работает для меня:

Установите для контроллера печати вашего документа значение 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));
        }
    }
3 голосов
/ 17 октября 2014

Просто чтобы подтвердить ответ от 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

2 голосов
/ 16 декабря 2016

Я думаю, что сделал это. Используйте этот класс вместо 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());
        }
    }
}
2 голосов
/ 11 октября 2009

Я не хочу отвечать на свой вопрос, но решение смотрело мне в лицо.

Поскольку я уже закодировал возможность распечатывать накладную, моим следующим шагом было предоставление экранной копии (то есть, нет намерения распечатывать бумажную копию). Диалог предварительного просмотра печати выглядел как легкий выход.

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

К сожалению, я слишком сосредоточился на попытке заставить диалог предварительного просмотра вести себя так, как я хотел, вместо того, чтобы смотреть на большую проблему.

1 голос
/ 31 августа 2009

Возможно, вам повезет с PreviewPrintController вместо StandardPrintController.

0 голосов
/ 16 октября 2018

Решение, которое работает для меня, заключается в использовании 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());
0 голосов
/ 24 мая 2012

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

0 голосов
/ 31 августа 2009

Обходной путь может заключаться в использовании API EnumChildWindows для поиска дескриптора окна, и, если он найден, используйте API ShowWindow с флагом 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); 

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...