반응형
찰스 페졸드의 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;
}
}
}
}
반응형
'C# 개발 > WPF 관련 서적 예제' 카테고리의 다른 글
Charles Petzold의 WPF Chap. 01 - SayHello 예제 소스 (0) | 2021.09.04 |
---|---|
Charles Petzold의 WPF Chap. 17 - ChooseFont 예제 소스 (0) | 2021.09.03 |
Charles Petzold의 WPF Chap. 17 - PrintBanner 예제 소스 (0) | 2021.09.03 |
Charles Petzold의 WPF Chap. 17 - PrintaBunchaButtons 예제 소스 (0) | 2021.09.02 |
Charles Petzold의 WPF Chap. 17 - PrintEllipse 예제 소스 (0) | 2021.09.02 |