반응형

찰스 페졸드의 WPF 를 읽으면서 정리한 Banner 인쇄(PrintBanner) 소스.

 

[PrintBanner.cs 파일]

using System;
using System.Printing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace PrintBanner
{
    public class PrintBanner : Window
    {
        TextBox txtBox;

        [STAThread]
        public static void Main()
        {
            Application app = new Application();
            app.Run(new PrintBanner());
        }

        public PrintBanner()
        {
            Title = "Print Banner";
            SizeToContent = SizeToContent.WidthAndHeight;

            //윈도우 Content를 위한 스택 패널 생성
            StackPanel stack = new StackPanel();
            Content = stack;

            //텍스트 박스 생성
            txtBox = new TextBox();
            txtBox.Width = 250;
            txtBox.Margin = new Thickness(12);
            stack.Children.Add(txtBox);

            //버튼 생성
            Button btn = new Button();
            btn.Content = "_Print...";
            btn.Margin = new Thickness(12);
            btn.Click += PrintOnClick;
            btn.HorizontalAlignment = HorizontalAlignment.Center;
            stack.Children.Add(btn);

            txtBox.Focus();
        }

        private void PrintOnClick(object sender, RoutedEventArgs e)
        {
            PrintDialog dlg = new PrintDialog();

            if (dlg.ShowDialog().GetValueOrDefault())
            {
                //인쇄 방향이 수직인지 확인
                PrintTicket prnTkt = dlg.PrintTicket;
                prnTkt.PageOrientation = PageOrientation.Portrait;
                
                dlg.PrintTicket = prnTkt;

                //BannerDocumentPaginator 객체 생성
                BannerDocumentPaginator paginator = new BannerDocumentPaginator();

                //텍스트 박스로 Text 프로퍼티를 설정
                paginator.Text = txtBox.Text;

                //종이의 크기를 기반으로 PageSize 프로퍼티 설정
                paginator.PageSize = new Size(dlg.PrintableAreaWidth, dlg.PrintableAreaHeight);

                //Call PrintDocument to print the document
                dlg.PrintDocument(paginator, "Banner : " + txtBox.Text);
            }
        }
    }
}

 

[BannerDocumentPaginator.cs 파일]

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace PrintBanner
{
    public class BannerDocumentPaginator : DocumentPaginator
    {
        string txt = "";
        Typeface face = new Typeface("");
        Size sizePage;
        Size sizeMax = new Size(0, 0);

        //이 DocumentPaginator에 특화된 Public 프로퍼티
        public string Text
        {
            get { return txt; }
            set { txt = value; }
        }

        public Typeface Typeface
        {
            get { return face; }
            set { face = value; }
        }
        
        //FormattedText 객체를 생성하는 Private 함수
        FormattedText GetFormattedText(char ch, Typeface face, double em)
        {
            return new FormattedText(ch.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
                                    face, em, Brushes.Black);
        }

        //오버라이딩이 필요
        public override bool IsPageCountValid
        {
            get
            {
                //100em 사이즈를 기반으로 문자의 최대 크기를 결정
                foreach (char ch in txt)
                {
                    FormattedText formTxt = GetFormattedText(ch, face, 100);
                    sizeMax.Width = Math.Max(sizeMax.Width, formTxt.Width);
                    sizeMax.Height = Math.Max(sizeMax.Height, formTxt.Height);
                }
                return true;
            }
        }

        public override int PageCount
        {
            get { return txt == null ? 0 : txt.Length; }
        }

        public override Size PageSize
        {
            get { return sizePage; }
            set { sizePage = value; }
        }

        public override DocumentPage GetPage(int numPage)
        {
            DrawingVisual vis = new DrawingVisual();
            DrawingContext dc = vis.RenderOpen();

            //em 사이즈의 factor를 계산할 때 1/2인치 여백을 가정
            double factor = Math.Min((PageSize.Width - 96) / sizeMax.Width,
                                    (PageSize.Height - 96) / sizeMax.Height);

            FormattedText formTxt = GetFormattedText(txt[numPage], face, factor * 100);

            //페이지 중앙에 위치할 수 있게 좌표 계산
            Point ptText = new Point((PageSize.Width - formTxt.Width) / 2,
                                    (PageSize.Height - formTxt.Height) / 2);

            dc.DrawText(formTxt, ptText);
            dc.Close();

            return new DocumentPage(vis);
        }

        public override IDocumentPaginatorSource Source
        {
            get { return null; }
        }
    }
}

 

 

반응형

+ Recent posts