WPF Печать по размеру страницы - PullRequest
6 голосов
/ 28 октября 2011

Я искал варианты печати элементов управления WPF и нашел некоторые решения.Мне нужно подогнать свой печатный элемент управления к печати страницы, сохранив соотношение сторон (мой элемент управления квадратный; сетка судоку).

Я нашел решение, которое изменяет размеры и перемещает элемент управления под размер страницы.Это хорошо работает, но также перемещает этот элемент управления в моем окне.

Вот код, который я использую для печати и масштабирования:

        //get selected printer capabilities
            System.Printing.PrintCapabilities capabilities = dialog.PrintQueue.GetPrintCapabilities(dialog.PrintTicket);
        //get scale of the print wrt to screen of WPF visual
        double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / mrizka.ActualWidth, capabilities.PageImageableArea.ExtentHeight / mrizka.ActualHeight);

        //Transform the Visual to scale
        mrizka.LayoutTransform = new ScaleTransform(scale, scale);

        //get the size of the printer page
        Size sz = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);

        //update the layout of the visual to the printer page size.
        mrizka.Measure(sz);
        mrizka.Arrange(new Rect(new Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));

        dialog.PrintVisual(mrizka, mrizka.getID().ToString());

Я попробовал два подхода, чтобы решить эту проблему:

  1. Клонировать мой элемент управления и затем преобразовать клонированный, не влияя на оригинал.По какой-то причине это не сработало, я закончил с исключением: предоставленный объект DependencyObject не является контекстом для этой Freezable, но, как ни странно, только в некоторых случаях.

  2. Отмена изменения размера и положения.Я попытался вызвать метод InvalidateArrange (), который, казалось, работал, но только во время первого вызова метода print.Во время второго звонка это не сработало.

Что мне делать, пожалуйста, любые идеи <спасибо. </p>

Ответы [ 2 ]

23 голосов
/ 24 января 2012

Я знаю, что этот вопрос довольно старый, но я сам ищу решение этой проблемы.Вот решение, которое я сейчас использую.Я сохраняю исходное преобразование для элемента рамки и затем повторно применяю его после завершения печати. ​​

    private void Print(Visual v)
    {

        System.Windows.FrameworkElement e = v as System.Windows.FrameworkElement ;
        if (e == null)
            return;

        PrintDialog pd = new PrintDialog();
        if (pd.ShowDialog() == true)
        {
            //store original scale
            Transform originalScale = e.LayoutTransform;
            //get selected printer capabilities
            System.Printing.PrintCapabilities capabilities = pd.PrintQueue.GetPrintCapabilities(pd.PrintTicket);

            //get scale of the print wrt to screen of WPF visual
            double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / e.ActualWidth, capabilities.PageImageableArea.ExtentHeight /
                           e.ActualHeight);

            //Transform the Visual to scale
            e.LayoutTransform = new ScaleTransform(scale, scale);

            //get the size of the printer page
            System.Windows.Size sz = new System.Windows.Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);

            //update the layout of the visual to the printer page size.
            e.Measure(sz);
            e.Arrange(new System.Windows.Rect(new System.Windows.Point(capabilities.PageImageableArea.OriginWidth, capabilities.PageImageableArea.OriginHeight), sz));

            //now print the visual to printer to fit on the one page.
            pd.PrintVisual(v, "My Print");

            //apply the original transform.
            e.LayoutTransform = originalScale;
        }
    }
1 голос
/ 01 мая 2016
    private void DrawGrap_Click(object sender, RoutedEventArgs e)
    {
        // Visual v = sender as Visual;
        Visual v = song2Grid as Visual;   // the object (it is a DataGrid) that you want to print out, not a window
        PrintDialog prtDlg = new PrintDialog();
        if (prtDlg.ShowDialog() == true)
        {
            // because 96 pixels in an inch for WPF window
            double marginLeft = 96.0 * 0.75; // left margin is 0.75 inches
            double marginTop = 96.0 * 0.75; // top margin is 0.75 inches
            double marginRight = 96.0 * 0.75; // right margin is 0.75 inches
            double marginBottom = 96.0 * 0.75; // bottom margin is 0.75 inches

            // the following steps do not works for a WPF window
            FrameworkElement win = v as FrameworkElement;
            Transform oldLayoutTransform = win.LayoutTransform;
            Size oldSize = new Size(win.ActualWidth, win.ActualHeight);

            System.Printing.PrintCapabilities pCapability = prtDlg.PrintQueue.GetPrintCapabilities(prtDlg.PrintTicket);

            // calculate print area that you want
            double printWidth = (pCapability.PageImageableArea.ExtentWidth - pCapability.PageImageableArea.OriginWidth)
                                - (marginLeft + marginRight);
            double printHeight = (pCapability.PageImageableArea.ExtentHeight - pCapability.PageImageableArea.OriginHeight)
                - (marginTop + marginBottom);

            // calculate the scale
            double scale = Math.Min(printWidth / oldSize.Width , printHeight / oldSize.Height);
            if (scale > 1.0)
            {
                // keep the original size and layout if printable area is greater than the object being printed
                scale = 1.0; 
            }

            // store the original layouttransform
            win.LayoutTransform = new ScaleTransform(scale, scale);

            // new size of the visual
            Size newSize = new Size(oldSize.Width*scale , oldSize.Height*scale);
            win.Measure(newSize);

            // centralize print area
            double xStartPrint = marginLeft + (printWidth - newSize.Width)/2.0;
            double yStartPrint = marginTop + (printHeight - newSize.Height)/2.0;
            win.Arrange(new Rect(new Point(xStartPrint,yStartPrint),newSize));

            // print out the visual
            prtDlg.PrintVisual(win as Visual, "PrintTest");

            // resotre the original layouttransform and size on screen
            win.LayoutTransform = oldLayoutTransform;
            win.Measure(oldSize);
            win.Arrange(new Rect(new Point(0,0),oldSize));
        }
    }

Это был ответ на вопрос, заданный пользователем user1018711. Размещение распечатки на одной странице принтера с использованием C # и WPF. Когда вы хотите распечатать визуал, который может быть элементом управления, который может включать множество элементов управления (например, Button, DataGrid, TextBlock, Label и т. Д.). Здесь я хочу напечатать DataGrid с именем song2Drid на принтер, но его содержимое было больше, чем размер страницы принтера (его ширина была шире, чем ширина бумаги), поэтому он был обрезан. Я не мог видеть их все, поэтому мне пришлось масштабировать изображение, но я хотел, чтобы соотношение оставалось таким же, как и у старого.

Я также установил поля бумаги по 0,75 дюйма с каждой стороны листа, слева, сверху, справа и снизу. Я также централизовал визуальное содержание (song2Grid) на бумаге. Таким образом, я мог видеть напечатанный контент только по центру бумаги. Но если визуал представлял собой окно типа Application.Current.MainWindow или любое окно, созданное программно с помощью new Window (), то оно не будет масштабировано. это означало, что этот метод не будет работать для объекта Window.

Кроме того, если вы хотите восстановить исходный вид на экране из измененного путем масштабирования для печати, то вы должны иметь следующие утверждения win.LayoutTransform = oldLayoutTransform; win.Measure (oldSize); win.Arrange (new Rect (new Point (0,0), oldSize));

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