반응형

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

2개의 클래스 파일을 작성했으며, PrintWithMargins.cs 와 PageMarginsDialog.cs 파일로 구성된다.

 

[PrintWithMargins.cs 파일]

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace PrintWithMargins
{
    public class PageMarginsDialog : Window
    {
        //종이 테두리를 참조하는 내부 열거형
        enum Side
        {
            Left, Right, Top, Bottom
        }

        //숫자 입력을 위한 텍스트 박스 4개
        TextBox[] txtBox = new TextBox[4];
        Button btnOk;

        //페이지 여백을 위한 타입 Thickness의 Public 프로퍼티
        public Thickness PageMargins
        {
            set
            {
                txtBox[(int)Side.Left].Text = (value.Left / 96).ToString("F3");
                txtBox[(int)Side.Right].Text = (value.Right / 96).ToString("F3");
                txtBox[(int)Side.Top].Text = (value.Top / 96).ToString("F3");
                txtBox[(int)Side.Bottom].Text = (value.Bottom / 96).ToString("F3");
            }
            get
            {
                return new Thickness(Double.Parse(txtBox[(int) Side.Left].Text) * 96,
                                    Double.Parse(txtBox[(int)Side.Right].Text) * 96,
                                    Double.Parse(txtBox[(int)Side.Top].Text) * 96,
                                    Double.Parse(txtBox[(int)Side.Bottom].Text) * 96);
            }
        }

        //생성자
        public PageMarginsDialog()
        {
            //대화상자를 위한 표준 설정
            Title = "Page Setup";
            ShowInTaskbar = false;
            WindowStyle = WindowStyle.ToolWindow;
            WindowStartupLocation = WindowStartupLocation.CenterOwner;
            SizeToContent = SizeToContent.WidthAndHeight;
            ResizeMode = ResizeMode.NoResize;

            //윈도우 Content를 위한 스택 패널을 만든다.
            StackPanel stack = new StackPanel();
            Content = stack;

            //스택 패널의 자식으로 그룹 박스를 생성
            GroupBox grpBox = new GroupBox();
            grpBox.Header = "Margins (inches)";
            grpBox.Margin = new Thickness(12);
            stack.Children.Add(grpBox);

            //그룹 박스의 내용으로 그리드를 생성
            Grid grid = new Grid();
            grid.Margin = new Thickness(6);
            grpBox.Content = grid;

            //2개의 행과 4개의 열
            for (int i = 0; i < 2; i++)
            {
                RowDefinition rowDef = new RowDefinition();
                rowDef.Height = GridLength.Auto;
                grid.RowDefinitions.Add(rowDef);
            }

            for (int i = 0; i < 4; i++)
            {
                ColumnDefinition colDef = new ColumnDefinition();
                colDef.Width = GridLength.Auto;
                grid.ColumnDefinitions.Add(colDef);
            }

            //그리드에 레이블과 텍스트 박스 컨트롤을 추가
            for (int i = 0; i < 4; i++)
            {
                Label lbl = new Label();
                lbl.Content = "_" + Enum.GetName(typeof(Side), i) + ":";
                lbl.Margin = new Thickness(6);
                lbl.VerticalAlignment = VerticalAlignment.Center;
                grid.Children.Add(lbl);
                Grid.SetRow(lbl, i / 2);
                Grid.SetColumn(lbl, 2 * (i % 2));

                txtBox[i] = new TextBox();
                txtBox[i].TextChanged += TextBoxOnTextChanged;
                txtBox[i].MinWidth = 48;
                txtBox[i].Margin = new Thickness(6);
                grid.Children.Add(txtBox[i]);
                Grid.SetRow(txtBox[i], i / 2);
                Grid.SetColumn(txtBox[i], 2 * (i % 2) + 1);
            }

            //OK와 Cancel 버튼을 위해 UniformGrid를 이용
            UniformGrid uniGrid = new UniformGrid();
            uniGrid.Rows = 1;
            uniGrid.Columns = 2;
            stack.Children.Add(uniGrid);

            btnOk = new Button();
            btnOk.Content = "OK";
            btnOk.IsDefault = true;
            btnOk.IsEnabled = false;
            btnOk.MinWidth = 60;
            btnOk.Margin = new Thickness(12);
            btnOk.HorizontalAlignment = HorizontalAlignment.Center;
            btnOk.Click += OkButtonOnClick;
            uniGrid.Children.Add(btnOk);

            Button btnCancel = new Button();
            btnCancel.Content = "Cancel";
            btnCancel.IsCancel = true;
            btnCancel.MinWidth = 60;
            btnCancel.Margin = new Thickness(12);
            btnCancel.HorizontalAlignment = HorizontalAlignment.Center;
            uniGrid.Children.Add(btnCancel);
        }
        /// <summary>
        /// OK를 클릭하면 대화상자를 종료함
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OkButtonOnClick(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
        }
        /// <summary>
        /// 텍스트 박스의 값이 숫자이면 OK 버튼을 활성화
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TextBoxOnTextChanged(object sender, TextChangedEventArgs e)
        {
            double result;

            btnOk.IsEnabled = Double.TryParse(txtBox[(int)Side.Left].Text, out result) &&
                            Double.TryParse(txtBox[(int)Side.Right].Text, out result) &&
                            Double.TryParse(txtBox[(int)Side.Top].Text, out result) &&
                            Double.TryParse(txtBox[(int)Side.Bottom].Text, out result);
        }
    }
}

 

 

