이제 지금까지 만든 Paint 프로그램을 MDI 형태로 변경하고 인쇄 기능을 추가해보겠습니다.
MDI
C#에서 MDI는 일반적으로 제공하는 형태는 아닙니다. 그러나 편집기 등 MDI 형태가 필요한 프로그램 들이 있습니다. 이를 위해 간단히 작성 방법을 설명하겠습니다.
MDI를 구성하기 위해서는 MainForm외에 Form을 하나 만들어서 구성해주면 됩니다. 여기서는 C++구조와 비슷하게 ChildForm을 만든 후 PaintView를 만들어 그 위해 올려놓도록하겠습니다. PaintView를 Form으로 만들어 ChildForm 없이 구성해도 되나 향후 Internet Explore에 올리기 위해 두단계로 구성하여 만들도록 하겠습니다.
Paint 프로젝트에 아래와 같이 Windows Form을 추가하여 ChildForm으로 만듭니다.
또한 Paint 프로젝트에 아래와 같이 사용자 정의 컨트롤을 추가하여 ControlView로 만듭니다.
ChildForm을 다음과 같이 수정합니다.
public partial class ChildForm : Form
{
public ControlView controlView;
public ChildForm(MainForm mainForm, string strFile)
{
InitializeComponent();
this.controlView = new ControlView(mainForm, strFile);
this.controlView.Parent = this;
}
void SetViewSize()
{
if(this.controlView==null)
return;
this.controlView.Size = this.ClientSize;
}
private void ChildForm_Load(object sender, EventArgs e)
{
SetViewSize();
}
private void ChildForm_SizeChanged(object sender, EventArgs e)
{
SetViewSize();
}
}
MainForm.cs의 내용을 ControlView.cs에 복사하여 MainForm대신 ControlView로 수정한 후 컴파일하여 나타난 에러를 아래와 같이 수정합니다.
1. drawKindToolStripMenuItem_DropDownOpened 함수 및 PopupMenu_Opened함수 삭제
2. ShowToolbarStatus함수 내용 삭제
3. exitToolStripMenuItem_Click함수 삭제
4. MainForm에 선언된 enum DrawKind 삭제
또한 아래와같이 수정합니다.
1. MainForm으로 시작하는 모든 함수(4개)를 ControlView로 시작하도록 수정
2. this.drawKind를 this.mainForm.drawKind로 수정하고 MainForm의 drawKind를 public으로 변경
3. ControlView의 디자이너를 선택하여 속성에서 DoubleBuffered를 true로 선택합니다.
4. 또한 아래와 같이 속성의 이벤트 탭에서 MouseDown, MouseUp, Paint 이벤트를 연결 시킵니다.
5. 생성자의 인자에 MainForm과 strng를 넘겨 주도록 구성하여 아래와 같이 작성하고, 호출하는 부분도 맞추어 줍니다.
MainForm mainForm;
string strFile;
public ControlView(MainForm mainForm, string strFile)
{
InitializeComponent();
ShowToolbarStatus();
base.ResizeRedraw = true;
this.AutoScrollMinSize = this.imageSize;
this.mainForm = mainForm;
this.strFile = strFile;
if (string.IsNullOrEmpty(strFile) == false)
LoadReal(strFile);
}
6. ControlView_FormClosing함수를 아래와 같이 Close로 수정한다(bool로 리턴값있도록 수정).
MainForm mainForm;
string strFile;
public ControlView(MainForm mainForm, string strFile)
{
InitializeComponent();
ShowToolbarStatus();
base.ResizeRedraw = true;
this.AutoScrollMinSize = this.imageSize;
this.mainForm = mainForm;
this.strFile = strFile;
if (string.IsNullOrEmpty(strFile) == false)
LoadReal(strFile);
}
7. ControlView의 BackColor를 흰색으로 수정합니다.
8. MainForm의 IsMdiContainer를 true로 설정한 후 아래와 같이 CreateMdi라는 함수를 만들고 새파일과 열기 메뉴 이벤트 함수를 다음과 같이 수정합니다.
void CreateMdi(string strFile)
{
ChildForm childForm = new ChildForm(this, strFile);
childForm.MdiParent = this;
// childForm.WindowState = FormWindowState.Maximized;
childForm.Show();
}
private void newToolStripMenuItem_Click(object sender, EventArgs e)
{
CreateMdi("");
}
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "*.dat|*.dat";
if (dlg.ShowDialog() != DialogResult.OK)
return;
CreateMdi(dlg.FileName);
}
9. MainForm 생성자에 this.AutoScrollMinSize = this.imageSize;를 삭제합니다.
10. PaintView의 PaintView_FormClosing함수를 아래와 같이 수정합니다.
public bool Close()
{
if (!this.bModified)
return true;
DialogResult result = MessageBox.Show("변경된 내용을 저장할까요?", "Paint", MessageBoxButtons.YesNoCancel);
if (result == DialogResult.Cancel)
{
return false;
}
else if (result == DialogResult.No)
return true;
Save();
return true;
}
11. ChildForm에 FormClosing이벤트를 추가하여 다음과 같이 작성합니다.
private void ChildForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.controlView == null)
return;
if(this.controlView.Close()==false)
e.Cancel = true;
}
12. PaintView의 Save함수와 SaveAs함수를 public으로 선언하고, MainForm의 저장과 다른이름으로 저장 메뉴 이벤트를 다음과 같이 수정합니다.
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
ChildForm child = (ChildForm)this.ActiveMdiChild;
if (child == null)
return;
child.view.Save();
}
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
ChildForm child = (ChildForm)this.ActiveMdiChild;
if (child == null)
return;
child.view.SaveAs();
}
13. PaintView의 Export 메뉴 이벤트 함수를 다음과 같이 수정하고,
public void Export()
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "Image Files(*.bmp;*.gif;*.jpg)|*.bmp;*.gif;*.jpg";
if (dlg.ShowDialog() != DialogResult.OK)
return;
Bitmap bitmap = new Bitmap(imageSize.Width, imageSize.Height);
this.objList.Draw(Graphics.FromImage(bitmap));
bitmap.Save(dlg.FileName);
}
MainForm의 Export이벤트함수를 다음과 같이 수정합니다.
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
ChildForm child = (ChildForm)this.ActiveMdiChild;
if (child == null)
return;
child.view.Save();
}
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
ChildForm child = (ChildForm)this.ActiveMdiChild;
if (child == null)
return;
child.view.SaveAs();
}
14. MainForm에 계단식 배열과 바둑판식 배열 메뉴를 추가하여 그 이벤트에 다음과 같이 작성합니다.
private void ArrangeTileToolStripMenuItem_Click(object sender, EventArgs e)
{
LayoutMdi(MdiLayout.TileVertical);
}
private void ArrangeCascadeToolStripMenuItem_Click(object sender, EventArgs e)
{
LayoutMdi(MdiLayout.Cascade);
}
마지막으로 MainForm을 정리해보자(이작업은 하지 않아도 된다).
1. MainForm의 MouseDown, MouseUp, Paint, FormClosing 이벤트를 삭제합니다.
2. MainForm의 LoadReal, SaveReal, Save, SaveAs함수를 삭제합니다.
인쇄하기
ControlView의 디자이너에서 도구상자를 선택하여 PrintDocument와 PrintPreviewDialog, PrintDialog를 추가하여 printDoucment와 printPreviewDialog, printDialog로 만듭니다.
printDocument를 선택하여 PrintPage이벤트와 연결된 함수(printDocument_PrintPage)를 만듭니다.
또한 Print함수와 Preview함수를 만들어 아래와 같이 입력한다(using System.Drawing.Printing;를 추가해주어야 한다).
public void Print()
{
printDialog.AllowSomePages = true;
printDialog.ShowHelp = true;
printDialog.Document = printDocument;
if (printDialog.ShowDialog() != DialogResult.OK)
return;
printDocument.PrinterSettings = printDialog.PrinterSettings;
printDocument.DocumentName = "Viewer";
printDocument.Print();
}
public void PrintPreview()
{
printPreviewDialog.Document = printDocument;
printPreviewDialog.WindowState = FormWindowState.Maximized;
printPreviewDialog.ShowDialog();
}
private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Size size;
size = this.imageSize;
float fScale = Math.Min((float)e.MarginBounds.Width / (float)size.Width, (float)e.MarginBounds.Height / (float)size.Height);
Size sizeImg = new Size();
Point pt = new Point();
sizeImg.Width = (int)((float)size.Width * fScale);
sizeImg.Height = (int)((float)size.Height * fScale);
pt.X = (e.MarginBounds.Left + Math.Abs(e.MarginBounds.Width - sizeImg.Width)) / 2;
pt.Y = (e.MarginBounds.Top + Math.Abs(e.MarginBounds.Height - sizeImg.Height)) / 2;
e.Graphics.TranslateTransform(pt.X, pt.Y);
e.Graphics.ScaleTransform(fScale, fScale);
this.objList.Draw(e.Graphics);
}
MainForm의 메뉴에 인쇄와 미리보기 메뉴을 만들고, 이벤트 함수를 각각 만든후 아래와 같이 작성합니다.
private void PrintToolStripMenuItem_Click(object sender, EventArgs e)
{
ChildForm child = (ChildForm)this.ActiveMdiChild;
if (child == null)
return;
child.view.Print();
}
private void PreviewToolStripMenuItem_Click(object sender, EventArgs e)
{
ChildForm child = (ChildForm)this.ActiveMdiChild;
if (child == null)
return;
child.view.PrintPreview();
}
예제 프로그램 다운로드
'C#' 카테고리의 다른 글
C#12. Smart Client (0) | 2022.03.08 |
---|---|
C#11. DLL과 웹서비스 (0) | 2022.03.08 |
C#09. 파일 지원 (0) | 2022.03.08 |
C#08. 메모리, 마우스 및 스크롤 (0) | 2022.03.08 |
C#07. 대화상자 (0) | 2022.03.08 |