[PageMarginsDialog.cs 파일]

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

namespace PrintWithMargins
{
    public class PrintWithMargins : Window
    {
        //PringDialog의 정보를 저장하기 위한 Private 필드
        PrintQueue prnQueue;
        PrintTicket prnTkt;
        Thickness marginPage = new Thickness(96);

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

        public PrintWithMargins()
        {
            Title = "Print with Margins";
            FontSize = 24;

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

            //페이지 설정 버튼 생성
            Button btn = new Button();
            btn.Content = "Page Set_up...";
            btn.HorizontalAlignment = HorizontalAlignment.Center;
            btn.Margin = new Thickness(24);
            btn.Click += SetupOnClick;
            stack.Children.Add(btn);

            //인쇄 버튼 생성
            btn = new Button();
            btn.Content = "_Print...";
            btn.HorizontalAlignment = HorizontalAlignment.Center;
            btn.Margin = new Thickness(24);
            btn.Click += PrintOnClick;
            stack.Children.Add(btn);
        }
        /// <summary>
        /// 인쇄 버튼 : PringDialog 실행
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PrintOnClick(object sender, RoutedEventArgs e)
        {
            PrintDialog dlg = new PrintDialog();

            //PrintQueue와 PrintTicket 설정
            if (prnQueue != null) dlg.PrintQueue = prnQueue;

            if (prnTkt != null) dlg.PrintTicket = prnTkt;

            if (dlg.ShowDialog().GetValueOrDefault())
            {
                //PrintQueue와 PrintTicket을 대화상자의 값으로 설정
                prnQueue = dlg.PrintQueue;
                prnTkt = dlg.PrintTicket;

                //DrawingVisual을 생성하고 DrawingContext를 염
                DrawingVisual vis = new DrawingVisual();
                DrawingContext dc = vis.RenderOpen();
                Pen pen = new Pen(Brushes.Black, 1);

                //Rectangle은 여백을 뺀 페이지를 나타냄
                Rect rectPage = new Rect(marginPage.Left, marginPage.Top, 
                                         dlg.PrintableAreaWidth - (marginPage.Left + marginPage.Right), 
                                         dlg.PrintableAreaHeight - (marginPage.Top + marginPage.Bottom));

                //사용자 여백을 반영한 사각형 출력
                dc.DrawRectangle(null, pen, rectPage);

                //PrintableArea 프로퍼티를 보여주는 포맷팅된 텍스트 객체를 생성
                FormattedText formattedText = new FormattedText(String.Format("Hello, Printer! {0} x {1}",
                                                                dlg.PrintableAreaWidth / 96, dlg.PrintableAreaHeight / 96),
                                                                CultureInfo.CurrentCulture,
                                                                FlowDirection.LeftToRight,
                                                                new Typeface(new FontFamily("Times New Roman"), 
                                                                                FontStyles.Italic, FontWeights.Normal, FontStretches.Normal),
                                                                48, Brushes.Black);

                //포맷된 텍스트 스트링의 물리적 크기를 계산
                Size sizeText = new Size(formattedText.Width, formattedText.Height);

                //여백 내의 텍스트의 중앙점을 계산
                Point ptText = new Point(rectPage.Left + (rectPage.Width - formattedText.Width) / 2, 
                                         rectPage.Top + (rectPage.Height - formattedText.Height) / 2);

                //텍스트와 이를 둘러싸는 사각형 출력
                dc.DrawText(formattedText, ptText);
                dc.DrawRectangle(null, pen, new Rect(ptText, sizeText));

                //DrawingContext를 종료
                dc.Close();

                //끝으로 페이지를 인쇄
                dlg.PrintVisual(vis, Title);
            }
        }
        /// <summary>
        /// 페이지 설정 버튼 : PageMarginsDialog 실행
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SetupOnClick(object sender, RoutedEventArgs e)
        {
            //대화상자를 생성하고 PageMargins 프로퍼티를 초기화
            PageMarginsDialog dlg = new PageMarginsDialog();
            dlg.Owner = this;
            dlg.PageMargins = marginPage;

            if (dlg.ShowDialog().GetValueOrDefault())
            {
                //대화상자의 페이지 여백을 저장
                marginPage = dlg.PageMargins;
            }
        }
    }
}

 

 

 

반응형

+ Recent posts